0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CodexでTerraform作成 -> OCIに検証環境を速攻デプロイする

0
Posted at

はじめに

本記事では、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 ──► メールなどの購読先

image.png
↑ こちらもcodexで作成

今回は検証用のため、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、監視通知をコード化できた
  • 他の環境でも変数を差し替えて追試できる形にできた
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?