見出し画像

CDK for Terraformでimport機能がリリースされたので試してみた



概要

CDKTFネタ第2弾です。
CDKTF 0.19 から待望のimportやmoveがサポートされるようになったので試してみたいと思います。importからのコード生成やリソースの移動もできるようになってますが、今回はimportのみ。


初期設定

をベースに進めます。今回はmoduleは利用しないので設定は不要です。ただ、今回はtfstateの管理をS3で行う設定で行います。

検証で利用するAuroraはマネージメントコンソールから作成する時にデフォルト指定でできるものを利用します。データベースエンジンはpostgres互換

AuroraCluster: database-1
AuroraClusterInstance: database-1-instance-1 
  • cdktf.json
    tfstate ファイルを管理するS3バケットは予め作成しておき、bucketに指定する。 auroraClusterIdは作成したAuroraClusterのIDを指定。projectNameも適宜変更。
    tfstate ファイルは 以下のようなパスで管理されるようになります。
    XXXXXXXXXXXXXXXXXXXXXXXXXX-terraformstate-bucket/sample/terraform.tfstate

{
  "language": "typescript",
  "app": "npx ts-node main.ts",
  "projectId": "f6bb6b84-3ff3-484f-9620-f031d4666947",
  "sendCrashReports": "false",
  "terraformProviders": [
    "hashicorp/aws@~>4.0"
  ],
  "terraformModules": [],
  "context": {},
  "terraformBackend": {
    "s3": {
      "bucket": "XXXXXXXXXXXXXXXXXXXXXXXXXX-terraformstate-bucket",
      "key": "terraform.tfstate",
      "region": "ap-northeast-1",
      "encrypt": true
    }
  },
  "projectName": "sample",
  "rdsConfig": {
    "auroraClusterId": "database-1",
    "engine": "aurora-postgresql",
    "instanceClass": "db.t4g.medium"
  }
}
  • main.ts
    defaultTagsなどは独自で設定してあるので、適宜環境に合わせてカスタマイズ 特に MyStack の第2引数で指定しているsampleなど

import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import { S3Backend } from 'cdktf';
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import * as fs from 'fs';
import * as path from 'path';

const configPath = path.join(__dirname, './', 'cdktf.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));

// aws provider 
import * as aws from '@cdktf/provider-aws';


class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // define resources here
    // Define AWS provider
    new AwsProvider(this, 'aws', {
      region: 'ap-northeast-1', // Example: 'us-west-2'
      defaultTags: [{
        tags: {
          environment: id,
          IaC: 'cdktf',
          BillingGroup: `test/${id}`

        }
      }]
    });

    // S3 backend configuration
    new S3Backend(this, {
      bucket: config.terraformBackend.s3.bucket,
      key: `${id}/${config.terraformBackend.s3.key}`,
      region: config.terraformBackend.s3.region,
      encrypt: true,
    });

    // Aurora cluster
    const auroraClusterId = config.rdsConfig.auroraClusterId; // Aurora cluster ID

    new aws.rdsCluster.RdsCluster(this, "auroracluster", {
      engine: config.rdsConfig.engine,
    }).importFrom(auroraClusterId); // import existing resource


    const instanceCount = 1; // インスタンス数
    for (let i = 0; i < instanceCount; i++) {
      let auroraInstanceName = `${auroraClusterId}-instance-${i + 1}`;
      new aws.rdsClusterInstance.RdsClusterInstance(this, `auroraclusterinstance${i + 1}`, {
        clusterIdentifier: auroraClusterId,
        engine: config.rdsConfig.engine,
        instanceClass: config.rdsConfig.instanceClass,
      }).importFrom(auroraInstanceName); // import existing resource

    }

  }
}

const app = new App();
new MyStack(app, "sample");
app.synth();

これで準備はOKです。

実行

この状態でdiffを実行してみます。 第2引数はmain.tsで指定している値を指定します。

cdktf diff sample
  • 出力内容(一部省略しています。)
    デフォルト設定から変わる箇所が出力されます。変更しても問題ない場合は引き続きdeploy実行、実際に合わせたい場合はmain.tsを修正します。今回は変更しても問題ない差分なのでそのままdeployを実行します。

        Terraform will perform the following actions:
sample    # aws_rds_cluster.auroracluster (auroracluster) will be updated in-place
          # (imported from "database-1")
          ~ resource "aws_rds_cluster" "auroracluster" {
                allocated_storage                   = 1
                cluster_identifier                  = "database-1"
                cluster_members                     = [
                    "database-1-instance-1",
                ]
              ~ copy_tags_to_snapshot               = true -> false
              + enable_global_write_forwarding      = false
                engine                              = "aurora-postgresql"
                engine_mode                         = "provisioned"
                engine_version                      = "14.9"
                engine_version_actual               = "14.9"
              ~ skip_final_snapshot                 = true -> false
                storage_encrypted                   = true
                tags                                = {}
              ~ tags_all                            = {
                  + "BillingGroup" = "test/sample"
                  + "IaC"          = "cdktf"
                  + "environment"  = "sample"
                }
            }

        Plan: 1 to import, 0 to add, 1 to change, 0 to destroy.

        ─────────────────────────────────────────────────────────────────────────────

        Saved the plan to: plan

        To perform exactly these actions, run the following command to apply:
            terraform apply "plan"

diff実行時のエラーについて

以下のようなエラーになった場合はインポート対象のリソースが存在しないということなのでimportFromの値と実際のリソース名で差異がないか確認します。

│ Error: Cannot import non-existent remote object
│
│ While attempting to import an existing object to
│ "aws_rds_cluster_instance.auroraclusterinstance0", the provider detected
│ that no object exists with the given id. Only pre-existing objects can be
│ imported; check that the id is correct and that it is associated with the
│ provider's configured region or endpoint, or use "terraform apply" to
│ create a new remote object for this resource.
  • 反映

cdk deploy sample

初期作成時には付与されていなかったタグなどが設定されていることが確認できます。

注意点

  • この状態でdiffを実行しても差分なしとでるが、main.tsには必須パラメータのみなので再現性が担保されているわけではありません。そのため、削除してしまったりするとパラメータグループやサブネットグループなど元々の設定とは異なる設定になってしまいます。CDKTFでの管理していくということであれば設定内容を確認、main.tsに反映、差分がないことを確認する必要がります。

    確認コマンド

terraform -chdir="cdktf.out/stacks/sample" show
  • Auroraで即時実行したい場合
    Auroraの場合、即時反映、メンテナンスウィンドウでの反映をパラメータ指定で行う必要があります。即時実行したい場合はapplyImmediatelyのパラメータ指定でtrueにします。


まとめ

CDKでもterraformでもサポートされているimport機能ですが、CDKTFでも比較的あっさりimportできるようになってIaC体験がよいです。今回の記事には記載しませんでしたが、GitHubActionsに組み込んでプルリクエストトリガーで反映できるようにもしてあるので次回以降にその内容で記事を描きたいと思います。 ではよきIaCライフを!

この記事が気に入ったらサポートをしてみませんか?