$30 off During Our Annual Pro Sale. View Details »

App Staging Synthesizerに入門する

App Staging Synthesizerに入門する

sakurai-ryo

July 09, 2024
Tweet

More Decks by sakurai-ryo

Other Decks in Technology

Transcript

  1. App Staging Synthesizer This library includes constructs aimed at replacing

    the current model of bootstrapping and providing greater control of the bootstrap experience to the CDK user. ドキュメントより引用 (雑な日本語訳) 「このライブラリには、現在のブートストラップモデルを置き換え、CDKユーザーに対してブートストラップ体験をより コントロールできるようにするための構成が含んでいる」 既存のブートストラップの仕組みの置き換えを目指して開発されている ブートストラップ体験をよりコントロールできるようにする??
  2. App Staging Synthesizerを理解するには App Staging Synthesizerを理解するには以下の項目がキーになる 1. 既存のBootstrapモデルが抱えている課題とは? 2. App

    Staging Synthesizerがどのように解決を目指しているか これからこの2つをメインテーマとして深ぼっていきます
  3. Bootstrapの役割 Bootstrapping is the process of preparing your AWS environment

    for usage with the AWS Cloud Development Kit (AWS CDK). Before you deploy a CDK stack into an AWS environment, the environment must first be bootstrapped. Developer Guideより (雑な日本語訳) 「ブートストラッピングとは、AWS Cloud Development Kit(AWS CDK)を使用するためにAWS環境を準備するプロセ スです。 」 「CDKスタックをAWS環境にデプロイする前に、まずその環境をブートストラップする必要があります。 」 あるAWSアカウントに対して初めてAWS CDKを利用したデプロイを行う前に必要となる処理のこと しれっと出てきた環境(Environment)という概念が重要
  4. 環境(Environment)とは AWSアカウントとリージョンの組み合わせを環境(Environment)と呼んでいる 同じAWSアカウントでもリージョンが違えばことなる Environment となる 以下の2つはことなる Environment なので注意 アカウント(111111111111) =>

    リージョン(us-east-1) アカウント(111111111111) => リージョン(ap-northeast-1) 📝 https://docs.aws.amazon.com/cdk/v2/guide/environments.html 同じアカウントでも異なるリージョンにデプロイする場合は最初に2回のブートストラップが必要 なので注意
  5. 作成されるIAM Role 以下のようなIAM RoleがBootstrapプロセスによって作成される(細かい部分は省略します) ロール名 概要 ImagePublishingRole ECRへコンテナイメージの保存に利用(後述) FilePublishingRole S3へファイルの保存に利用(後述)

    DeploymentActionRole 主にCFnスタックに関連する操作に利用 CloudFormationExecutionRole CFn実行時のサービスロールとして利用 LookupRole fromLookup メソッド実行時にAWSリソース参照のために利用
  6. ロールが利用される様子 cdk deploy コマンドに -v オプションを付与するとデバッグログが表示される Assuming role ~ というログからどういったRoleを利用しているか確認可能

    Assuming role ~ だけを切り出してみると色々なロールを駆使してデプロイしているのがわかる [23:54:26] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-deploy-role-111111111111-ap-nor [23:54:26] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-deploy-role-111111111111-ap-nor [23:54:26] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-file-publishing-role-1111111111 [23:54:26] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-file-publishing-role-1111111111 [23:54:27] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-file-publishing-role-1111111111 [23:54:27] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-file-publishing-role-1111111111 [23:54:27] Assuming role 'arn:aws:iam::111111111111:role/cdk-hnb659fds-lookup-role-111111111111-ap-nor
  7. Bootstrapモデルのまとめ cdk deployに必要なAWSリソースのプロビジョニングを行うプロセス アセットを保存するためのECRとS3バケット cdkコマンドの実行時にAssumeするためのIAM Role Bootstrapにはリージョンリソースが含まれるため各リージョンで実行が必要 グローバルリソースであるIAM Roleは {roleName}-{region}

    という命名で作成されるので命名が被ることはない CDKのデプロイには色々なIAM RoleにAssumeを行うことで実現されている Bootstrapping is the process of preparing your AWS environment for usage with the AWS Cloud Development Kit (AWS CDK). Before you deploy a CDK stack into an AWS environment, the environment must first be bootstrapped. Developer Guideより もう2つApp Staging Synthesizerの理解のために必要な概念があるので触れていきます
  8. ① Stack Synthesizer Each Stack has a synthesizer, an object

    that determines how and where the Stack should be synthesized and deployed. https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#stack-synthesizers より (雑な日本語訳) 「各スタックにはsynthesizerがあり、これはスタックがどのように、そしてどこに合成およびデプロイされるべきかを 決定するオブジェクトです」 役割としては主に2点 CDKのアセットをどこに保存して参照するか CFnスタックをデプロイするためにどのIAM Roleを利用するか いくつか種類がありますがここではデフォルトで利用される DefaultStackSynthesizer を取り上げます
  9. DefaultStackSynthesizer デフォルトで利用されるStack Synthesizer Bootstrapで作成されたアセットの保存場所とIAM Roleを使用する cdkコマンド実行時に利用するIAM Role Arnの決定 アセット保存時にどのS3バケットやECRに保存するかを決定 Bootstrapテンプレートを変更している場合は、変更内容をDefaultStackSynthesizerにも教えてあげる必要有

    これらの情報とCFnテンプレートファイルの場所などを合成時に cdk.out/manifest.json に吐き出す cdk.out/manifest.json を元にアプリケーションのデプロイが行われる AppStagingSynthesizer はこの DefaultStackSynthesizer の代わりに利用するモジュール
  10. ② Assets CDKアプリケーションが必要とするファイルやコンテナイメージを指す Bootstrapで作成されたS3バケットとECRに保存(自由に保存先を選択出来ないので注意) S3に保存されるファイルとECRに保存されるコンテナイメージの2種類が存在 import { Asset } from

    'aws-cdk-lib/aws-s3-assets'; import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; // 明示的にS3アセットを作成する場合 // 多くはLambda関数作成時など裏側で作成される const directoryAsset = new Asset(this, "SampleZippedDirAsset", { path: path.join(__dirname, "sample-asset-directory") }); // ECRアセットを作成する場合 const asset = new DockerImageAsset(this, 'MyBuildImage', { directory: path.join(__dirname, 'my-image') });
  11. ① セキュリティポリシーへの準拠 デフォルトで作成されるリソースが組織のセキュリティポリシーに準拠していない場合がある Bootstrapテンプレートはユーザー側で変えることが出来る cdk bootstrap コマンドの --template オプションに変更したテンプレートを指定可能 例えばECRのスキャンの有効化などなど

    ただ、元のBootstrapテンプレートが変更される場合もあるので追従していく手間がある cdk bootstrap --show-template コマンドなどで最新のテンプレートを確認し、カスタムテンプレートに反映す る 同一環境でデプロイされる複数のプロジェクトにおいてリソースの分離が難しい アカウントを分けるのがベストではあるが、分けられない事情があるケースも 📝 https://github.com/aws/aws-cdk-rfcs/blob/main/text/0513-app-specific-staging.md#v2
  12. App Staging Synthesizerの概要 DefaultStackSynthesizer に変わる新しいSynthesizerの実装 導入後ユーザーが作成したスタックとは別に StagingStack がデプロイされる CDKアプリケーションごとにS3バケットとECRを作成可能 =>

    CDKアプリごとにリソースの分離が出来る これらは StagingStack に含まれ、Bootstrapの一部代わりとなる import { BucketEncryption } from 'aws-cdk-lib/aws-s3'; const app = new App({ defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({ appId: 'my-app-id', // `StagingStack`のスタック名やS3バケットのprefixとして利用される stagingBucketEncryption: BucketEncryption.S3_MANAGED, }), }); 📝 https://docs.aws.amazon.com/cdk/api/v2/docs/app-staging-synthesizer-alpha-readme.html
  13. なぜBootstrapが不要にならないか 前述の通りApp Staging SynthesizerはBootstrapプロセスで作成されたIAM Roleを使用するため ファイルとコンテナイメージの保存には新しく作成したIAM Roleを使用 一方でリージョンリソース(S3, ECR)についてはBootstrapプロセスで作成する必要は無い 現状でIAM

    Roleのみ作成するBootstrapテンプレートは提供されていないので要カスタマイズ BootstrapはIAM Role名のsuffixして実行したリージョンを付与するので、Bootstrapしていないリージョンで cdk deploy を実行する際はリージョンの指定が必要 ただ現状はStagingStackのデプロイに利用するロール名の指定がおかしくバグっている。 。 deploymentIdentities: DeploymentIdentities.defaultBootstrapRoles({bootstrapRegion: 'us-east-1'}), const app = new cdk.App({ defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({ appId: "my-app", stagingBucketEncryption: BucketEncryption.S3_MANAGED, }), });
  14. StagingStackで作成されるS3バケットの特徴 バケット名は明示的に指定が可能、デフォルトは cdk-${appId}-staging-${account}-${region} デフォルトで RemovalPolicy が Destroy かつ autoDeleteObjects もtrueに設定されている

    StagingStack スタックの削除で全てのS3アセットは削除される autoDeleteStagingAssets プロパティで制御可能 autoDeleteStagingAssets: false の場合は RemovalPolicy が Retain に変更される stagingBucketName : "my-staging-bucket", autoDeleteStagingAssets: false, const app = new App({ defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({ appId: 'my-app-id', stagingBucketEncryption: BucketEncryption.S3_MANAGED, }), });
  15. AppStagingSynthesizerにおけるS3アセットの扱い Deploy Time S3 Assets という概念が追加された 合成したCFnテンプレートやLambdaのコードバンドルなど、デプロイ時にみに参照するアセットが該当 これらのアセットは deploy-time/{assetName} というキーで保存される

    またデフォルトで30日間保持されるようにライフサイクルルールが設定される deployTimeFileAssetLifetime プロパティで保持期間を明示的に設定可能 ロールバックの期間を考え慎重に設定する必要がある deployTimeFileAssetLifetime: Duration.days(100), const app = new cdk.App({ defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({ appId: "my-app", stagingBucketEncryption: BucketEncryption.S3_MANAGED, }), });
  16. Deploy Time S3 Assetsとして扱われるアセット Lambda関数のコードバンドル aws-s3-assets を利用した場合でも明示的に指定が可能 deployTime: false, //

    デフォルトはtrueとみなされる new Function(this, 'Lambda', { code: new AssetCode(path.join(__dirname, "function"), { }), }); deployTime: true, new Asset(this, 'S3Asset', { path: path.join(__dirname, "asset"), });
  17. StagingStackで作成されるECRの特徴① デフォルトでライフサイクルルールで最大3つのイメージまで保持 & emptyOnDelete がtrueに設定 imageAssetVersionCount プロパティでイメージの世代数を指定可能 バケットと同じく autoDeleteStagingAssets をtrueに指定した場合、ECRの

    RemovalPolicy が Retain に変更される S3と共通の設定なのでECRのみ RemovalPolicy.Destroy などは出来ない imageAssetVersionCount: 10, // コンテナイメージの最大数の指定 autoDeleteStagingAssets: false, // S3バケットと共通の設定 const app = new App({ defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({ appId: 'my-app-id', stagingBucketEncryption: BucketEncryption.S3_MANAGED, }), });
  18. StagingStackで作成されるECRの特徴② AppStagingSynthesizer 利用時は DockerImageAsset で assetName プロパティの指定が必須 この assetName ごとにECRが作成される(DockerImageAssetを利用しない限りECRは作成されない)

    リポジトリ名は明示的に指定出来ず、 ${appId}/${assetName} となるのでスタック名を入れるなど工夫が必要 タグ名は既存と同じでハッシュ値になり指定出来ない assetName: "backend", // `{appId}/backend`というリポジトリが作成される assetName: "frontend", // `{appId}/frontend`というリポジトリが作成される export class TestStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new DockerImageAsset(this, 'ECRAsset', { directory: path.join('assets'), }); new DockerImageAsset(this, 'ECRAsset2', { directory: path.join('assets2'), }); } }
  19. 主な利用上の注意点① StagingStack は環境ごとに作成される 各Stack classの synthesizer プロパティに設定は出来るが複数スタックが同一環境の場合は1つのみ作成されるため あまり意味はない synthesizer: AppStagingSynthesizer.defaultResources({}),

    synthesizer: AppStagingSynthesizer.defaultResources({}), // 複数のAppStagingSynthesizerを指定しているが1つのStagingStackしか出来ない例 new BackendStack(app, 'BackendStack', { env: { account: '111111111111', region: 'ap-northeast-1' }, // 同じ環境 }); new FrontendStack(app, 'FrontendStack', { env: { account: '111111111111', region: 'ap-northeast-1' }, // 同じ環境 });
  20. つづき 全てのスタックが同一環境の場合、 App の初期化時に指定を行う 各スタックで環境が違う場合、 Stack に指定することで環境毎に設定が可能 ただ、挙動が直感的ではないので基本的には App に指定するのが無難?

    // `App`に指定した場合でも各スタックが異なる環境の場合は各リージョンで`StagingStack`を作成して defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({}), env: { account: '111111111111', region: 'ap-northeast-1' }, // ap-northeast-1独自の設定をしたい場合 defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({}), env: { account: '111111111111', region: 'us-east-1' }, // ue-east-1独自の設定をしたい場合 defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({}), const app = new App({ }); new TokyoStack(app, 'TokyoStack', { }); new VirginiaStack(app, 'VirginiaStack', { });
  21. 主な利用上の注意点② CDK Pipelineは非対応 作成出来るECRリポジトリは20個までに制限されている(将来緩和の可能性あり) StagingStack のCFnテンプレートをS3経由でデプロイが出来ないためCloudFormationのクォータでテンプレート サイズが51,200 bytesに制限される S3バケットは StagingStack

    で作成されるため、 StagingStack のデプロイ時はそもそもバケットが存在しない BootstraplessSynthesizer というまた別のSynthesizerを利用してデプロイを実現している まだalpha版のモジュールのため破壊的な変更が入る恐れがある 本番環境での利用は要検討 既知のバグに関してはGitHub issueをご参照ください 📝制限について: https://docs.aws.amazon.com/cdk/api/v2/docs/app-staging-synthesizer-alpha- readme.html#known-limitations 📝GitHub issue: https://github.com/aws/aws-cdk/labels/%40aws-cdk%2Fapp-staging-synthesizer-alpha