🚶‍♂️

CDK for Terraformを使ってAWS Step Functionsをデプロイする

2023/05/14に公開

背景

業務の中でCDK for Terraformを使って、AWS Step Functionsを構築する機会がありました。
そのやり方を今後使用する方や私自身の備忘録として記載しておきます!

CDK for Terraformとは

Cloud Development Kit for Terraform(CDKTF)は、使い慣れたプログラミング言語を使ってインフラの定義やプロビジョニングを行うことができます。これにより、HashiCorp Configuration Language(HCL)を学ぶことなくTerraformエコシステム全体にアクセスでき、テストや依存関係管理などに既存のツールチェインの力を活用することができます。
TypeScript、Python、Java、C#、Goをサポートしています。

CDK for Terraformは、AWS Cloud Development Kitのコンセプトとライブラリを活用し、お客様のコードをTerraform用のインフラ構成ファイルに変換します。

公式ページから引用

つまり、AWS Cloud Development Kitを使って、Terraformを動かすことができるIaC (Infrastructure as Code) の一種です!

実装方法

事前に必要なもの(2023/05/12時点)

Terraform CLI ( 1.2 以上 )
Node.js ( v16 以上 )

CDK for Terraformをインストールします

$ npm install --global cdktf-cli@latest

一応正常にインストールされたかを確認

$ cdktf help

Please pass a command to cdktf, here are all available ones:
cdktf

コマンド:
  cdktf init                Create a new cdktf project from a template.
  cdktf get                 Generate CDK Constructs for Terraform providers
                            and modules.
  cdktf convert             Converts a single file of HCL configuration to
                            CDK for Terraform. Takes the file to be
                            converted on stdin.
  cdktf deploy [stacks...]  Deploy the given stacks     [エイリアス: apply]
  cdktf destroy [stacks..]  Destroy the given stacks
  cdktf diff [stack]        Perform a diff (terraform plan) for the given
                            stack                        [エイリアス: plan]
  cdktf list                List stacks in app.
  cdktf login               Retrieves an API token to connect to Terraform
                            Cloud or Terraform Enterprise.
  cdktf synth               Synthesizes Terraform code for the given app in
                            a directory.           [エイリアス: synthesize]
  cdktf watch [stacks..]    [experimental] Watch for file changes and
                            automatically trigger a deploy
  cdktf output [stacks..]   Prints the output of stacks
                                                      [エイリアス: outputs]
  cdktf debug               Get debug information about the current project
                            and environment
  cdktf provider            A set of subcommands that facilitates provider
                            management
  cdktf completion          generate completion script

オプション:
      --version                   バージョンを表示                   [真偽]
      --disable-plugin-cache-env  Dont set TF_PLUGIN_CACHE_DIR
                                  automatically. This is useful when the
                                  plugin cache is configured differently.
                                  Supported using the env
                                  CDKTF_DISABLE_PLUGIN_CACHE_ENV.
                                                 [真偽] [デフォルト: false]
      --log-level                 Which log level should be written. Only
                                  supported via setting the env
                                  CDKTF_LOG_LEVEL                  [文字列]
  -h, --help                      ヘルプを表示                       [真偽]

Options can be specified via environment variables with the "CDKTF_" prefix
(e.g. "CDKTF_OUTPUT")

大丈夫そうです!

作業用ディレクトリの作成

ディレクトリ作って、移動しておきます

$ mkdir cdktf-step-function
$ cd cdktf-step-function

初期化

今回はTypeScriptで書いていきます。

$ cdktf init --template=typescript --local

templateで使用する言語を指定し、--localをつけることで自分のプロジェクトでtfstateを管理するようにしています。

対話形式で複数聞かれるのでプロジェクトに合わせて作成していきます。

$ cdktf init --template=typescript --local
Note: By supplying '--local' option you have chosen local storage mode for storing the state of your stack.
This means that your Terraform state file will be stored locally on disk in a file 'terraform.<STACK NAME>.tfstate' in the root of your project.
? Project Name cdktf-step-functions
? 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 No

added 2 packages, and audited 57 packages in 2s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

added 302 packages, and audited 359 packages in 30s

37 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
========================================================================================================

  Your cdktf typescript project is ready!

  cat help                Print this message

  Compile:
    npm run get           Import/update Terraform providers and modules (you should check-in this directory)
    npm run compile       Compile typescript code to javascript (or "npm run watch")
    npm run watch         Watch for changes and compile typescript in the background
    npm run build         Compile typescript

  Synthesize:
    cdktf synth [stack]   Synthesize Terraform resources from stacks to cdktf.out/ (ready for 'terraform apply')

  Diff:
    cdktf diff [stack]    Perform a diff (terraform plan) for the given stack

  Deploy:
    cdktf deploy [stack]  Deploy the given stack

  Destroy:
    cdktf destroy [stack] Destroy the stack

  Test:
    npm run test        Runs unit tests (edit __tests__/main-test.ts to add your own tests)
    npm run test:watch  Watches the tests and reruns them on change

  Upgrades:
    npm run upgrade        Upgrade cdktf modules to latest version
    npm run upgrade:next   Upgrade cdktf modules to latest "@next" version (last commit)

 Use Providers:

  You can add prebuilt providers (if available) or locally generated ones using the add command:

  cdktf provider add "aws@~>3.0" null kreuzwerker/docker

  You can find all prebuilt providers on npm: https://www.npmjs.com/search?q=keywords:cdktf
  You can also install these providers directly through npm:

  npm install @cdktf/provider-aws
  npm install @cdktf/provider-google
  npm install @cdktf/provider-azurerm
  npm install @cdktf/provider-docker
  npm install @cdktf/provider-github
  npm install @cdktf/provider-null

  You can also build any module or provider locally. Learn more https://cdk.tf/modules-and-providers

========================================================================================================

Note: You can always add providers using 'cdktf provider add' later on
? What providers do you want to use? aws
Checking whether pre-built provider exists for the following constraints:
  provider: aws
  version : latest
  language: typescript
  cdktf   : 0.16.1

Found pre-built provider.
Adding package @cdktf/provider-aws @ 14.0.4
Installing package @cdktf/provider-aws @ 14.0.4 using npm.
Package installed.

また最後に使用するproviderを聞かれるので、awsを選択しておきます。

initが終わると、いろんなファイルが作成されます。

lambaの作成

まずはstep functionsで起動するlambadaを作成していきます。
今回はstep functionsのデプロイ方法中心に説明するためにlambdaはコンソール上から簡単に作成します。

作成したlambdaはこんな感じです。
(関数はデフォルトのままです)

CDK for Terraformでstep functionsを起動する

main.tsにstep functionsの起動に必要なコードを記述していきます。

main.ts
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import * as aws from '@cdktf/provider-aws'

// step functionsのassumeRoleのpolicy
const stepFunctionsAssumeRolePolicy = {
  Version: '2012-10-17',
  Statement: [
    {
      Action: 'sts:AssumeRole',
      Principal: {
        Service: 'states.amazonaws.com',
      },
      Effect: 'Allow',
    },
  ],
}

// step functionsにアタッチするpolicy
const stepFunctionsPolicy = {
  Version: '2012-10-17',
  Statement: [
    {
      Effect: 'Allow',
      Action: ['lambda:InvokeFunction'],
      Resource: '*',
    },
    {
      Effect: 'Allow',
      Action: [
        'xray:PutTraceSegments',
        'xray:PutTelemetryRecords',
        'xray:GetSamplingRules',
        'xray:GetSamplingTargets',
      ],
      Resource: '*',
    },
  ],
}

// step functionsのASLを定義
const definition = {
  StartAt: 'LambdaExec',
  States: {
    LambdaExec: {
      Type: 'Task',
      Resource:
        '起動するlambdaのARN',
      End: true,
    },
  }
}


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

    new aws.provider.AwsProvider(this, 'aws', {
      region: 'ap-northeast-1',
    })

    // step functions実行用のroleを作成
    const role = new aws.iamRole.IamRole(this, 'cdktf-test-step-functions-role', {
      name: 'cdktf-test-step-functions-role',
      assumeRolePolicy: JSON.stringify(stepFunctionsAssumeRolePolicy),
    })

    // policyの作成
    const policy = new aws.iamPolicy.IamPolicy(this, 'cdktf-test-step-functions-policy', {
      name: 'cdktf-test-step-functions-policy',
      policy: JSON.stringify(stepFunctionsPolicy),
    })

    // step functionsの実行に必要なpolicyをアタッチ
    new aws.iamRolePolicyAttachment.IamRolePolicyAttachment(
      this,
      'cdktf-test-step-functions-managed-policy',
      {
        policyArn: policy.arn,
        role: role.name,
      }
    )

    // step functionsをデプロイ
    new aws.sfnStateMachine.SfnStateMachine(this, 'cdktf-test-state-machine', {
      name: 'cdktf-test-state-machine',
      definition: JSON.stringify(definition),
      roleArn: role.arn,
    })
  }
}

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

デプロイしてみる

デプロイコマンドを実行します。

$ cdktf deploy

terraformと同様、作成するリソースが出力されるので、リソースが想定したものかを確認します。

問題なければ、

❯ Approve  Applies the changes outlined in the plan.

を選択することで、デプロイ完了です。

デプロイされているかの確認

コンソールでStep Functionsを開いてみます。
ステートマシンを確認すると、想定通りステートマシンが作成されています。

実際に実行もしてみると、前もって作成したlambdaが無事呼び出されていることを確認できました!

Discussion