🤖

CDK Pipelineを導入する時に「aws:cdk:path」にハマった話

2023/06/22に公開

はじめに

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で複数の環境にデプロイする場合は、複数のステージ(DevStagePreProdStageProdStage、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を実装するのもいいかもしれません。

最後までお読みいただき、ありがとうございました。

参考

https://catalog.us-east-1.prod.workshops.aws/workshops/5195ab7c-5ded-4ee2-a1c5-775300717f42/en-US/cicd/cdk-pipelines
https://dev.classmethod.jp/articles/cdk-practice-6-metadata/
https://docs.aws.amazon.com/cdk/v2/guide/hello_world.html#hello_world_tutorial_synth

D2C m-tech

Discussion