CDK Pipelines とは

# 初めに

AWS CDK について学習を進めると CDK Pipelines というワードに出会います。

CDK の[開発者ガイドページ](https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/cdk_pipeline.html)には次のような説明があります。

> [CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html) は、 AWS CDK アプリケーションを問題なく継続的に配信するためのコンストラクトライブラリモジュールです。 AWS CDK アプリのソースコードを 、 AWS CodeCommit GitHub、または にチェックインするたびに AWS CodeStar、CDK Pipelines は新しいバージョンを自動的に構築、テスト、デプロイできます。
> 

CDK と CodePipeline に関連するモジュールだと推測できますが、具体的な内容はよく分かりません。

CDK Pipelines の ReadMe ページには以下のような説明があります。

> A construct library for painless Continuous Delivery of CDK applications.
> 
> 
> CDK Pipelines is an *opinionated construct library*. It is purpose-built to deploy one or more copies of your CDK applications using CloudFormation with a minimal amount of effort on your part. It is *not* intended to support arbitrary deployment pipelines, and very specifically it is not built to use CodeDeploy to deploy applications to instances, or deploy your custom-built ECR images to an ECS cluster directly: use CDK file assets with CloudFormation Init for instances, or CDK container assets for ECS clusters instead.
> 
> ＜Google翻訳＞
> 
> CDK アプリケーションの継続的デリバリーのための構築ライブラリ。
> 
> CDK Pipelines は自立型構築ライブラリです。 これは、CloudFormation を使用して CDK アプリケーションの 1 つ以上のコピーを最小限の労力でデプロイすることを目的としています。 これは、任意のデプロイメント パイプラインをサポートすることを目的としたものではなく、具体的には、CodeDeploy を使用してアプリケーションをインスタンスにデプロイしたり、カスタム構築された ECR イメージを ECS クラスターに直接デプロイしたりするように構築されていません。インスタンスには CloudFormation Init で CDK ファイル アセットを使用します。 代わりに、ECS クラスターの CDK コンテナ アセットを使用してください。
> 

(/・ω・)/　なんのこっちゃねん

# CDK と CodePipeline

CDK Pipelines について理解するためには、AWSの以下の2個のサービスを知る必要があります。

1. AWS CDK
2. AWS CodePipeline

## AWS CDK

AWS CDK は AWS 専用の IaCツールです。Typescript/Python などのプログラミング言語でAWSサービスの構成を定義することができます。
例えば、次のソースコードはVPCとサブネットを作成し、プライベートサブネットに EC2を構築しています。

```tsx
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  aws_ec2 as ec2,
} from 'aws-cdk-lib';

const NAME = 'cdk-pipelines';

export class VpcWithEc2Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = this.createVpc();
    const instance = this.createEc2(vpc);
  }

  createVpc() {
    return new ec2.Vpc(this, 'Vpc', {
      ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
      vpcName: `${NAME}-vpc`,
      subnetConfiguration: [
        { cidrMask: 24, name: 'public', subnetType: ec2.SubnetType.PUBLIC },
        { cidrMask: 24, name: 'application', subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      ]
    });
  }

  createEc2(vpc:ec2.Vpc){
    return new ec2.Instance(this, 'Instance', {
      vpc: vpc,
      vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      instanceName: `${NAME}-ec2`,
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO),
      machineImage: ec2.MachineImage.latestAmazonLinux2023(),
    });
  }
}

```

CDK のデプロイは Node.js などがインストールされたローカル環境などで cdk deploy コマンドで行います。

<details><summary>デプロイログ</summary>
    
    > cdk deploy
    
    ✨  Synthesis time: 4.5s
    
    This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
    Please confirm you intend to make the following modifications:
    
    IAM Statement Changes
    ┌───┬─────────────────────────────────────────────────────┬────────┬─────────────────────────────────────────────────────┬───────────────────────────────────────────────────────┬───────────┐ 
    │   │ Resource                                            │ Effect │ Action                                              │ Principal                                             │ Condition │ 
    ├───┼─────────────────────────────────────────────────────┼────────┼─────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┼───────────┤ 
    │ + │ ${Custom::VpcRestrictDefaultSGCustomResourceProvide │ Allow  │ sts:AssumeRole                                      │ Service:lambda.amazonaws.com                          │           │ 
    │   │ r/Role.Arn}                                         │        │                                                     │                                                       │           │ 
    ├───┼─────────────────────────────────────────────────────┼────────┼─────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┼───────────┤ 
    │ + │ ${Instance/InstanceRole.Arn}                        │ Allow  │ sts:AssumeRole                                      │ Service:ec2.amazonaws.com                             │           │ 
    ├───┼─────────────────────────────────────────────────────┼────────┼─────────────────────────────────────────────────────┼───────────────────────────────────────────────────────┼───────────┤ 
    │ + │ arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::Acc │ Allow  │ ec2:AuthorizeSecurityGroupEgress                    │ AWS:${Custom::VpcRestrictDefaultSGCustomResourceProvi │           │ 
    │   │ ountId}:security-group/${Vpc8378EB38.DefaultSecurit │        │ ec2:AuthorizeSecurityGroupIngress                   │ der/Role}                                             │           │ 
    │   │ yGroup}                                             │        │ ec2:RevokeSecurityGroupEgress                       │                                                       │           │ 
    │   │                                                     │        │ ec2:RevokeSecurityGroupIngress                      │                                                       │           │ 
    └───┴─────────────────────────────────────────────────────┴────────┴─────────────────────────────────────────────────────┴───────────────────────────────────────────────────────┴───────────┘ 
    IAM Policy Changes
    ┌───┬────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────┐
    │   │ Resource                                                   │ Managed Policy ARN                                                                           │
    ├───┼────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────┤
    │ + │ ${Custom::VpcRestrictDefaultSGCustomResourceProvider/Role} │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"} │
    └───┴────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────┘
    Security Group Changes
    ┌───┬───────────────────────────────────────────┬─────┬────────────┬─────────────────┐
    │   │ Group                                     │ Dir │ Protocol   │ Peer            │
    ├───┼───────────────────────────────────────────┼─────┼────────────┼─────────────────┤
    │ + │ ${Instance/InstanceSecurityGroup.GroupId} │ Out │ Everything │ Everyone (IPv4) │
    └───┴───────────────────────────────────────────┴─────┴────────────┴─────────────────┘
    (NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
    
    Do you wish to deploy these changes (y/n)? y
    VpcWithEc2Stack: deploying... [1/1]
    VpcWithEc2Stack: creating CloudFormation changeset...
    VpcWithEc2Stack |  0/32 | 13:48:51 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | Vpc/IGW (VpcIGWD7BA715C) Resource creation Initiated
    VpcWithEc2Stack |  1/32 | 13:48:51 | CREATE_COMPLETE      | AWS::CDK::Metadata                    | CDKMetadata/Default (CDKMetadata) 
    VpcWithEc2Stack |  1/32 | 13:48:52 | CREATE_IN_PROGRESS   | AWS::EC2::VPC                         | Vpc (Vpc8378EB38) Resource creation Initiated
    VpcWithEc2Stack |  1/32 | 13:48:41 | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack            | VpcWithEc2Stack User Initiated
    VpcWithEc2Stack |  1/32 | 13:48:46 | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack            | VpcWithEc2Stack User Initiated
    VpcWithEc2Stack |  1/32 | 13:48:50 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | Vpc/IGW (VpcIGWD7BA715C) 
    VpcWithEc2Stack |  1/32 | 13:48:50 | CREATE_IN_PROGRESS   | AWS::EC2::VPC                         | Vpc (Vpc8378EB38) 
    VpcWithEc2Stack |  1/32 | 13:48:50 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | Vpc/publicSubnet2/EIP (VpcpublicSubnet2EIP811E07A7) 
    VpcWithEc2Stack |  1/32 | 13:48:50 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | Vpc/publicSubnet1/EIP (VpcpublicSubnet1EIP411541E6) 
    VpcWithEc2Stack |  1/32 | 13:48:50 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | CDKMetadata/Default (CDKMetadata) 
    VpcWithEc2Stack |  1/32 | 13:48:50 | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | Instance/InstanceRole (InstanceInstanceRoleE9785DE5) 
    VpcWithEc2Stack |  1/32 | 13:48:51 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | Vpc/publicSubnet2/EIP (VpcpublicSubnet2EIP811E07A7) Resource creation Initiated
    VpcWithEc2Stack |  1/32 | 13:48:51 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
    VpcWithEc2Stack |  1/32 | 13:48:51 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | Vpc/publicSubnet1/EIP (VpcpublicSubnet1EIP411541E6) Resource creation Initiated
    VpcWithEc2Stack |  1/32 | 13:48:51 | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | Instance/InstanceRole (InstanceInstanceRoleE9785DE5) Resource creation Initiated
    VpcWithEc2Stack |  1/32 | 13:48:52 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | Vpc/publicSubnet2/EIP (VpcpublicSubnet2EIP811E07A7) Eventual consistency check initiated
    VpcWithEc2Stack |  1/32 | 13:48:52 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | Vpc/publicSubnet1/EIP (VpcpublicSubnet1EIP411541E6) Eventual consistency check initiated   
    VpcWithEc2Stack |  1/32 | 13:48:52 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | Vpc/IGW (VpcIGWD7BA715C) Eventual consistency check initiated
    VpcWithEc2Stack |  2/32 | 13:49:03 | CREATE_COMPLETE      | AWS::EC2::VPC                         | Vpc (Vpc8378EB38) 
    VpcWithEc2Stack |  2/32 | 13:49:03 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/publicSubnet2/RouteTable (VpcpublicSubnet2RouteTableC5A6DF77)
    VpcWithEc2Stack |  2/32 | 13:49:03 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/applicationSubnet2/RouteTable (VpcapplicationSubnet2RouteTable17378AED)
    VpcWithEc2Stack |  2/32 | 13:49:03 | CREATE_IN_PROGRESS   | AWS::EC2::VPCGatewayAttachment        | Vpc/VPCGW (VpcVPCGWBF912B6E)
    VpcWithEc2Stack |  2/32 | 13:49:03 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/publicSubnet1/RouteTable (VpcpublicSubnet1RouteTable15C15F8E)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::EC2::SecurityGroup               | Instance/InstanceSecurityGroup (InstanceInstanceSecurityGroupF0E2D5BE)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/applicationSubnet1/RouteTable (VpcapplicationSubnet1RouteTableF03E8296)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/publicSubnet2/Subnet (VpcpublicSubnet2SubnetE34B022A)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/applicationSubnet1/Subnet (VpcapplicationSubnet1Subnet8B68205B)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/publicSubnet1/Subnet (VpcpublicSubnet1Subnet2BB74ED7)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/applicationSubnet2/Subnet (VpcapplicationSubnet2Subnet29670962)
    VpcWithEc2Stack |  2/32 | 13:49:04 | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | Custom::VpcRestrictDefaultSGCustomResourceProvider/Role (CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0)
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/publicSubnet2/RouteTable (VpcpublicSubnet2RouteTableC5A6DF77) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/applicationSubnet1/RouteTable (VpcapplicationSubnet1RouteTableF03E8296) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::VPCGatewayAttachment        | Vpc/VPCGW (VpcVPCGWBF912B6E) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/applicationSubnet2/RouteTable (VpcapplicationSubnet2RouteTable17378AED) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/publicSubnet1/RouteTable (VpcpublicSubnet1RouteTable15C15F8E) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/publicSubnet1/Subnet (VpcpublicSubnet1Subnet2BB74ED7) Resource creation Initiated      
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/applicationSubnet2/Subnet (VpcapplicationSubnet2Subnet29670962) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/applicationSubnet1/RouteTable (VpcapplicationSubnet1RouteTableF03E8296) Eventual consistency check initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/publicSubnet2/RouteTable (VpcpublicSubnet2RouteTableC5A6DF77) Eventual consistency check initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/applicationSubnet1/Subnet (VpcapplicationSubnet1Subnet8B68205B) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:05 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/publicSubnet2/Subnet (VpcpublicSubnet2SubnetE34B022A) Resource creation Initiated      
    VpcWithEc2Stack |  2/32 | 13:49:06 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/applicationSubnet2/RouteTable (VpcapplicationSubnet2RouteTable17378AED) Eventual consistency check initiated
    VpcWithEc2Stack |  2/32 | 13:49:06 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | Vpc/publicSubnet1/RouteTable (VpcpublicSubnet1RouteTable15C15F8E) Eventual consistency check initiated
    VpcWithEc2Stack |  2/32 | 13:49:06 | CREATE_IN_PROGRESS   | AWS::IAM::Role                        | Custom::VpcRestrictDefaultSGCustomResourceProvider/Role (CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0) Resource creation Initiated
    VpcWithEc2Stack |  2/32 | 13:49:06 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/applicationSubnet2/Subnet (VpcapplicationSubnet2Subnet29670962) Eventual consistency check initiated
    VpcWithEc2Stack |  2/32 | 13:49:06 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | Vpc/applicationSubnet1/Subnet (VpcapplicationSubnet1Subnet8B68205B) Eventual consistency check initiated
    VpcWithEc2Stack |  3/32 | 13:49:07 | CREATE_COMPLETE      | AWS::EC2::VPCGatewayAttachment        | Vpc/VPCGW (VpcVPCGWBF912B6E)
    VpcWithEc2Stack |  3/32 | 13:49:07 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/applicationSubnet2/RouteTableAssociation (VpcapplicationSubnet2RouteTableAssociationF25110CC)
    VpcWithEc2Stack |  3/32 | 13:49:07 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/applicationSubnet1/RouteTableAssociation (VpcapplicationSubnet1RouteTableAssociation75D5245D)
    VpcWithEc2Stack |  4/32 | 13:49:07 | CREATE_COMPLETE      | AWS::EC2::InternetGateway             | Vpc/IGW (VpcIGWD7BA715C) 
    VpcWithEc2Stack |  5/32 | 13:49:07 | CREATE_COMPLETE      | AWS::EC2::EIP                         | Vpc/publicSubnet2/EIP (VpcpublicSubnet2EIP811E07A7)
    VpcWithEc2Stack |  6/32 | 13:49:07 | CREATE_COMPLETE      | AWS::EC2::EIP                         | Vpc/publicSubnet1/EIP (VpcpublicSubnet1EIP411541E6)
    VpcWithEc2Stack |  7/32 | 13:49:08 | CREATE_COMPLETE      | AWS::IAM::Role                        | Instance/InstanceRole (InstanceInstanceRoleE9785DE5)
    VpcWithEc2Stack |  7/32 | 13:49:08 | CREATE_IN_PROGRESS   | AWS::EC2::SecurityGroup               | Instance/InstanceSecurityGroup (InstanceInstanceSecurityGroupF0E2D5BE) Resource creation Initiated
    VpcWithEc2Stack |  8/32 | 13:49:08 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | Vpc/applicationSubnet2/Subnet (VpcapplicationSubnet2Subnet29670962)
    VpcWithEc2Stack |  8/32 | 13:49:08 | CREATE_IN_PROGRESS   | AWS::IAM::InstanceProfile             | Instance/InstanceProfile (InstanceInstanceProfileAB5AEF02)
    VpcWithEc2Stack |  9/32 | 13:49:08 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | Vpc/applicationSubnet1/Subnet (VpcapplicationSubnet1Subnet8B68205B)
    VpcWithEc2Stack | 10/32 | 13:49:08 | CREATE_COMPLETE      | AWS::EC2::SecurityGroup               | Instance/InstanceSecurityGroup (InstanceInstanceSecurityGroupF0E2D5BE)
    VpcWithEc2Stack | 10/32 | 13:49:08 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/applicationSubnet2/RouteTableAssociation (VpcapplicationSubnet2RouteTableAssociationF25110CC) Resource creation Initiated
    VpcWithEc2Stack | 10/32 | 13:49:08 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/applicationSubnet1/RouteTableAssociation (VpcapplicationSubnet1RouteTableAssociation75D5245D) Resource creation Initiated
    VpcWithEc2Stack | 11/32 | 13:49:08 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | Vpc/publicSubnet2/Subnet (VpcpublicSubnet2SubnetE34B022A)
    VpcWithEc2Stack | 12/32 | 13:49:08 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | Vpc/publicSubnet1/Subnet (VpcpublicSubnet1Subnet2BB74ED7)
    VpcWithEc2Stack | 13/32 | 13:49:09 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | Vpc/applicationSubnet2/RouteTableAssociation (VpcapplicationSubnet2RouteTableAssociationF25110CC)
    VpcWithEc2Stack | 14/32 | 13:49:09 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | Vpc/applicationSubnet1/RouteTableAssociation (VpcapplicationSubnet1RouteTableAssociation75D5245D)
    VpcWithEc2Stack | 14/32 | 13:49:09 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/publicSubnet2/RouteTableAssociation (VpcpublicSubnet2RouteTableAssociationCCE257FF)    
    VpcWithEc2Stack | 14/32 | 13:49:09 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/publicSubnet1/RouteTableAssociation (VpcpublicSubnet1RouteTableAssociation4E83B6E4)    
    VpcWithEc2Stack | 14/32 | 13:49:10 | CREATE_IN_PROGRESS   | AWS::IAM::InstanceProfile             | Instance/InstanceProfile (InstanceInstanceProfileAB5AEF02) Resource creation Initiated     
    VpcWithEc2Stack | 14/32 | 13:49:11 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/publicSubnet2/RouteTableAssociation (VpcpublicSubnet2RouteTableAssociationCCE257FF) Resource creation Initiated
    VpcWithEc2Stack | 14/32 | 13:49:11 | CREATE_IN_PROGRESS   | AWS::IAM::InstanceProfile             | Instance/InstanceProfile (InstanceInstanceProfileAB5AEF02) Eventual consistency check initiated
    VpcWithEc2Stack | 14/32 | 13:49:11 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | Vpc/publicSubnet1/RouteTableAssociation (VpcpublicSubnet1RouteTableAssociation4E83B6E4) Resource creation Initiated
    VpcWithEc2Stack | 15/32 | 13:49:11 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | Vpc/publicSubnet2/RouteTableAssociation (VpcpublicSubnet2RouteTableAssociationCCE257FF)    
    VpcWithEc2Stack | 16/32 | 13:49:11 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | Vpc/publicSubnet1/RouteTableAssociation (VpcpublicSubnet1RouteTableAssociation4E83B6E4)    
    VpcWithEc2Stack | 17/32 | 13:49:15 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | Vpc/publicSubnet2/RouteTable (VpcpublicSubnet2RouteTableC5A6DF77) 
    VpcWithEc2Stack | 18/32 | 13:49:15 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | Vpc/applicationSubnet1/RouteTable (VpcapplicationSubnet1RouteTableF03E8296)
    VpcWithEc2Stack | 19/32 | 13:49:15 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | Vpc/applicationSubnet2/RouteTable (VpcapplicationSubnet2RouteTable17378AED)
    VpcWithEc2Stack | 20/32 | 13:49:16 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | Vpc/publicSubnet1/RouteTable (VpcpublicSubnet1RouteTable15C15F8E)
    VpcWithEc2Stack | 20/32 | 13:49:16 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/publicSubnet2/DefaultRoute (VpcpublicSubnet2DefaultRoute732F0BEB)
    VpcWithEc2Stack | 20/32 | 13:49:16 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/publicSubnet1/DefaultRoute (VpcpublicSubnet1DefaultRouteB88F9E93)
    VpcWithEc2Stack | 20/32 | 13:49:17 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/publicSubnet2/DefaultRoute (VpcpublicSubnet2DefaultRoute732F0BEB) Resource creation Initiated
    VpcWithEc2Stack | 21/32 | 13:49:17 | CREATE_COMPLETE      | AWS::EC2::Route                       | Vpc/publicSubnet2/DefaultRoute (VpcpublicSubnet2DefaultRoute732F0BEB) 
    VpcWithEc2Stack | 21/32 | 13:49:18 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/publicSubnet1/DefaultRoute (VpcpublicSubnet1DefaultRouteB88F9E93) Resource creation Initiated
    VpcWithEc2Stack | 21/32 | 13:49:18 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | Vpc/publicSubnet2/NATGateway (VpcpublicSubnet2NATGateway4A29FD4F)
    VpcWithEc2Stack | 22/32 | 13:49:18 | CREATE_COMPLETE      | AWS::EC2::Route                       | Vpc/publicSubnet1/DefaultRoute (VpcpublicSubnet1DefaultRouteB88F9E93)
    VpcWithEc2Stack | 22/32 | 13:49:19 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | Vpc/publicSubnet1/NATGateway (VpcpublicSubnet1NATGatewayA036E8A6)
    VpcWithEc2Stack | 22/32 | 13:49:19 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | Vpc/publicSubnet2/NATGateway (VpcpublicSubnet2NATGateway4A29FD4F) Resource creation Initiated
    VpcWithEc2Stack | 22/32 | 13:49:20 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | Vpc/publicSubnet1/NATGateway (VpcpublicSubnet1NATGatewayA036E8A6) Resource creation Initiated
    VpcWithEc2Stack | 22/32 | 13:49:20 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | Vpc/publicSubnet2/NATGateway (VpcpublicSubnet2NATGateway4A29FD4F) Eventual consistency check initiated
    VpcWithEc2Stack | 22/32 | 13:49:21 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | Vpc/publicSubnet1/NATGateway (VpcpublicSubnet1NATGatewayA036E8A6) Eventual consistency check initiated
    VpcWithEc2Stack | 23/32 | 13:49:23 | CREATE_COMPLETE      | AWS::IAM::Role                        | Custom::VpcRestrictDefaultSGCustomResourceProvider/Role (CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0)
    VpcWithEc2Stack | 23/32 | 13:49:24 | CREATE_IN_PROGRESS   | AWS::Lambda::Function                 | Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler (CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E)
    VpcWithEc2Stack | 23/32 | 13:49:26 | CREATE_IN_PROGRESS   | AWS::Lambda::Function                 | Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler (CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E) Resource creation Initiated
    VpcWithEc2Stack | 23/32 | 13:49:26 | CREATE_IN_PROGRESS   | AWS::Lambda::Function                 | Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler (CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E) Eventual consistency check initiated
    VpcWithEc2Stack | 24/32 | 13:49:31 | CREATE_COMPLETE      | AWS::Lambda::Function                 | Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler (CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E)
    VpcWithEc2Stack | 24/32 | 13:49:32 | CREATE_IN_PROGRESS   | Custom::VpcRestrictDefaultSG          | Vpc/RestrictDefaultSecurityGroupCustomResource/Default (VpcRestrictDefaultSecurityGroupCustomResourceC73DA2BE)
    VpcWithEc2Stack | 24/32 | 13:49:42 | CREATE_IN_PROGRESS   | Custom::VpcRestrictDefaultSG          | Vpc/RestrictDefaultSecurityGroupCustomResource/Default (VpcRestrictDefaultSecurityGroupCustomResourceC73DA2BE) Resource creation Initiated
    VpcWithEc2Stack | 25/32 | 13:49:42 | CREATE_COMPLETE      | Custom::VpcRestrictDefaultSG          | Vpc/RestrictDefaultSecurityGroupCustomResource/Default (VpcRestrictDefaultSecurityGroupCustomResourceC73DA2BE)
    25/32 Currently in progress: VpcWithEc2Stack, CDKMetadata, InstanceInstanceProfileAB5AEF02, VpcpublicSubnet2NATGateway4A29FD4F, VpcpublicSubnet1NATGatewayA036E8A6
    VpcWithEc2Stack | 26/32 | 13:50:49 | CREATE_COMPLETE      | AWS::EC2::NatGateway                  | Vpc/publicSubnet2/NATGateway (VpcpublicSubnet2NATGateway4A29FD4F) 
    VpcWithEc2Stack | 26/32 | 13:50:50 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/applicationSubnet2/DefaultRoute (VpcapplicationSubnet2DefaultRoute928D347B)
    VpcWithEc2Stack | 26/32 | 13:50:52 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/applicationSubnet2/DefaultRoute (VpcapplicationSubnet2DefaultRoute928D347B) Resource creation Initiated
    VpcWithEc2Stack | 27/32 | 13:50:52 | CREATE_COMPLETE      | AWS::EC2::Route                       | Vpc/applicationSubnet2/DefaultRoute (VpcapplicationSubnet2DefaultRoute928D347B)
    VpcWithEc2Stack | 28/32 | 13:50:55 | CREATE_COMPLETE      | AWS::EC2::NatGateway                  | Vpc/publicSubnet1/NATGateway (VpcpublicSubnet1NATGatewayA036E8A6) 
    VpcWithEc2Stack | 28/32 | 13:50:56 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/applicationSubnet1/DefaultRoute (VpcapplicationSubnet1DefaultRouteD1F37131)
    VpcWithEc2Stack | 28/32 | 13:50:58 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | Vpc/applicationSubnet1/DefaultRoute (VpcapplicationSubnet1DefaultRouteD1F37131) Resource creation Initiated
    VpcWithEc2Stack | 29/32 | 13:50:58 | CREATE_COMPLETE      | AWS::EC2::Route                       | Vpc/applicationSubnet1/DefaultRoute (VpcapplicationSubnet1DefaultRouteD1F37131)
    VpcWithEc2Stack | 30/32 | 13:51:20 | CREATE_COMPLETE      | AWS::IAM::InstanceProfile             | Instance/InstanceProfile (InstanceInstanceProfileAB5AEF02) 
    VpcWithEc2Stack | 30/32 | 13:51:21 | CREATE_IN_PROGRESS   | AWS::EC2::Instance                    | Instance (InstanceC1063A87)
    VpcWithEc2Stack | 30/32 | 13:51:23 | CREATE_IN_PROGRESS   | AWS::EC2::Instance                    | Instance (InstanceC1063A87) Resource creation Initiated
    VpcWithEc2Stack | 31/32 | 13:51:55 | CREATE_COMPLETE      | AWS::EC2::Instance                    | Instance (InstanceC1063A87) 
    VpcWithEc2Stack | 32/32 | 13:51:56 | CREATE_COMPLETE      | AWS::CloudFormation::Stack            | VpcWithEc2Stack 
    
     ✅  VpcWithEc2Stack
    
    ✨  Deployment time: 199.77s
    
    Stack ARN:
    arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxx:stack/VpcWithEc2Stack/a03e0b00-e419-11ee-80ea-06f0795242c1
    
    ✨  Total time: 204.28s

</details>
<br>
CDK 独自の機能によってデプロイを行うように見えますが、実際は CDK プログラムから Cloudformation テンプレートファイルを作成し、Cloudformation サービスを利用してデプロイを行っています。テンプレートファイルは cdk synth コマンドでも作成でき cdk.out フォルダに格納されます。

![CDKデプロイの実態.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/a0c65a22-5e88-cf87-4a76-2f4475cd3cfb.png)


マネジメントコンソールの Cloudformation から該当スタックの存在を確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/e76484db-121a-41b0-231d-ff39025cc462.png)


## AWS CodePipeline

AWS CodePipeline は AWS が提供する CI/CD サービスです。

CodePipeline ではプロバイダーと呼ばれるサービスを組み合わせることによってデプロイ作業を自動化できます。

主なプロバイダーとして以下の3種類があります。

### ソースプロバイダー

ソースコードなどを管理するプロバイダーです。Gitリポジトリを指定する場合が多いですが、ECR、S3を指定することもできます。

CodePipeline はソースプロバイダーを監視し、ソースコード変更があった場合にパイプライン自身を実行します。（監視と実行は Eventbridge が行っているようです）

例：AWS CodeCommit、GitHub、ECR、S3など

### ビルドプロバイダー

ソースプロバイダーが管理するソースコードをビルドするプロバイダーです。コンテナイメージファイルの作成、jar ファイルの作成など、ビルド処理内容は様々です。CodeBuild が指定されることが多いようです。

例：AWS CodeBuild 、CloudBees 、Jenkins 、TeamCity

### デプロイプロバイダー

ビルドプロバイダーの作成物（CodeBuild では Artifacts と呼ばれる）をデプロイするサービスです。CodePipeline について説明しているサイトでは CodeDeploy が指定されていることが多いですが、Cloudformation や Elastic Beanstalk といった別のデプロイサービスや ECS、S3といったデプロイ先となるサービスをプロバイダーとして選択することもできます。CodeDeploy の利用は必須ではありません。

例：AWS CodeDeploy 、Cloudformation、Elastic Beanstalk、ECS、S3 など

<br>
以下は AWS Black Belt の資料からの抜粋ですが、CodeCommit へのプッシュをトリガーにコンテナイメージファイルを作成し、ECS へデプロイするパイプラインの構成例になります。

ソースプロバイダー：AWS CodeCommit

ビルドプロバイダー：AWS CodeBuild

デプロイプロバイダー：ECS

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/aad0d668-6d25-08c9-1d3d-c3d277a44526.png)


詳細は以下の動画をご覧ください。

https://youtu.be/31-w23SdOAs?si=ecgcoVdHvgYzC8ey&t=2363

## CDK と CodePipeline を融合！！

上記を踏まえたうえで、AWS の開発エンジニアはきっとこんなことを考えたはずです。

*CDK プログラムを Git リポジトリにプッシュして、それをトリガーに cdk deploy するパイプラインを作れば便利じゃね!?*

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/83e2e8cb-e70a-2a2c-e1a8-5b09ad72ed12.png)


AWS の開発エンジニアは天才ですから、さらにこんなことも考えたはずです。

*そもそも cdk deploy するパイプライン自体も CDK プログラムに含めれば便利じゃね!?*

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/32e9b142-f789-75ed-4ce4-759e9a4c9ba6.png)


そうして生まれたのが CDK Pipelines です。~~知らんけど~~

# CDK Pipelinesとは？

少し長くなりましたが、ここでようやく本題に入ります。

CDK Pipelines とは以下の機能を有する CodePipeline を作成できるモジュールの名称です。また、サイトによっては本モジュールで作成された CodePipeline 自体を指す場合もあります。

1. CDK プログラムのビルドし、作成したいCloudformation テンプレートファイルでデプロイを行う
2. CDK プログラムに含まれているパイプライン自身の定義を確認し、変更があった場合はセルフアップデートを行う

1については通常の CodePipeline でも実現可能ですので、CDK Pipelines の特徴は2になります。

CDK Pipelinesでは CDK プログラムのビルド・デプロイを行う Pipeline 自身の定義が CDKプログラムに記載されています。パイプラインの構成に差分があった場合は定義に従ってセルフアップデートを行います。

このような処理をプログラムで記載するのは難しそうに感じますが、CDK Pipelines モジュールを利用すれば少ない行数で済みます。CDK では少ない行数で記載できるモジュールを L3 コンストラクト・パターンと呼んでいますが、CDK Pipelines モジュールだけで複数の Codebuild や Cloudformation デプロイ機能を作成できるため、 L3 コンストラクトに似ていると思います。

比較的簡単にパイプライン自体を IaC ツールの管理に含めることができ、パイプラインに変更があった場合に柔軟に対応できることが通常の CodePipeline にはないメリットだと思います。

# 実際に構築してみた

ここからは実際の CDK プログラムとマネジメントコンソール画面を確認していきたいと思います。

## CDK プログラム

以下は CDK Pipelines について定義した CDK プログラムの抜粋・編集したものです。

```tsx
import { CodeBuildStep, CodePipeline, CodePipelineSource } from 'aws-cdk-lib/pipelines';
import { Stage, StageProps } from 'aws-cdk-lib'
import { VpcStack } from './vpc-stack';

// CodeCommit
declare const codeCommitRepo: codecommit.IRepository;

// ブランチ名
const releaseBranchName = 'release';

// CDKパイプライン
const cdkPipeline = new CodePipeline(this, `cdkPipeline`, {
  // ビルドプロバイダーを定義
  synth: new CodeBuildStep(`SynthStep`, {
    input: CodePipelineSource.codeCommit(codeCommitRepo, releaseBranchName),
    installCommands: [
      'npm install -g cdk',
    ],
    commands: [
      'npm ci',
      'npm run build',
      `npx cdk synth`
    ],
  }),
  pipelineName: `cdkPipelinesSample`
});

// ステージ追加
const deployStage = new DeployStage(this, `Deploy`, {});
cdkPipeline.addStage(deployStage, {
  pre: [new ManualApprovalStep('Approval')],
});

// デプロイステージ
class DeployStage extends Stage { 
  constructor(scope: Construct, id: string, props: StageProps) {
    super(scope, id, props);
 
    // VPC作成
    const vpcStack = new VpcStack(this, `VPCStack`, {});
  }
}
```

重要な個所をピックアップします。

- 'aws-cdk-lib/pipelines' が CDK Pipelines のモジュールです。通常の CodePipeline 用のモジュールは 'aws-cdk-lib.aws_codepipeline’ と別にあります。
- CodePipeline コンストラクタの synth プロパティでは Cloudformation テンプレートファイルを作成するビルドプロバイダーを定義しています。ソースプロバイダーとして CodeCommit に作成したリポジトリの release ブランチを input に記載し、cdk synth コマンドでテンプレートファイルを作成しています。
- デプロイプロバイダーがデプロイするサービスは最後の cdkPipeline.addStage(deployStage); で追加しています。今回は VPC のみを記載した1スタックのみですが、複数サービスを記載したスタックを複数記載することもできます。

初期段階では CDK Pipelines の構築はされていないため、CodeCommit にソースコードをプッシュしても意味はありません。そのため、最初に一度だけローカルPCなどで cdk deploy コマンドを実行する必要があります。

## マネジメントコンソール画面

以下が初期構築後の CodePipeline 画面です。CodeCommit が空のため、エラーになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/8601ec15-0ef8-ab62-b642-9dd3146cb7da.png)


release ブランチへプッシュ直後の画面です。Build ステージの処理が動き出しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/324e41ff-af2d-1c75-76bd-d91187c42106.png)

しばらくして、Deployステージまで処理が完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/6062ddca-ae1f-e106-4e5d-98f72044d9f3.png)


Cloudformation では VPCStack が作成完了したことが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/d80c2f8a-738a-d24b-6a72-678eeb7d1235.png)


続いて、パイプラインのデプロイステージの承認回数を2回に増やしプッシュします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/ef2e6981-7414-d4ae-6d3a-300db682f504.png)

Build が完了し、UpdatePipeline が実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/e3e68c02-63d7-1b8f-d928-9e50c10ba8c4.png)

しばらくすると、Buildステージが再度実行され、UpdatePipeline ステージが停止します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/18aa7764-daee-98d2-5a6f-a29de802e5bb.png)

Deploy ステージの認証回数が2回に増えていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2232744/7e5c4532-2c5f-6995-e04f-d430605208c0.png)


UpdatePipeline ステージでパイプライン自身の差分を確認し、差分がある場合はセルフアップデートを実施しています。その後 Build ステージから再開していることが分かります。

# 参考

[CDK Pipelines を使用した継続的な統合と配信 (CI/CD) - AWS Cloud Development Kit (AWS CDK) v2 (amazon.com)](https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/cdk_pipeline.html)

[コンストラクト - AWS Cloud Development Kit (AWS CDK) v2 (amazon.com)](https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/constructs.html)

[aws-cdk-lib.pipelines module · AWS CDK (amazon.com)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html)

[[AWS Black Belt Online Seminar] AWS CodeStar & AWS CodePipeline 資料及び QA 公開 | Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/webinar-bb-awscodestar_awscodepipeline-2020/)

[CodePipeline アクションタイプとの統合 - AWS CodePipeline (amazon.com)](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/integrations-action-type.html#integrations-deploy)