はじめに
本記事では、CodexにTerraformの雛形作成を依頼し、OCIへ小規模な構成をデプロイした流れを紹介します。
- プライベートネットワーク上のOracle Base Database Service
- 疑似アプリケーション/監視処理を置く小さなComputeインスタンス
- ZRCVで使用する14日保持のProtection Policy
- Recovery Serviceの健全性アラームとOCI Notificationsトピック
構成
Cloud Shell / ローカル端末
│
│ Terraform + OCI API
▼
┌──────────────────── OCI VCN ────────────────────┐
│ │
│ App subnet (private) DB subnet (private) │
│ ┌────────────────────┐ ┌──────────────────┐ │
│ │ Compute │────► Oracle Base DB │ │
│ │ 1 OCPU / 6 GB │1521 │ 1 OCPU │ │
│ │ 疑似アプリ・監視用 │ │ Standard Edition │ │
│ └────────────────────┘ └─────────┬────────┘ │
│ │ │
│ Service Gateway │
└────────────────────────────────────────┼────────────┘
│
┌────────────────────────▼─────────────┐
│ Autonomous Recovery Service / ZRCV │
│ ・14日保持のProtection Policy │
│ ・後続で自動バックアップ先に設定 │
└──────────────────────────────────────┘
OCI Monitoring ──► OCI Notifications ──► メールなどの購読先
今回は検証用のため、ComputeとDBにはパブリックIPを割り当てません。
作成したリソース
| 種別 | 設定 | 目的 |
|---|---|---|
| VCN | 10.20.0.0/16 |
検証用ネットワーク |
| DBサブネット |
/27、プライベート |
Base DBとRecovery Service用のIP余裕を確保 |
| Appサブネット |
/28、プライベート |
疑似アプリ/監視処理用 |
| Compute |
VM.Standard.E5.Flex、1 OCPU、6 GB |
ログ生成や監視スクリプトの実行先 |
| Base DB |
VM.Standard.E5.Flex、1 OCPU、Standard Edition、単一ノード |
ZRCVの保護対象となる検証DB |
| ストレージ | 256 GB | VM DB System作成時の最小構成として指定 |
| Recovery Service Policy | 14日保持、Retention Lockなし | ZRCV検証用の最短保持ポリシー |
| Monitoring Alarm | ProtectedDatabaseHealth |
Recovery Serviceの保護状態を通知 |
| Notifications | トピックとメール購読 | アラームの受け取り先 |
前提条件
- OCIユーザーに、対象コンパートメントでCompute、Network、Database、Recovery Service、Monitoring、Notificationsを操作する権限があること
- OCI API Keyを作成済みであること
- Terraform 1.12以降
- SSH公開鍵
- DB管理者パスワード
Codexに依頼したプロンプト
まずは、構成と制約を明示してTerraformを作らせました。
OCIのSan Joseリージョンに、TerraformでZRCV検証用の最小環境を作成してください。
- ComputeはVM.Standard.E5.Flex、1 OCPU、メモリ6GB
- Oracle Base Database ServiceはVM.Standard.E5.Flex、1 OCPU、Standard Edition、単一ノード
- ComputeとDBは別のプライベートサブネットに置く
- ComputeからDBへのTCP 1521だけをNSGで許可する
- Service Gatewayを使い、パブリックIPとNAT Gatewayは作らない
- Recovery Serviceの14日保持Protection Policyを作る
- Recovery ServiceのProtectedDatabaseHealthをNotificationsトピックへ通知する
- API Key、OCID、メールアドレス、パスワードをソースに直書きしない
- terraform.tfvarsを.gitignoreへ追加する
- terraform fmt、terraform validate、terraform planで検証する
ディレクトリ構成
zrcv-recovery-demo/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── terraform.tfvars
└── .gitignore
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.*
terraform.tfvars
terraform.tfstateにはパスワードなどの情報を含み得るので注意。
Terraformの主要部分
Providerと変数
terraform {
required_version = ">= 1.12.0"
required_providers {
oci = {
source = "oracle/oci"
version = "~> 8.27"
}
}
}
provider "oci" {
tenancy_ocid = var.tenancy_ocid
user_ocid = var.user_ocid
fingerprint = var.fingerprint
private_key_path = var.private_key_path
region = "us-sanjose-1"
}
variable "db_admin_password" {
type = string
sensitive = true
}
terraform.tfvarsは次のようにします。値はすべて例です。
tenancy_ocid = "ocid1.tenancy.oc1..example"
compartment_ocid = "ocid1.compartment.oc1..example"
user_ocid = "ocid1.user.oc1..example"
fingerprint = "aa:bb:cc:dd:ee:ff"
private_key_path = "/secure/path/oci_api_key.pem"
ssh_public_key_path = "/secure/path/id_rsa.pub"
notification_email = "your-address@example.com"
db_admin_password = "replace-with-a-strong-password"
ネットワークとNSG
DB接続は、App用NSGからDB用NSGへのTCP 1521に限定します。
resource "oci_core_network_security_group_security_rule" "app_to_db" {
network_security_group_id = oci_core_network_security_group.db.id
direction = "INGRESS"
protocol = "6" # TCP
source = oci_core_network_security_group.app.id
source_type = "NETWORK_SECURITY_GROUP"
stateless = false
tcp_options {
destination_port_range {
min = 1521
max = 1521
}
}
}
DBサブネットはRecovery Serviceも考慮して/27にしました。
Recovery Serviceでは、DBとRecovery Service間の通信にTCP 8005と2484を使います。
NSGやセキュリティリストを明示的に絞り込む場合は、これらの通信も許可します
Compute
resource "oci_core_instance" "sentinel" {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
compartment_id = var.compartment_ocid
display_name = "zrcv-demo-sentinel"
shape = "VM.Standard.E5.Flex"
create_vnic_details {
subnet_id = oci_core_subnet.app.id
assign_public_ip = false
nsg_ids = [oci_core_network_security_group.app.id]
}
shape_config {
ocpus = 1
memory_in_gbs = 6
}
source_details {
source_type = "image"
source_id = data.oci_core_images.oracle_linux.images[0].id
}
}
Base Database Service
resource "oci_database_db_system" "demo" {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
compartment_id = var.compartment_ocid
display_name = "zrcv-demo-basedb"
hostname = "zrcvdemodb"
shape = "VM.Standard.E5.Flex"
cpu_core_count = 1
data_storage_size_in_gb = 256
database_edition = "STANDARD_EDITION"
license_model = "LICENSE_INCLUDED"
node_count = 1
subnet_id = oci_core_subnet.db.id
nsg_ids = [oci_core_network_security_group.db.id]
ssh_public_keys = [file(var.ssh_public_key_path)]
db_system_options {
storage_management = "LVM"
}
db_home {
db_version = var.db_version
is_unified_auditing_enabled = false
database {
admin_password = var.db_admin_password
db_name = "ZRCVDEMO"
db_workload = "OLTP"
pdb_name = "ZRCVPDB"
}
}
}
DBバージョンは変数にし、対象リージョンで使える値を指定します。
variable "db_version" {
type = string
default = "19.32.0.0" # 例。リージョンごとに要確認
}
Recovery ServiceのProtection Policy
検証環境なので14日保持、Retention Lockなしにしています。
Retention Lockが有効になると保持設定を戻せないため、短期間で破棄する検証用途では慎重に扱う必要あり
resource "oci_recovery_protection_policy" "demo" {
compartment_id = var.compartment_ocid
display_name = "zrcv-demo-14d-policy"
backup_retention_period_in_days = 14
}
RSを選ぶには、同じVCNにACTIVEなSubnetが必要です。
これがない場合、UpdateDatabaseは409 IncorrectStateで失敗します。
resource "oci_recovery_recovery_service_subnet" "demo" {
compartment_id = var.compartment_ocid
display_name = "zrcv-demo-recovery-service-subnet"
vcn_id = oci_core_vcn.demo.id
subnets = [oci_core_subnet.db.id]
nsg_ids = [oci_core_network_security_group.db.id]
}
DB作成後、次の設定を追加して自動バックアップ先をRecovery Serviceに切り替えます。
db_backup_config {
auto_backup_enabled = true
backup_destination_details {
# OCI Database APIでRecovery Serviceを表す列挙値はDBRS
type = "DBRS"
dbrs_policy_id = oci_recovery_protection_policy.demo.id
is_zero_data_loss_enabled = true
backup_retention_policy_on_terminate = "RETAIN_PER_RETENTION_WINDOW"
}
}
typeはコンソールの表示名ではなく、OCI Database APIの列挙値であるDBRSを指定します。RECOVERY_SERVICEを渡すとUpdateDatabaseが400 InvalidParameterで失敗しました。
今回はDB作成後にこのブロックを適用しました。
is_zero_data_loss_enabled = trueはreal-time redo保護の指定で、追加料金が発生し得ます。
検証終了時の保持はProtection Policyに従うようRETAIN_PER_RETENTION_WINDOWを指定しています。
MonitoringとNotifications
resource "oci_monitoring_alarm" "recovery_health" {
compartment_id = var.compartment_ocid
display_name = "zrcv-demo-protected-database-health"
metric_compartment_id = var.compartment_ocid
namespace = "oci_recovery_service"
query = "ProtectedDatabaseHealth[1m].max() >= 1"
severity = "WARNING"
destinations = [oci_ons_notification_topic.incident.id]
is_enabled = true
}
メール購読は、作成後にOCIから届く確認メールを承認するまで有効になりません。
デプロイ手順
terraform init
terraform fmt -check
terraform validate
terraform plan -out tfplan
terraform apply tfplan
planで、特に次を確認してからapplyします。
- リージョンが意図したものか
- Computeが1 OCPU/6 GBか
- DBが1 OCPU、Standard Edition、単一ノードか
- パブリックIPが
falseか - DBストレージとRecovery Serviceの保持期間が想定どおりか
- 意図しない既存リソースの変更・削除が含まれていないか
ZRCV設定の検証
terraform applyが成功しても、Protection Policyが存在するだけでは不十分です。
Base DBがRecovery ServiceのProtected Databaseとして登録され、ポリシーとredo出荷の状態を取得して確認します。
Codexには次のように依頼しました。
ZRCVを有効化した後、OCI APIの参照系コマンドで検証してください。
DBの自動バックアップ先、Recovery ServiceのProtected Database、
Protection Policy、is_redo_logs_shippedを確認し、秘密情報・OCIDは出力しないでください。
Terraform Providerから確認する場合は、次のデータソースを一時的に追加してterraform planを実行できます。検証後はこのファイルを削除して構いません。
data "oci_recovery_protected_databases" "verify" {
compartment_id = var.compartment_ocid
}
output "zrcv_verify" {
value = [for db in data.oci_recovery_protected_databases.verify.protected_database_collection[0].items : {
state = db.state
health = db.health
redo_logs_shipped = db.is_redo_logs_shipped
protection_policy = db.protection_policy_id
}]
}
OCI CLIを利用できる場合の同等コマンドは以下です。
# Base DBのバックアップ設定(database-idは環境の値に置き換える)
oci db database get --database-id "$DATABASE_OCID" \
--query 'data."db-backup-config"'
# Recovery Serviceに登録された保護対象DB
oci recovery protected-database-collection list-protected-databases \
--compartment-id "$COMPARTMENT_OCID"
# Recovery Serviceが利用するサブネット
oci recovery recovery-service-subnet-collection list-recovery-service-subnets \
--compartment-id "$COMPARTMENT_OCID"
今回の適用直後の実測では、DBRS設定とRecovery Service Subnetの作成は成功し、Recovery Service Subnetは1件でした。
一方、Protected Databaseは0件でした。初回バックアップ・サービス側登録は非同期なので、Protected Databaseがまだ0件なら、設定失敗と即断せずしばらく待って再実行します。
確認条件は、auto_backup_enabled=true、バックアップ先のtype=DBRS、対象Protection Policyの紐付け、Protected Databaseのstateとhealthが正常であることです。is_redo_logs_shipped=trueはreal-time redo保護の確認項目です。
まとめ
Codexに構成条件と安全上の制約を明示すると、OCI向けTerraformの雛形作成、変数の分離、fmt/validate/planによる検証までを短時間で進められました。
- 私用情報や秘密情報をTerraform本体から分離できた
- Compute、Base DB、Recovery Service Policy、監視通知をコード化できた
- 他の環境でも変数を差し替えて追試できる形にできた
