皆様、こんにちは。y.kobayashiです。
今回は、TerraformとGitHub Actionsを組み合わせて、OCIへ自動デプロイする方法をご紹介します。
目次
はじめに
本記事では、TerraformとGitHub Actionsを組み合わせて、OCIへのインフラ構築を自動化する方法を解説します。
最終的には、GitHubリポジトリのmainブランチへコードをpushするだけで、GitHub ActionsがTerraformを実行し、OCI上にリソースが自動的に作成・更新される状態を目指します。
構成イメージ
全体の流れは次のとおりです。
本構成では、GitHubのmainブランチへコードをpushすると、それをトリガーにGitHub ActionsがTerraformを実行し、OCI上にリソースを作成・更新します。
tfstateはOCI Object Storageに保存し、チームやCI/CDから共有できるようにします。
前提
この記事を進めるにあたって、以下の環境が準備できていることを前提とします。
- OCIアカウント:テナンシーが作成済みで、コンソールログインできること
- OCIの権限:APIキーを作成でき、本記事で構築するリソース(VCN・サブネット・コンピュートなど)を作成・操作する権限を持っていること
- GitHubアカウント:リポジトリを作成し、GitHub Actionsを利用できること
- Terraform:ローカル端末にインストールしていること(本記事ではbackend "oci"を使用するため、バージョン1.12.0以上が必要です)
事前準備
OCIの認証情報を作成
TerraformがOCIのAPIを呼び出すために、以下の構成情報が必要になります。
| No | 項目 | 説明 |
|---|---|---|
| 1 | テナンシーOCID | 接続先のOCIテナンシーを特定する |
| 2 | ユーザーOCID | APIを実行するユーザーを指定する |
| 3 | フィンガープリント | 使用するAPIキーを特定する |
| 4 | 秘密鍵 | APIリクエストの署名に使用する |
これらの構成情報は、APIキーを作成する際に生成される「構成ファイルのプレビュー」からまとめて取得できます。
APIキーは、次の手順で作成します。
- OCI コンソール左上のユーザーアイコンをクリックし、「プロファイル」からユーザー名をクリックする
- 自分のプロファイルが開くので、「トークンおよびキー」タブに移り、「API キーの追加」をクリックする
- 秘密キーと公開キーのペアをダウンロードする(すでにキー・ペアがある場合は「公開キー・ファイルの選択」から公開キーをアップロードする)
- 「追加」をクリックする
- 「API キー 構成ファイルのプレビュー」が表示される
これらは後ほどGitHub Secretsに登録するので、メモしておきます。
APIキーの詳しい作成手順は、末尾の参考URLもあわせてご参照ください。
なお、秘密鍵のファイル自体はリポジトリにコミットしないよう注意してください。
コンパートメントOCIDの取得
リソースの作成先となるコンパートメントのOCIDを取得します。
OCI コンソールで「アイデンティティとセキュリティ」→「コンパートメント」を開き、対象のコンパートメントの詳細画面から OCID をコピーします。
GitHub Secretsの登録
GitHubリポジトリの「Settings」→「Secrets and variables」→「Actions」→「New repository secret」から、以下のSecretを登録します。
| No | Secret名 | 内容 |
|---|---|---|
| 1 | OCI_TENANCY | テナンシーのOCID |
| 2 | OCI_USER | ユーザーのOCID |
| 3 | OCI_FINGERPRINT | APIキーのフィンガープリント |
| 4 | OCI_PRIVATE_KEY | APIキーの秘密鍵(PEMの中身をそのまま貼り付け) |
| 5 | OCI_COMPARTMENT | コンパートメントのOCID |
※Secret名は任意ですが、Workflowファイル内の参照名(${{ secrets.xxx }}と一致させる必要があります。
名前を変更する場合はWorkflow側も合わせて修正してください。
Object Storageバケットの作成
OCIコンソールから、tfstate保存用のバケットを作成します。
Object Storageバケットの作成方法は以下のドキュメントをご参照ください。
その7 - オブジェクト・ストレージを使う | OCIチュートリアル
Terraformプロジェクトの準備
リポジトリのディレクトリ構成は次のようにします。
. ├── .github/ │ └── workflows/ │ └── terraform-deploy.yaml # GitHub Actions の Workflow ├── infra/ │ ├── provider.tf # Provider・Backend 設定 │ ├── availability_domains.tf # 可用性ドメインの取得 │ ├── compute.tf # コンピュートインスタンス定義 │ ├── network.tf # VCN・サブネットなどのネットワーク定義 │ └── variables.tf # 変数定義 └── .gitignore
Terraform関連のファイルはinfra/ディレクトリ配下にまとめます。
ローカルでのコマンド実行はinfra/に移動して行い、GitHub Actions側でも実行ディレクトリとしてinfra/を指定します。
.gitignoreには、ローカルのstateファイルなどが誤ってコミットされないよう、以下を追加しておきます。
.terraform *.tfstate *.tfvars tfplan *.pem
tfstateをOCI Object Storageで管理する
リモートバックエンドとは
リモートバックエンドとは、tfstate をローカルではなくリモートストレージサービスで管理する仕組みです。
Terraformは、管理しているリソースの状態をterraform.tfstateに記録し、このファイルはデフォルトではローカルに保存されます。
しかし、チーム開発では各メンバーがローカルにtfstateを持つと、同じインフラを管理していてもtfstateの内容に差異が生じます。
その結果、他のメンバーが作成したリソースが自分のtfstateに反映されず、存在しているはずのリソースがないものとして扱われるなど、不整合が発生する可能性があります。
そこで、tfstateはチーム全員とCI/CDが参照できる場所、リモートバックエンドに保存します。
OCIでは、Terraform 1.12で追加されたbackend "oci"を使用してObject Storageに保存します。
tfstateのロックにも対応しており、複数人や複数ジョブが同時にapplyした際の競合も防いでくれます。
バックエンド設定
provider.tf(または任意の.tfファイル)にOCIバックエンドの設定を記述します。
バケットには事前準備で作成したものを指定します。
terraform {
required_providers {
oci = {
source = "oracle/oci"
version = ">= 8.0.0"
}
}
backend "oci" {
bucket = "<作成したバケット名>"
namespace = "<tenancy-namespace>"
}
}
必須項目はbucketとnamespaceの2つです。
その他の項目は省略可能です。
たとえば、tfstateのファイル名を指定するkeyは省略した場合、ファイル名は「terraform.tfstate」になります。
なお、bucketやnamespaceなどの必須属性は環境変数で設定できないため、バックエンド設定ブロックに明示的に記述する必要があります。
TerraformでOCI環境構築
providerの設定
OCI Providerは、APIキー認証に必要な値が~/.oci/configから提供されていれば、providerブロックの記述は不要です。
そのため、本記事ではproviderブロックを定義せず、terraformブロックにrequired_providersとbackendの設定のみを記述しています。
リソースの作成
今回作成するリソースは、VCN・サブネットなどのネットワーク(network.tf)とコンピュートインスタンス(compute.tf)です。
すべて掲載すると長くなるため、ここでは一部抜粋して紹介します。
locals {
instance_shape = "VM.Standard.E5.Flex"
}
# プラットフォームイメージを動的に解決(リージョン差異の吸収と最新パッチの追随のため)
data "oci_core_images" "test_vm_image" {
compartment_id = var.compartment_id
operating_system = "Oracle Linux"
operating_system_version = "10"
shape = local.instance_shape
sort_by = "TIMECREATED"
sort_order = "DESC"
}
# テスト用VMインスタンス
resource "oci_core_instance" "test-vm" {
availability_domain = data.oci_identity_availability_domains.abs.availability_domains[0].name
compartment_id = var.compartment_id
shape = local.instance_shape
display_name = "test-vm"
create_vnic_details {
subnet_id = oci_core_subnet.public_subnet.id
assign_public_ip = true
nsg_ids = [oci_core_network_security_group.test_network_security_group.id]
}
source_details {
source_id = data.oci_core_images.test_vm_image.images[0].id
source_type = "image"
}
shape_config {
ocpus = 1
memory_in_gbs = 16
}
metadata = {
ssh_authorized_keys = file("${path.module}/ssh-key-2026-06-24.key.pub")
}
preserve_boot_volume = false
}
GitHub Actionsを設定する
Workflowファイルの作成
.github/workflows/terraform-deploy.yamlを作成します。
mainブランチへのpushをトリガーにTerraformを実行する構成です。
name: "terraform deploy"
on:
push:
branches:
- main
paths:
- "infra/**"
- ".github/workflows/**"
env:
TF_VERSION: 1.14.6
OCI_REGION: ap-tokyo-1
jobs:
deploy:
name: "Terraform Deploy"
runs-on: ubuntu-latest
env:
TF_VAR_compartment_id: ${{ secrets.OCI_COMPARTMENT }}
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: configure oci credentials
env:
OCI_USER: ${{ secrets.OCI_USER }}
OCI_TENANCY: ${{ secrets.OCI_TENANCY }}
OCI_FINGERPRINT: ${{ secrets.OCI_FINGERPRINT }}
OCI_PRIVATE_KEY: ${{ secrets.OCI_PRIVATE_KEY }}
run: |
mkdir -p ~/.oci
cat > ~/.oci/config << EOF
[DEFAULT]
user=${OCI_USER}
fingerprint=${OCI_FINGERPRINT}
tenancy=${OCI_TENANCY}
region=${OCI_REGION}
key_file=$HOME/.oci/key.pem
EOF
printf '%s' "${OCI_PRIVATE_KEY}" > ~/.oci/key.pem
chmod 600 ~/.oci/config ~/.oci/key.pem
- name: setup terraform
uses: hashicorp/setup-terraform@v4
with:
terraform_version: ${{ env.TF_VERSION }}
- name: terraform format
working-directory: infra
run: terraform fmt -check
- name: terraform init
working-directory: infra
run: terraform init
- name: terraform validate
working-directory: infra
run: terraform validate
- name: terraform plan
working-directory: infra
run: terraform plan -input=false -out=tfplan
- name: terraform apply
working-directory: infra
run: terraform apply -input=false tfplan
Jobの中では次のステップを実行します。
- リポジトリのチェックアウト
- OCI認証情報の設定
- Terraformのセットアップ
- コードフォーマットの検査
- Terraformの実行環境を初期化
- 構文・設定の妥当性チェック
- 変更内容の確認
- 変更の適用
自動デプロイを実行する
pushをトリガーにデプロイ
準備が整ったら、実際にコードをpushしてデプロイを実行してみます。
git add . git commit -m "<任意のコミットメッセージ>" git push origin main
Actionsの実行結果を確認
GitHubリポジトリの「Actions」タブを開くと、pushをトリガーにWorkflowが起動していることが確認できます。
ステータスが成功(緑のチェック)になっていれば成功です。
OCI側でリソース確認
最後に、OCIコンソールで実際にリソースが作成されていることを確認します。
Object Storageのバケットを開くとtfstateファイルが作成されていることも確認できます。
以降は、.tfファイルを変更してpushするだけで、インフラの変更が自動的に反映されます。
さいごに
本記事では、TerraformとGitHub Actionsを組み合わせ、pushするだけでOCIへ自動デプロイできる環境を構築する方法をご紹介しました。いかがでしたでしょうか。
tfstateをObject Storageで管理することで、Terraformの状態を安全に共有・管理できる構成としています。
本記事が、TerraformとGitHub Actionsを活用したOCI環境の構築・自動化の一助となれば幸いです。
参考
以下のドキュメントもあわせてご参照ください。
- APIキーの作成手順
https://docs.oracle.com/ja-jp/iaas/Content/API/Concepts/apisigningkey.htm
- tfstateバックエンドの設定リファレンス
https://developer.hashicorp.com/terraform/language/backend/oci



