AWS Cloud Development Kit(CDK) part2

出典:AWS Blackbelt

CDKのライフサイクル

AWS CDK -> AWS CloudFormation -> AWS Cloud

  • AWS CDK
    From: Source Code , To: CloudFormation Template

    1. Construct
    2. Prepare
    3. Validate
    4. Symthetize
    • リソースのあるべき状態を宣言
    • CloudFormationテンプレートにロジックは含めることはできないため、未確定な値はCDKまたは別のプログラムで解決してCloudFormationに渡す必要がある
  • AWS CloudFormation
    Copy: Template , Props: Resources

    • ユーザーの指示をテンプレートとして受け取ってAPI呼び出し
    • スタックに永続化
      • テンプレートのコピー
      • 管理しているリソースの設定
      • Export / Import された値

CDK Appのライフサイクル

  • CDK AppはCDK CLIによって実行され、さらに実行は4つの内部フェーズに分かれる
  • コードは基本的にConstructionフェーズで実行される
    • 後続フェーズでValidateされる例:RestApiにメソッドが一つも含まれない場合にエラーにする
  • コードの実行が完了してからCloudFormationやAssetのデプロイが行われる
    • コード上でデプロイ時に決定される値を受け取ったり、デプロイ中に処理を実行したりすることはできない
      (未決定の値を扱うTokenやCustom Resource, Triggerなどの機能でカバー可能)

CDK AppとCDK Toolkit

  • CDK AppとCDK Toolkit(CLI)は直接統合しない
    • CDK Appをコマンドで実行(別プロセス)
    • Contextは環境変数やJSONで渡す(言語非依存)
  • valueFromLookupなどによって未解決のContext値が参照されるとCDK Appが複数回実行されることがある
    • CDK AppでSDK呼び出しや副作用のある処理を書く場合はパフォーマンスの劣化や冪等性、権限などに注意が必要

差分の検出

  • AWS CDK
    • cdk diffコマンド
      • 合成したテンプレートとすでにデプロイ済みのテンプレートを比較
      • リソースの置換が起こるかどうかも仕様から確認
    • CDKのスナップショットテスト
      • 合成したテンプレートと以前のテンプレート(スナップショット)を比較
  • AWS CloudFormation
    • CloudFormation変更セット
      • 新しいテンプレートをアップロードし保存されているスタックリソースの状態と比較
      • UpdateStackが呼ばれると以前の変更セットは削除
    • CloudFormationドリフト検出
      • 保存されているあスタックリソースの状態と現在のリソースの状態を比較

CDK Appの構成要素

Construct

  • クラウドコンポーネントを表現する
    • 単一のリソースだけでなく、複数のリソースを含んだConstructを定義可能
    • AppやStackなどのクラスもConstructで実装している
  • AWS Construct Libraryが標準で提供されるほかユーザーが独自の Constructを定義・配布可能
  • Construct Programming Model(CPM)の一部
    • クラウドアプリケーションなどの望ましい状態を定義して抽象化するためのプログラミングモデル
    • CDKv2からConstructは独立したライブラリとなり、CDKTF,CDK8s,Prohenなどの他のツールでも使用される

Constructのシグネチャ

位置 仮引数 説明
1 scope Construct Constructツリーの親を指定。通常は現在のスコープを表すthisになる。任意のConstructを渡す場合はIDの重複に注意
2 id string Construct IDと呼ばれる。Scope内で一位となる識別子を指定、リソース名や論理IDの一部になる
3 props Constructごとの固有の型 Constructの初期状態を定義するプロパティ、適切なデフォルト値が用意されており、すべてのプロパティがオプションのこともある

複数のConstructをまとめる(コンポジション)

  • Constructを継承したクラスを定義して複数のConstructをまとめる
  • CDKでコンポーネトを構造化する最も一般的な方法
    • CloudFormationではStackとテンプレートが1:1対応だが、CDKではStackを複数のConstructから構成可能で、ファイルの分割も自由に行える
  • 作成したハイレベルのConstructをライブラリとして共有する場合はProjenの利用を推奨

Construct IDと物理名

  • Construct IDはコンストラクトを初期化するときに第二引数に指定する文字列のこと
    • スタック名にはConstruct IDがそのまま使われる
    • 物理名には<Stack>ーが前置され、リソースまでのConstructのパスが統合して使われる
    • StageでStackをまとめると<Stage>-が前置される

App

  • エントリーポイント
  • 複数のAWSアカウント、リージョンをまたいでStackを一元管理
  • Stackの依存関係からデプロイ順序を自動で管理
  • CDK CLIから実行され、Cloud Assemblyを作成、CDK CLIによりCloud Assemblyのデプロイが行われる

Stack

  • CloudFormationスタックに対応するため、制約も同様に受ける
  • StackごとにAWSアカウント、リージョンを指定可能
  • tagsプロパティをp指定してStack自身と配下のタグ付け可能なリソースにタグ付けされる

Stage

  • 複数のStackをまとめて論理的なアプリ(サービス)のかたまりを表現
  • 1つのStageを定義して環境ごとにインスタンスすることで複製が可能
  • CDK Pipelines使用時には必須

Environment

  • StackやStageを初期化するときにデプロイ先のAWSアカウントとリージョンを指定
  • env,account,regionいずれも指定はオプション
    • 指定を省略すると、環境に依存しないスタックとみなされる(environment-agnostic)
    • この場合Vpc.fromLookupstack.regionなどの環境を特定する必要のあるコードは機能しない
  • 環境変数CDK_DEFAULT_ACCOUNTCDK_DEFAULT_REGIONがCDK CLIにより提供

Asset

  • CDK Appと一緒にデプロイできるファイルやディレクトリ、Dockerイメージ
  • zip圧縮またはdocker buildとアップロードはCDK CLIによって実行される
  • バンドル時に任意のビルドコマンドを実行可能

Context

  • CDK Appから参照できるKey-Valueペア
  • cdk.jsonのcontextプロパティとCDK CLIの-c,--contextで任意の値を渡せる
  • CDK CLIは合成中に未解決の値がレポートされるとAWS SDKを使用して解決、cdk.context.jsonにキャッシュ
  • cdk.context.jsonは手で編集せず、Gitで管理することを推奨
  • cdk context --resetでリセット

Feature Flag

  • 後方互換性を保ちながらCDKを進化させたり、特定のクラスやメソッドの動作を変更できるようにする
  • cdk.jsonにコンテキスト値として指定(cdk context --resetではリセットされない)
  • cdk initで新しいプロジェクトを作成した場合、推奨されるすべての機能フラグを有効にしたcdk.jsonを生成する

Bootstrapping

  • Appをデプロイする前に、ファイル保存するためのS3バケットやECRリポジトリ、IAM Roleなどを作成するプロセス
  • AWSアカウントとリージョンごとにBootstrapが必要
  • CDK pipelinesを使用する場合など、別のアカウントへのデプロイ許可は--trustオプションが使用可能

Token

  • Appで未解決の値を扱うためのクラス
  • 合成中の後続のコードで決定される値
    • Lazy.stringなど
    • produce関数で値を返す実装を行う必要がある
  • デプロイ時に決定される値
    • S3バケット名などのプロパティはTokenを返す
    • 合成後にCloudFormationのRef関数に変換される
  • Tokenを参照するとプレースホルダが返る
    • ほかのリソースに渡せるが、文字列結合以外の演算は不可

Aspect

  • 指定されたスコープのすべてのConstructへの捜査を実装可能
  • タグをつけたり、削除ポリシーを設定したり、暗号化の有無をチェックすることなどが可能
  • Prepareフェーズでvisit関数が呼び出される
  • Stageをまたいだ適用はできない

Tags

  • 指定されたスコープのすべてのConstructに一括でタグ付け可能
  • タグの捜査が競合した場合、priorityの高いものが採用される
  • Aspectを使用しているため、Stageをまたいだ適用はできない
  • タグ付け可能なリソースのみに付与される

リソースとパラメータの参照

CDK App内のリソース参照

  • 組み込み関数で値を解決可能
  • CDKアプリのコード内でリソースを参照すると、CloudFormationの組み込み関数に変換される
    • CDK App内で値にアクセスするとTokenが返る

参照するリソースの場所に応じてテンプレートを合成

  • 同じStack内のリソース
    • !Refまたは!GetAtt
  • 別のStack内のリソース
    • Export!ImportValueのセット
  • 別のリージョンのリソース
    • ExportとCustomResourceによって消費側のリージョンにSSMParameterを作成し!GetAttで取得
  • 別のStageのリソース
    • 参照不可

AWS CDKのクロスリージョン参照(Preview)

  • CDKが自動的にCustomResourceとSSM Parameter Store作成
  • 提供側と消費側の両方に指定crossRegionReferences: true(※v2.79.0現在)

パラメータ・スークレット参照の使い分け

  • シークレット値
    1
    2
    const secure1 = SecretValue.ssmSecure('CdkConfSecret1');
    const secure1 = SecretValue.secretManager('CdkConfSecret2');
  • 平文パラメータ
    1
    const param1 = StringParameter.valueForStringParameter(stack, 'P1');
  • Synth時に値を解決
    1
    const param1 = StringParameter.valueFromLookup(stack, 'P2');
  • パラメータ・シークレットのリソース
    1
    2
    3
    const param1ref = 
    StringParameter.fromStringParameterName(stack, 'P1Ref', 'P1');
    Tags.of(bucker).add('Param1', param1ref.stringValue);

環境ごとにテンプレートを出しわける方法

  • 外部のパラメータを読み込む方法
  • スタックを定義する方法

リソースのインポート

CloudFormationへのリソースのインポート

cdk import

  • 前提条件:テンプレートとリソースの設定はセット
  • 現在のリソースの状態と一致するテンプレートを用意してインポートを実施(OSSのFormer2などを利用する)

インポート手順例

  1. Former2 で L1 Constructを生成
  2. cdk import
  3. ドリフトがないことを確認
  4. Snapshot testを作成
  5. L2 Constructにリファクタリング

CloudFormation資産の活用

CloudFormationへのリソースのインクルード

CfnInclude

  • CloudFormationのテンプレートを再利用
  • preserveLogicalIds: falseを指定することで論理IDの命名をCDKに任せられる(デフォルトtrue)
  • インクルードした添付れーどで作成したリソースはgetResource()などでアクセス可能

CloudFormationスタックをCDKに移行

  • CfnIncludeを行うスコープのスタック名を合わせる
    • 通常はConstruct ID(new Stack()の第2引数)
    • Stage配下の場合はstackNameプロパティを明示的に指定
  • cdk diffでBootstrap関連のパラメータや条件のみが追加されていることを確認

CloudFormationからCDKへの移行方法

  • デプロイ済みのスタックを維持して移行
    • デプロイ済みのスタックを変更しないため稼働中アプリへの影響を与えづらい
    • スタック構成の変更やL2 Constructへのリファクタなどが段階的に行える
    • リファクタ時にステート富楼那リソースの論理IDが変更される場合overrideLogicakId()で維持
    • 移行手順
    1. CfnIncludeで既存のスタック名と合わせてデプロイ
    2. Snapshot testを作成・実行
  • デプロイ済みのスタックを削除して移行
    • ステートフルなリソースのみインポート対象にする
    • 既存リソースの一部だけを利用したい場合に有効
    • 移行手順
    1. CloudFormationでDeletionPolicy: Retainを設定
    2. CloudFormationスタックを削除
    3. CDKでスタックを作成
    4. cdk import