5分で理解するAWS CDK


はじめに

本記事はAWS CDKについてキャッチアップすることを目的に、AWS CDKの概念や、ウォークスルーとしてAWSが公開しているWORKSHOPについて記載しています。

AWS Cloud Development Kit (AWS CDK) (以下、CDK)はTypeScript及びPythonなどのプログラミング言語を使用して、AWSリソースを定義し、Terraformの様にInfrastructure as Code(以降、IaC)を実現する手段として、クラウドインフラのリソースをプロビジョニングすることができます。

TerraformはGo言語で書かれた公式のAWS SDKを用いて、Terraform実行時にAWSのAPIを呼び出して、環境を構築しています。

Terraformは1つのプロバイダーに依存することなく、他のプロバイダーのクラウドインフラを扱えることから、汎用性だけで見たらTerraformに勝るものはないと思いますが、AWSに依存する環境の場合、IaCの手段としてCDKは最適だと思います。

CDKとは

IaCはChefやAnsibleなど構成情報や設定情報を定義する手続き型や、Terraformの様にテンプレートに必要とするリソースを定義し、冪等性を担保するために宣言型に分類することができます。

AWS CDKはTerraformと同じ宣言型として、テンプレートを定義することでプロビジョニングを実現します。また、CDKでは高いレベルの抽象化を使用して少ないコード量でインフラストラクチャを定義できますが、その裏ではCloudFormationが使用されています。

従ってCDKで書いたコードはCloudFormationのリソースとしてデプロイされることにより、プロビジョニングを実現しています。そのため、デプロイ時間だけ見れば直接APIを実行しているだけのTerraformに比べると遅いですが、CloudFormationが裏で使用されているメリットとして、自動ロールバックやドリフト検出などを享受できます。

CDKを理解するために、宣言型のIaCの概念が理解できていれば、CloudFormationに対する深い知識は不要だと思います。その他、以下の知識や経験があると理解しやすいと思います。

  • CDKで実装するリソースについて、コンソール画面で実際に作業した経験
  • CloudFormationの概念
  • オブジェクト思考(クラス、コンストラクター、オーバーライド、インターフェース等の概念)
  • TypeScriptおよびPython等CDKを使用するためのプログラミング言語

CDKはただリソースを定義するだけでなく、プログラム内でテストコードも書くこともできます。

  • Snapshot tests
  • Fine-grained assertions
  • Validation tests

AWS CDK Constructs

CDKは以下、APP->Stack->Constructの各要素によって構成されています。

  • APP
    • コンポーネントの最上位要素
    • 複数スタックの依存関係を定義
  • Stack
    • CloudFormationのStack
    • デプロイ可能な最小単位
  • Construct
    • 1つ以上からなるAWSリソース

Construct Library

CDKはConstruct Libraryを使用してAWSリソースを定義します。また、Construct Libraryには以下3種類があります。

  • High Level Construct(L2)
    • 直感的にリソースを定義することができ、デフォルト値や便利なメソッドが定義済み
    • 全てのサービスをサポートしている訳ではない
  • Low Level Construct(L1)
    • プロパティを明示的に設定する必要があるため、パラメーターを詳細に設定したい場合はこの低レベルライブラリを使用
    • クラス名にCfnプレフィックスがついている
  • Patterns
    • 一般的なアーキテクチャパターンに従う高レベルのConstructを提供

以下はHigh Level Construct(L2)でS3バケットを定義しているサンプルコードです。

import { App, Stack, StackProps } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

class HelloCdkStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

const app = new App();
new HelloCdkStack(app, "HelloCdkStack");

サーバレースのAmazonECS(Fargate)も以下のコード量で環境構築することができます。

import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";

constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, "MyVpc", {
      maxAzs: 3 // Default is all AZs in region
    });

    const cluster = new ecs.Cluster(this, "MyCluster", {
      vpc: vpc
    });

    // Create a load-balanced Fargate service and make it public
    new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", {
      cluster: cluster, // Required
      cpu: 512, // Default is 256
      desiredCount: 6, // Default is 1
      taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") },
      memoryLimitMiB: 2048, // Default is 512
      publicLoadBalancer: true // Default is false
    });
  }

Constructsは初期化時に3つのを引数使用します。

  • scope
    • 現在の構成のスコープ内で構成を定義します。thisで渡すのが一般的です。
  • id
    • 同じスコープ内では一意であるIDが必要です。
  • props
    • キーワード引数になるため特に指定しない場合、適切なデフォルト値が設定されます。また、propsは省略可能です。

WORKSHOP

公開されているWORKSHOPを基にCDKについて学びしょう。
はじめにCDKを使用するためには、Node.jsをインストールします。

準備作業

次に準備作業として任意のディレクトリを作成し、作成したディレクトリに移動します。

$ mkdir cdk-workshop && cd cdk-workshop

以下のコマンドを実行し、TypeScriptのプロジェクトを作成します。

$ cdk init sample-app --language typescript

プロジェクト作成後、CDKを用いて実装していきます。

デプロイ作業

以下のコマンドを実行すると、CloudFormationの定義情報が出力されるので、定義するテンプレートの内容を確認します。

$ cdk synth

CloudFormationの定義情報確認後、CDKが利用するリソース群をCloudFormationスタックとしてデプロイします。

$ cdk bootstrap

なお、AWS SSOを利用している環境の場合、そのまま実行すると、エラーになります。

Unable to resolve AWS account to use. It must be either configured when you define your CDK Stack, or through the environment

$ cdk bootstrap --profile XXXXXXXXXXXXなど、--profileのオプションを付与してもエラーになります。確認すると、本記事執筆時点ではAWS SSOについてサポートされてない様です。

この様な場合、環境変数をexportすることで回避できます。

export AWS_ACCESS_KEY_ID="XXXXXXXXXXXX"
export AWS_SECRET_ACCESS_KEY="XXXXXXXXXXXX"
export AWS_SESSION_TOKEN="XXXXXXXXXXXX"

デフォルトのリージョンはus-east-1になっているため、リージョンに関するエラーが出た場合はリージョンも設定します。

❌  Environment aws://XXXXXXXXXXXX/us-east-1 failed bootstrapping: AccessDenied: XXXX〜
export AWS_DEFAULT_REGION="ap-northeast-1"

bootstrap完了後、deployを実行することで定義したリソースがCloudFormationを媒介に構築されます。

$ cdk deploy

おわりに

CDKの本質は抽象化です。抽象化によってAWSの深い知識がなくてもクラウドインフラの構築が行えます。また、Terraform同様、冪等性の性質を利用し、テンプレートとして利用できることが大きなメリットと感じています。

参考