CDK Pipelineを導入する時に「aws:cdk:path」にハマった話
はじめに
D2Cでエンジニアをしている、閃(セン)と申します。
私の所属するチームでは、AWS上でシステムを構築しており、AWS CDKをIaCツールとして採用しています。最近はCI/CDツールの導入を検討し、その際にAWS Code Pipelineを選定しました。Code Pipelineを構築するには、Code Pipelineのコンストラクトを使うのも可能ですが、それと別にCDK Pipelineのコンストラクトがあります。
CDK Pipelineというのは、CDKプロジェクトをデプロイするCode Pipelineを容易に構築できるコンストラクトです。今回はCDK Pipelineを紹介し、それを導入する時にハマったaws:cdk:path
問題について説明する予定です。
CDK Pipelineの構成と特徴
まずはCDK Pipelineの構成について紹介します。前節で紹介したように、CDK PipelineはあくまでCode Pipelineを容易に構築できるコンストラクトであり、利用しているサービスはAWS Codeシリーズです。基本的な構成は下記のように、Source、Build、UpdatePipeline、PublishAssetsの四つのステージと複数のMyStageとなります。実際のコードを見せつつ、詳しく紹介していきます。
Source:Code Pipelineと同様、CodeStarを通じてCode Pipelineのトリガーを定義するステージです。
input = pipelines.CodePipelineSource.connection(
repo_string="repo_string",
branch=branch_name,
connection_arn="connection_arn",
)
Build:こちもCode Pipelineと同じCode Buildを利用しているが、cdk synth
のためのCode Buildを簡単に構築できる独自のコンストラクトがあります。
synth = pipelines.ShellStep(
id="CdkPipelineSynth",
input=input,
commands=[
"pip install -r requirements.txt",
"npm install -g aws-cdk",
"cdk synth",
],
primary_output_directory="directory/cdk.out",
)
UpdatePipeline:CDK Pipeline独自のステージです。デプロイの前に、Pipeline自体が最新かどうかをチェックし自我更新するCode Buildです。Pipeline自体が最新ではない場合は、Pipelineを更新した上で最初のステージに戻り、再度デプロイします。なお、自動作成されるため、実装する必要はない。
MyStage:デプロイする予定のスタックを定義するステージです。同じ複数のPipelineで複数の環境にデプロイする場合は、複数のステージ(DevStage
、PreProdStage
、ProdStage
、etc.)を用意することとなります。なお、こちらでスタックを定義した上で、従来のApp.py
でのスタック定義はPipelineのスタックだけで十分です。
class MyStage(Stage):
def __init__(
self,
scope,
id,
*,
):
super().__init__(scope, id)
TestStack(
self,
"TestStack",
stack_name="TestStack",
)
それぞれのステージについて紹介しましたが、Code Pipelineと似たような構成もあって独自な構成もある。次にCDK Pipelineの特徴について少しまとめます。
- CDKでの実装が簡単で、数行だけで複雑なデプロイ用Code Pipelineが作られます。
- Pipelineの自己更新があります。
- クロスアカウントやクロスリージョンの多環境デプロイが簡単にできる。
以上がCDK Pipelineの構成と特徴を簡潔に整理したものとなります。しかし、実際の導入と運用では予想外のaws:cdk:path
問題が発生し、それが本稿を書くきっかけとなります。
「aws:cdk:path」問題とその回避策
問題の発見
まずは問題の発見から説明します、CDK Pipelineの検証段階で発生したことです。CDK Pipelineスタックの実装が完了し、DEV環境にデプロイした状態で、テスト用スタックだけのステージの初デプロイが完了しました。
予想通りの仕組みで、既存スタックのステージ実装に取り組んでいきたいところです。デプロイ結果の確認として、CLIでテストスタックにcdk diff
を実行しました。そこで問題が発生しました、下記のようにAWS::CDK::Metadata
中のaws:cdk:path
の差分が発生しています。
Resources
[~] AWS::S3::Bucket MyBucket
└─ [~] Metadata
└─ [~] .aws:cdk:path:
├─ [-] CdkPipelineStack/CdkPipelineDeploy/TestStack/MyBucket/Resource
└─ [+] TestStack/MyBucket/Resource
そもそもAWS::CDK::Metadata
とは何でしょう?公式ドキュメントによりますと、下記のように書かれています。
Every generated template contains a
AWS::CDK::Metadata
resource by default. (We haven't shown it here.) The AWS CDK team uses this metadata to gain insight into how the AWS CDK is used, so that we can continue to improve it. For details, including how to opt out of version reporting, see Version reporting.
バージョン管理とAWS CDKチームが情報収集用のリソースで、自動生成されたものとなります。現状ではCDK Pipelineと通常のCLIによる生成されたaws:cdk:path
が異なり、Issueが作成されている状態です。
問題の整理
以上の内容を踏まえで、Issueの内容も加えて、問題と影響を整理してみます。
問題:
- CDK PipelineによるデプロイとCLIによるデプロイの
aws:cdk:path
が一致しない - CLIの場合:
MyStack/MyQueue/Resource
- CDK Pipelineの場合:
MyPipelineStack/MyAppStage/MyStack/MyQueue/Resource
影響:
-
AWS::CDK::Metadata
に差分が発生します -
aws:cdk:path
による生成されたリソースのパラメータに差分が発生します- 一例としてセキュリティグループの
description
が設定されてない状態だと、デフォルトでaws:cdk:path
となります - 既に作成されたリソースに関しては、場合によってリソースの再作成となります。
- 一例としてセキュリティグループの
問題の回避策
現状では根本的な解決ができません。一つの回避策としては、aws:cdk:path
をそのままにしてCLIにオプションを付けて使用する。
cdk synth
で作成されたテンプレートはcdk.out
配下にありますが、Pipelineで使うテンプレートは別ディレクトリにあると気づきました。cdk.out
ではなく、cdk.out/assembly-CdkPipelineStack-CdkPipelineStackDeploy
に作成されてます。CLIで-a
オプションを使用したことで、CDK Pipelineと同じテンプレートで比較・デプロイできる。
$ cdk synth
$ cdk diff -a cdk.out/assembly-CdkPipelineStack-CdkPipelineStackDeploy
$ cdk deploy CdkPipelineStack/CdkPipelineDeploy/TestStack -a cdk.out/assembly-CdkPipelineStack-CdkPipelineStackDeploy
初回Pipelineデプロイによるリソースの差分や再作成問題については、今のところに回避策はありません。リソースの状況によってケイスバイケイスで対応しかありません。
おわりに
寄り道ですが、これでCDK Pipeline運用上のaws:cdk:path
問題が回避できました。記事投稿時までは、機能改善のissueはまだ進んでいないようで、かなり先の話になりそうです。
CDK Pipelineの使いやすいところがあるものの、それによる不便も若干あるというのは導入した感想です。CDK Pipelineの改善を待ちつつ、自作でデプロイ用のCode Pipelineを実装するのもいいかもしれません。
最後までお読みいただき、ありがとうございました。
参考
株式会社D2C d2c.co.jp のテックブログです。 D2Cは、NTTドコモと電通などの共同出資により設立されたデジタルマーケティング企業です。 ドコモの膨大なデータを活用した最適化を行える広告配信システムの開発をしています。
Discussion