[アップデート]AWS ProtonがCodeBuildプロビジョニングを通じてAWS CDKをサポートするようになりました

2022.11.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「AWS ProtonでAWS CDKが使えるようになった!」

環境の標準化に便利なサービスのProton。今年の3月にTerraformをサポートしました。

今回のアップデートでAWS Proton が CodeBuild プロビジョニングを通じて AWS CDK をサポートするようになりました。

AWS Proton now supports AWS CDK through CodeBuild provisioning

どういった流れで、AWS ProtonでAWS CDKを使えるのか試してみます。

やってみた

以下の記事を参考に試してみます。

Announcing AWS CDK Support and CodeBuild Provisioning for AWS Proton | Containers

全体のイメージは以下です。

サンプルコードのFork、ローカルへのClone

今回は用意されているサンプルコードを使用します。

記事中ではテンプレートをS3に置く方法を使っていますが、せっかくなのでGithubと同期させる方法でやってみます。

まずは、サンプルコードをForkします。

Githubと連携させるため、少しコードを変更します。

$ git clone <Forkしたリポジトリ名>
$ cd cdk/environment-templates/vpc-ecs-cluster
$ mkdir v1
$ mv infrastructure v1/
$ mv schema v1/
$ mv README.md v1/
$ git add .
$ git commit -m "update: dir"
$ git push origin HEAD

環境テンプレートのバージョニング機能の関係で、以下のディレクトリ構成にする必要があるためです。

*/{テンプレート名}/{バージョン}/テンプレート構成

今回であれば、以下のディレクトリ構成になっている必要があります。

$ pwd
<WORK DIR>/proton-codebuild-provisioning-examples/cdk/environment-templates
$ tree -L 3
.
└── vpc-ecs-cluster
    └── v1
        ├── README.md
        ├── infrastructure
        └── schema

サンプルコードの内容をみてみる

terraformやpulumiもリポジトリに含まれていますが、今回使用するのはcdk/environment-templates/vpc-ecs-clusterディレクトリ配下のものになります。

https://github.com/aws-containers/proton-codebuild-provisioning-examples/tree/main/cdk/environment-templates/vpc-ecs-cluster

$ cd cdk/environment-templates/vpc-ecs-cluster/v1
$ tree -L 2
.
├── README.md
├── infrastructure
│   ├── bin
│   ├── cdk-to-proton.sh
│   ├── cdk.json
│   ├── jest.config.js
│   ├── lib
│   ├── manifest.yaml
│   ├── package-lock.json
│   ├── package.json
│   ├── proton-inputs.json
│   ├── proton-outputs.json
│   └── tsconfig.json
└── schema
    └── schema.yaml

schema/schema.yaml

まずは、スキーマファイルです。 このファイルで、Protonのコンソール上から渡すパラメータを定義します。

このファイルの書き方については、CloudformationでProtonを使う場合と同様です。

schema/schema.yaml

schema:
  format:
    openapi: "3.0.0"
  environment_input_type: "EnvironmentInputs"
  types:
    EnvironmentInputs:
      type: object
      description: "Input properties for my environment"
      properties:
        vpc_cidr_block:
          type: string
          title: "VPC CIDR block"
          description: "VPC CIDR block, or default if left blank"
          default: "10.0.0.0/16"
        ec2_capacity:
          type: boolean
          title: "Enable EC2 Capacity"
          description: "Enable EC2 capacity for the cluster"
          default: false
        ec2_instance_type:
          type: string
          title: "EC2 instance types for cluster (if enabled)"
          description: "If EC2 capacity enabled, instance type to be used"
          default: "t3.medium"
        allow_ecs_exec:
          type: boolean
          title: "Enable ECS Execute command logging for the cluster"
          description: "Enable ECS Exec on the cluster"
          default: false
        enhanced_cluster_monitoring:
          type: boolean
          title: "Enable Container Insights for this cluster"
          default: false
          description: "Enable Cloudwatch Container Insights for the cluster"
        service_discovery_namespace:
          type: string
          title: "Service discovery namespace domain"
          description: "Service discovery domain"
      required:
        - service_discovery_namespace

スキーマファイル - AWS Proton

infrastructure/manifest.yaml

CodeBuildプロビジョニングを使うため、manifest.yamlの書き方がCloudFormationを使う場合と少し異なります。 ざっくり内容としては、cdk deployでプロビジョニング・cdk destroyでデプロビジョニングを行なっています。

outputs.jsonを生成して、ステータスの更新をProtonに通知しているようです。

infrastructure/manifest.yaml

infrastructure:
  templates:
    - rendering_engine: codebuild
      settings:
        image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
        runtimes:
          nodejs: 16
        provision:
          # Run when create/update is triggered for environment or service
          # Install dependencies
          - npm install
          - npm run cdk deploy -- --require-approval never
          # Script to convert CFN outputs into outputs for Proton
          - chmod +x ./cdk-to-proton.sh
          - cat proton-outputs.json | ./cdk-to-proton.sh > outputs.json
          # Notify AWS Proton of deployment status
          - aws proton notify-resource-deployment-status-change --resource-arn $RESOURCE_ARN --status IN_PROGRESS --outputs file://./outputs.json
        deprovision:
          # Install dependencies and destroy resources
          - npm install
          - npm run cdk destroy -- --force

Wrap up template files for AWS Proton - AWS Proton CodeBuild provisioning template bundle - AWS Proton

infrastructure配下(CDKのコード)

environment-templates/infrastructure配下にはAWS CDKのコードが入っています。 VPCとECSクラスターを作成するといった内容です。

通常のAWS CDKのコードと異なる点は、proton-inputs.jsonで環境作成時に与えるパラメータを与えているところです。 proton-inputs.jsonに関しては、プロビジョニング時にコンソールから渡した値を元に生成されます。

CDKのコードでエラーを出さないために、仮のものとしてリポジトリ内に含んでいるのかと思います

proton-inputs.json

{
  "environment": {
    "name": "cdk-env-demo",
    "inputs": {
      "vpc_cidr_block": "10.0.0.0/16",
      "ec2_capacity": false,
      "ec2_instance_type": "t3.medium",
      "allow_ecs_exec": false,
      "enhanced_cluster_monitoring": false,
      "service_discovery_namespace": "proton.cdkdemo.svc"
    }
  }
}

infrastructure/lib/vpc-ecs-cluster-stack.ts

import { Stack, StackProps, CfnOutput } from "aws-cdk-lib";
import { Construct } from "constructs";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as autoscaling from "aws-cdk-lib/aws-autoscaling";
import * as iam from "aws-cdk-lib/aws-iam";
import input from "../proton-inputs.json";

export class VpcEcsClusterStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const environmentInputs = input.environment.inputs;
    const stackName = props.stackName ?? input.environment.name;

    const vpc = new ec2.Vpc(this, "ProtonVPC", {
      vpcName: stackName,
            // proton-inputs.jsonの値を渡している
      cidr: environmentInputs.vpc_cidr_block,
    });
// 省略

Githubリポジトリとの接続

GithubのリポジトリをProtonから使えるようにするためにリンクを作成します。

GithubアカウントとCodeStar接続が存在しない場合は、以下の手順を参考にGithubアカウントと接続します。

GitHub 接続 - AWS CodePipeline

手順完了後にステータスが利用可能になってればOKです。

Protonの画面に戻って、「リポジトリの作成」を選択します。

必要な情報を入力して、リポジトリを作成します。

環境テンプレートの作成

サイドバー>テンプレート> 環境テンプレート>環境テンプレートの作成を選択します。 テンプレート定義リポジトリは前の手順で作成したリポジトリを指定します。

環境テンプレートの名前は、vpc-ecs-clusterとします。

環境テンプレートの名前は環境テンプレートのディレクトリ名と一致させる必要があります。 (異なっている場合、バージョンが公開できません)

テンプレートを作成するだけでは使用できないため、テンプレートのバージョンを公開します。ステータスがPublishedになればOKです。

CodeBuild用 IAMロールの用意

ProtonでAWS CDKを使用するためには、CodeBuildを使用する必要があります。 そのため、CodeBuild用のIAMロールが必要です。

以下コマンドを実行して、IAMロールを作成します。

$ aws iam create-role --role-name AWSProtonCodeBuildProvisioning --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"codebuild.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
$ aws iam attach-role-policy --role-name AWSProtonCodeBuildProvisioning --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

aws iam attach-role-policy --role-name AWSProtonCodeBuildProvisioning --policy-arn arn:aws:iam::aws:policy/AWSProtonCodeBuildProvisioningBasicAccess

環境の作成

それでは登録したテンプレートを使って環境を作成します。

サイドバー >環境 > 環境を作成するを選択します。

作成した環境テンプレートを使用します。

環境の名前やIAMロールの情報を設定して、次に進みます。

カスタム設定の画面が出るので、必要な値を設定して次に進みます。 最後に確認画面が出ます。問題なければ作成を行います。

成功するとCloudformationスタックが作成されたことを確認できます。(CodeBuildスタックとCDKで定義したECS,VPCのスタック)

クリーンアップ

Protonのコンソールから環境を削除すると、上記で作成したCloudformationのスタックも削除されます。

おわりに

CodeBuildプロビジョニングで対応するIaCツールが増えて嬉しいです。

AWS CDKへの対応はAWS Proton発表時から要望が多かった機能なので、待ち望んでいた方も多いはずです。

Integrate with AWS Cloud Development Kit (CDK) · Issue #21 · aws/aws-proton-public-roadmap

今回はCDKを紹介しましたが、同様にCodeBuildプロビジョニングでPulumiも使えるようです。

以上、AWS事業本部の佐藤(@chari7311)でした。