実践! CDK for Terraform #1 導入

2023.07.07

こんにちは!AWS 事業本部コンサルティング部のたかくに(@takakuni_)です。

皆さん、CDK for Terraform 使ってますでしょうか?私はあまり使っていません。

本エントリは、何本出るかわかりませんが、シリーズもので「CDK for Terraform 触っていこう」をモチベーションにしたブログになります。

田中 の執筆した「実践!AWS CDK」シリーズをパクらせて参考にさせていただき、 CDK for Terraform を入門できればと思います。

今回は「導入編」として、 CDK for Terraform のインストールと、軽くリソースをプロビジョニングしていきたいと思います。

CDK for Terraform とは

ざっくり解説すると以下になります。

  • Cloud Development Kit for Terraform (略称 CDKTF または CDK for Terraform)
  • TypeScript などのプログラミング言語を使ってインフラのプロビジョニングを行うフレームワーク
    • Terraform で利用する HashiCorp Configuration Language の学習コストを減らせる
  • アプリケーションコードから Terraform ファイルを生成してデプロイする
  • テストコードが記述できる

CDK for Terraform を利用することで、Terraform の得意な部分であるマルチプラットフォームのプロビジョニングが、プログラミングコードで可能になります。

CDK for Terraform より画像引用

CDK for Terraform のインストール

今回は、 TypeScript で CDK for Terraform を利用します。

CKD for Terraform をインストールするには事前に以下が必要です。

  • Terraform CLI (v1.2 以降)
  • Node.js (v16 以降)

インストールは、 npm か、 Mac の場合は Homebrew を利用できます。

npm

npm install --global cdktf-cli@latest

Homebrew

brew install cdktf

インストールが完了すると、cdktf --version でバージョンを確認してみましょう。

takakuni@~ % cdktf --version
0.17.1

プロジェクトの作成

まずは、空のディレクトリを作成し移動します。

mkdir cdktf-devio && cd cdktf-devio

続いて、ディレクトリ内で CDK for Terraform の初期化を行います。

cdktf init --template=typescript --local

すると、対話形式でプロジェクト名等の追加情報が質問されるため、回答します。

(今回は全部 Enter でスキップしました)

? Project Name cdktf-devio
? Project Description A simple getting started project for cdktf.
? Do you want to start from an existing Terraform project? no
? Do you want to send crash reports to the CDKTF team? Refer to https://developer.hashicorp.com/terraform/cdktf/create-and-deploy/configuration-file#enable-crash-reporting-for-the-cli for more information yes
Note: You can always add providers using 'cdktf provider add' later on
? What providers do you want to use?

初期化が完了すると、以下のフォルダ階層でプロジェクトが作成されます。

takakuni@cdktf-devio % tree . -L 1
.
├── __tests__
├── cdktf.json
├── help
├── jest.config.js
├── main.ts
├── node_modules
├── package-lock.json
├── package.json
├── setup.js
└── tsconfig.json

3 directories, 8 files

今後は、デプロイしたいリソースを main.tsMyStack クラスに定義していく流れになります。

main.ts

import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";

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

    // define resources here
  }
}

const app = new App();
new MyStack(app, "cdktf-devio");
app.synth();

リソースを定義してみる

プロバイダーの設定

Terraform には、 プロバイダーと呼ばれるプラットフォームごとに API をまとめたリストを提供しています。

AWS なら aws プロバイダー、 Google Cloud なら google と言ったイメージです。

aws プロバイダーのプロビジョニング先リージョンを設定しようと思います。

まずはプロバイダーのインストールを行います。

npm install @cdktf/provider-aws

main.ts を編集します。次のように、追記します。

main.ts

import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";

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

    // define resources here
    new AwsProvider(this, "aws", {
      region: "ap-northeast-1",
    });
  }
}

const app = new App();
new MyStack(app, "cdktf-devio");
app.synth();

VPC の作成

aws_vpc を利用して、 VPC を作成していきましょう。

引き続き main.ts を次のように編集していきます。

main.ts

import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import { Vpc } from "@cdktf/provider-aws/lib/vpc";

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

    // define resources here
    new AwsProvider(this, "aws", {
      region: "ap-northeast-1",
    });

    // VPC
    new Vpc(this, 'vpc', {
      cidrBlock: '10.0.0.0/16',
      enableDnsHostnames: true,
      enableDnsSupport: true,
      tags: {
        Name: 'cdktf-devio-vpc',
      }
    });
  }
}

const app = new App();
new MyStack(app, "cdktf-devio");
app.synth();

Terraform ファイルの生成

cdktf synth(synthesize)コマンドを使用して、コードから Terraform ファイルを生成します。

takakuni@cdktf-devio % cdktf synth

Generated Terraform code for the stacks: cdktf-devio

デフォルトで作成された Terraform ファイルは cdktf.out/stacks 配下に出力されてました。

cdktf.out/stacks/cdktf-devio/cdk.tf.json

{
  "//": {
    "metadata": {
      "backend": "local",
      "stackName": "cdktf-devio",
      "version": "0.17.1"
    },
    "outputs": {
    }
  },
  "provider": {
    "aws": [
      {
        "region": "ap-northeast-1"
      }
    ]
  },
  "resource": {
    "aws_vpc": {
      "vpc": {
        "//": {
          "metadata": {
            "path": "cdktf-devio/vpc",
            "uniqueId": "vpc"
          }
        },
        "cidr_block": "10.0.0.0/16",
        "enable_dns_hostnames": true,
        "enable_dns_support": true,
        "tags": {
          "Name": "cdktf-devio-vpc"
        }
      }
    }
  },
  "terraform": {
    "backend": {
      "local": {
        "path": "/Users/takakuni/Desktop/cdktf-devio/terraform.cdktf-devio.tfstate"
      }
    },
    "required_providers": {
      "aws": {
        "source": "aws",
        "version": "5.6.2"
      }
    }
  }
}

デプロイ

cdktf deploy コマンドでアプリケーションコードを Terraform ファイルにコンパイルし、VPC をプロビジョニングします。

前回からの差分が表示し、差分に問題なければ Approve を選択します。

takakuni@cdktf-devio % cdktf deploy   
cdktf-devio  Initializing the backend...
cdktf-devio  Initializing provider plugins...
             - Reusing previous version of hashicorp/aws from the dependency lock file
cdktf-devio  - Using previously-installed hashicorp/aws v5.6.2
cdktf-devio  Terraform has been successfully initialized!
             
             You may now begin working with Terraform. Try running "terraform plan" to see
             any changes that are required for your infrastructure. All Terraform commands
             should now work.

             If you ever set or change modules or backend configuration for Terraform,
             rerun this command to reinitialize your working directory. If you forget, other
             commands will detect it and remind you to do so if necessary.
cdktf-devio  Terraform used the selected providers to generate the following execution plan.
             Resource actions are indicated with the following symbols:
               + create

             Terraform will perform the following actions:
cdktf-devio    # aws_vpc.vpc (vpc) will be created
               + resource "aws_vpc" "vpc" {
                   + arn                                  = (known after apply)
                   + cidr_block                           = "10.0.0.0/16"
                   + default_network_acl_id               = (known after apply)
                   + default_route_table_id               = (known after apply)
                   + default_security_group_id            = (known after apply)
                   + dhcp_options_id                      = (known after apply)
                   + enable_dns_hostnames                 = true
                   + enable_dns_support                   = true
                   + enable_network_address_usage_metrics = (known after apply)
                   + id                                   = (known after apply)
                   + instance_tenancy                     = "default"
                   + ipv6_association_id                  = (known after apply)
cdktf-devio  + ipv6_cidr_block                      = (known after apply)
                   + ipv6_cidr_block_network_border_group = (known after apply)
                   + main_route_table_id                  = (known after apply)
                   + owner_id                             = (known after apply)
                   + tags                                 = {
                       + "Name" = "cdktf-devio-vpc"
                     }
                   + tags_all                             = {
                       + "Name" = "cdktf-devio-vpc"
                     }
                 }

             Plan: 1 to add, 0 to change, 0 to destroy.
             
             Do you want to perform these actions?
               Terraform will perform the actions described above.
               Only 'yes' will be accepted to approve.
cdktf-devio  Enter a value: yes
cdktf-devio  aws_vpc.vpc (vpc): Creating...
cdktf-devio  aws_vpc.vpc (vpc): Still creating... [10s elapsed]
cdktf-devio  aws_vpc.vpc (vpc): Creation complete after 12s [id=vpc-08667013746e9fb49]
cdktf-devio  
             Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

No outputs found.

手動で変更してみる

試しに、手動で変更してみます。

再度 cdktf deploy をしてみると差分が表示され、元に戻すことができました。

takakuni@cdktf-devio % cdktf deploy
cdktf-devio  Initializing the backend...
cdktf-devio  Initializing provider plugins...
             - Reusing previous version of hashicorp/aws from the dependency lock file
cdktf-devio  - Using previously-installed hashicorp/aws v5.6.2

             Terraform has been successfully initialized!
cdktf-devio  
             You may now begin working with Terraform. Try running "terraform plan" to see
             any changes that are required for your infrastructure. All Terraform commands
             should now work.

             If you ever set or change modules or backend configuration for Terraform,
             rerun this command to reinitialize your working directory. If you forget, other
             commands will detect it and remind you to do so if necessary.
cdktf-devio  aws_vpc.vpc (vpc): Refreshing state... [id=vpc-08667013746e9fb49]
cdktf-devio  Terraform used the selected providers to generate the following execution plan.
             Resource actions are indicated with the following symbols:
               ~ update in-place

             Terraform will perform the following actions:
cdktf-devio    # aws_vpc.vpc (vpc) will be updated in-place
               ~ resource "aws_vpc" "vpc" {
                   ~ enable_dns_hostnames                 = false -> true
                   ~ enable_dns_support                   = false -> true
                     id                                   = "vpc-08667013746e9fb49"
                     tags                                 = {
                         "Name" = "cdktf-devio-vpc"
                     }
                     # (13 unchanged attributes hidden)
                 }

             Plan: 0 to add, 1 to change, 0 to destroy.
             
             Do you want to perform these actions?
               Terraform will perform the actions described above.
               Only 'yes' will be accepted to approve.
cdktf-devio  Enter a value: yes
cdktf-devio  aws_vpc.vpc (vpc): Modifying... [id=vpc-08667013746e9fb49]
cdktf-devio  aws_vpc.vpc (vpc): Still modifying... [id=vpc-08667013746e9fb49, 10s elapsed]
cdktf-devio  aws_vpc.vpc (vpc): Still modifying... [id=vpc-08667013746e9fb49, 20s elapsed]
cdktf-devio  aws_vpc.vpc (vpc): Modifications complete after 22s [id=vpc-08667013746e9fb49]
cdktf-devio  
             Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

No outputs found.

リソースの削除

cdktf destroy コマンドでリソースを削除していきます。無事削除が完了したようです。

takakuni@cdktf-devio % cdktf destroy
cdktf-devio  Initializing the backend...
cdktf-devio  Initializing provider plugins...
             - Reusing previous version of hashicorp/aws from the dependency lock file
cdktf-devio  - Using previously-installed hashicorp/aws v5.6.2

             Terraform has been successfully initialized!
cdktf-devio  
             You may now begin working with Terraform. Try running "terraform plan" to see
             any changes that are required for your infrastructure. All Terraform commands
             should now work.

             If you ever set or change modules or backend configuration for Terraform,
             rerun this command to reinitialize your working directory. If you forget, other
             commands will detect it and remind you to do so if necessary.
cdktf-devio  aws_vpc.vpc (vpc): Refreshing state... [id=vpc-08667013746e9fb49]
cdktf-devio  Terraform used the selected providers to generate the following execution plan.
             Resource actions are indicated with the following symbols:
               - destroy

             Terraform will perform the following actions:
cdktf-devio    # aws_vpc.vpc (vpc) will be destroyed
               - resource "aws_vpc" "vpc" {
                   - arn                                  = "arn:aws:ec2:ap-northeast-1:123456789012:vpc/vpc-08667013746e9fb49" -> null
                   - assign_generated_ipv6_cidr_block     = false -> null
                   - cidr_block                           = "10.0.0.0/16" -> null
                   - default_network_acl_id               = "acl-0ab0232dc86c525ce" -> null
                   - default_route_table_id               = "rtb-0b8a13b2c1a713934" -> null
                   - default_security_group_id            = "sg-0ffd80b65fdcb12f9" -> null
                   - dhcp_options_id                      = "dopt-03c00cf53d618e49b" -> null
                   - enable_dns_hostnames                 = true -> null
cdktf-devio  - enable_dns_support                   = true -> null
                   - enable_network_address_usage_metrics = false -> null
                   - id                                   = "vpc-08667013746e9fb49" -> null
                   - instance_tenancy                     = "default" -> null
                   - ipv6_netmask_length                  = 0 -> null
                   - main_route_table_id                  = "rtb-0b8a13b2c1a713934" -> null
                   - owner_id                             = "622809842341" -> null
                   - tags                                 = {
                       - "Name" = "cdktf-devio-vpc"
                     } -> null
                   - tags_all                             = {
                       - "Name" = "cdktf-devio-vpc"
                     } -> null
                 }

             Plan: 0 to add, 0 to change, 1 to destroy.
             
             Do you really want to destroy all resources?
cdktf-devio  Terraform will destroy all your managed infrastructure, as shown above.
               There is no undo. Only 'yes' will be accepted to confirm.
cdktf-devio  Enter a value: yes
cdktf-devio  aws_vpc.vpc (vpc): Destroying... [id=vpc-08667013746e9fb49]
cdktf-devio  aws_vpc.vpc (vpc): Destruction complete after 1s
cdktf-devio  
             Destroy complete! Resources: 1 destroyed.

おわりに

以上、「実践! CDK for Terraform #1 導入」でした。このような流れで、 CDK for Terraform をゆっくり入門していきたいと思います。

AWS 事業本部コンサルティング部のたかくに(@takakuni_)でした!

参考