インフラ

AWS CDKのADVANCED WORKSHOPやってみた

cdk

こんにちは、ちゃりおです。

CDK Pipelineをざっくり試したいと思っていて、なにかいいチュートリアルないかと探していたら。「AWS CDK ADVANCED WORKSHOP」なるものを発見しました。
CDK Pipelineやパッケージ化を自分で手を動かして学ぶのによい教材だったので紹介します。

ワークショップの概要

  • マルチリージョン構成の作成
  • カスタムリソースの使用
  • L1を使ったリソースの更新
  • CDKコンストラクトのパッケージ化
  • CDKパイプラインを使用したデプロイ

必要な時間: 2~3時間

Create Our Sample Application

作成するリソースはこんな感じです。

Source BucketとTarget BucketではS3のレプリケーションが行われています。
Regionで作成するリソースごとにConstructが分かれています。

「us-east-1」で作成したKMSのキーを「us-east-2」で使用する

2つのリージョンに配置するS3はレプリケーションしています。
レプリケーションのために、source側(us-east-1)でtarget側(us-east-2)のS3のKMSキーを取得可能な必要があります。

このハンズオンでは取得するために以下を行っています。

  • target側: パラメーターストアを作成・KMSのキーARNをパラメーターストアに保存
  • source側: Custom Resourceを使用して別リージョンのパラメーターストアからKMSキーARN取得

該当部分を抜き出しました。

# multi-region-s3-crr-kms-cmk-target/lib/index.ts
    new ssm.StringParameter(this, 'MyTargetKeyIdSSMParam', {
       parameterName: parameterName,
       description: 'The KMS Key Id for the target stack',
       stringValue: targetKmsKey.keyArn
     });

    this.targetBucket = targetBucket;
    this.targetKeyIdSsmParameterName = parameterName;
# multi-region-s3-crr-kms-cmk-source/lib/index.ts
    const stack = cdk.Stack.of(this);
    const parameterArn = stack.formatArn({
      account: stack.account,
      region: props.targetRegion,
      resource: 'parameter',
      resourceName: props.targetKeyIdSsmParameterName,
      service: 'ssm'
    });
    
    const targetKeyLookupCR = new cr.AwsCustomResource(this, 'TargetKeyLookup', {
      onUpdate: {   // will also be called for a CREATE event
        service: 'SSM',
        action: 'getParameter',
        parameters: {
          Name: props.targetKeyIdSsmParameterName
        },
        region: props.targetRegion,
        physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString())
      },
      policy: cr.AwsCustomResourcePolicy.fromSdkCalls({resources: [parameterArn]})
    });

パッケージ化したConstructを使用する

targetとsourceのコンストラクトをパッケージ化して使用します。
jsiiを使用してそれぞれパッケージ化しました。
AWS CDK Advanced Workshop > Create Our Sample Application > Replication Target Construct > jsii and package.json

パッケージ使用する側のコードはこんな感じです。だいぶスッキリしましたね。

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { MultiRegionS3CrrKmsCmkSourceStack } from '../lib/multi-region-s3-crr-kms-cmk-source-stack';
import { MultiRegionS3CrrKmsCmkTargetStack } from '../lib/multi-region-s3-crr-kms-cmk-target-stack';

const accountId = '';

const app = new cdk.App();

const targetStack = new MultiRegionS3CrrKmsCmkTargetStack(app, 'MultiRegionS3CrrKmsCmkTarget', {
  env: { account: accountId, region: 'us-east-2' },
});

const sourceStack = new MultiRegionS3CrrKmsCmkSourceStack(app, 'MultiRegionS3CrrKmsCmkSource', {
  env: { account: accountId, region: 'us-east-1' },
  targetBucket: targetStack.targetBucket,
  targetKeyIdSsmParameterName: targetStack.targetKeyIdSsmParameterName,
  targetRegion: targetStack.region
});

sourceStack.addDependency(targetStack);

ADD CDK PIPELINES

CDK Pipelineを使用して、自動デプロイを実現します。

  1. CodeCommitへPushされる
  2. CodePipeline発火
  3. PreProd環境へデプロイ
  4. 手動承認
  5. Prod環境へデプロイ

import * as codecommit from "@aws-cdk/aws-codecommit"
import * as codepipeline from "@aws-cdk/aws-codepipeline"
import * as codepipeline_actions from "@aws-cdk/aws-codepipeline-actions"
import { Construct, SecretValue, Stack, StackProps } from "@aws-cdk/core"
import { CdkPipeline, SimpleSynthAction } from "@aws-cdk/pipelines"

import { MultiRegionS3CrrKmsCmkStage } from "./multi-region-s3-crr-kms-cmk-stage"

export class MultiRegionS3CrrKmsCmkPipelineStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps ){
        super(scope, id, props)
        const sourceArtifact = new codepipeline.Artifact()
        const cloudAssemblyArtifact = new codepipeline.Artifact()
        
        const pipeline = new CdkPipeline(this, "Pipeline", {
            pipelineName: "MultiRegionS3CrrKmsCmkPipeline",
            cloudAssemblyArtifact,
            sourceAction: new codepipeline_actions.CodeCommitSourceAction({
                actionName: "CodeCommit",
                repository: codecommit.Repository.fromRepositoryName(this, 
                "CodeCommitRepo", 
                "cdk-pipelines-workshop",
                ),
                output: sourceArtifact
            }),
            synthAction: SimpleSynthAction.standardNpmSynth({
                sourceArtifact,
                cloudAssemblyArtifact,
                buildCommand: "npm run build"
            })
        })
        const preProdStage = pipeline.addApplicationStage(new MultiRegionS3CrrKmsCmkStage(this, "PreProd", {
            env: { account: props?.env?.account, region: "us-east-1" }
        }))
        preProdStage.addManualApprovalAction()
        pipeline.addApplicationStage(new MultiRegionS3CrrKmsCmkStage(this, 'Production', {
          env: { account: props?.env?.account, region: 'us-east-1' }
        }));
    }
}

感想

パッケージ化や自動デプロイについて、学ぶことができました。
CDK Pipelineを使って見たいと、思っていたのでちょうど良かったです。
通常のCDK Workshopをやってもう少し学びたい方におすすめです。

Amzonで「AWS」の本を見てみる

楽天で「AWS」の本をみてみる!!

CodeBuildを使ってDBマイグレーションを実行してみるこんにちは、ちゃりおです。 CodeBuildからDBマイグレーションを実行する方法についてです。 Jenkinsで実行する方法や、...
Github Actionsを使ってCDKを自動デプロイするこんにちは、ちゃりおです。 CDK手動反映だと反映漏れが発生することもあり、今回はGithub Actionsを使ってCDKを自動デプ...
ECR
CDKで作成したECRをスタック削除時に同時に削除されるようにするこんにちは、ちゃりおです。 デフォルトではCDKでECRを作成して、「cdk destroy」で削除したときにECRのリポジトリが残り...