【AWS】Configで分けるCDK環境の紹介【CDK】
こんにちは。M研の村瀬です。今回は以前紹介したクイズ作成システムQukkerで利用しているCDKについてご紹介したいと思います。Qukkerについては以下noteをご参照ください。
Qukkerでは、複数環境をCDKを用いて構築しています。今回のnoteではCDKで複数の環境を作成する際にConfigファイルを用いて環境を分ける方法をご紹介します。このブログがCDK利用の手助けになれば幸いです。
CDKとは
AWS CDKは、AWSのリソースをプログラマブルに定義し、コードとして管理することができる、Infrastructure as Code (IaC) ツールです。AWS CDKを使用すると、AWSのリソースを手動で作成する必要がなく、コードをデプロイするだけでAWSのリソースを自動的に作成できます。
Stackとは
AWS CDKのStackは、AWSのリソースを定義し、デプロイするための単位として機能します。複数のAWSリソースを1つのスタックにまとめて管理でき、AWS CloudFormationのテンプレートよりもより柔軟な方法でアプリケーションのインフラストラクチャを定義できます。
CDKのプロジェクトの作成
詳細な仕様やドキュメントについては以下の公式のGetting Startedページを参照ください。
今回のnoteではTypescriptでCDKプロジェクトを開始してみようと思います。まずはCDKコマンドをインストールします。
■CDKコマンドのインストール
$ npm install -g cdk
次にインストールしたcdkコマンドを使ってCDKプロジェクトを作成します。
■CDKプロジェクトの作成
$ mkidr cdk-sample
$ cd cdk-sample
$ cdk init --language typescript
Configファイルで環境を分ける
検証環境用のConfigファイルと本番環境用のConfigファイルを作成し、importするConfigファイルを変えることで作成するStackを分けます。CDKはStack名が異なると別リソースとして各AWSリソースを構築します。そのためStack名やパラメータを環境毎に設定できるようなConfigファイルを用意し、Stackの宣言時にConfigファイルで設定した名前を渡すことで環境毎のリソースを構築することができます。以下はConfigファイルのサンプルです。sample-configディレクトリを作成し、dev.ts(検証環境のConfigファイル)とprod.ts(本番環境のConfigファイル)を作成します。今回の例では、EC2のインスタンスサイズをパラメータ化し、検証環境と本番環境でインスタンスサイズを変更します。
■sample-config/types.ts
Configファイルの型定義です。環境の名前、instanceSizeとinstanceClassを設定できるようにしておきます。
import { InstanceClass, InstanceSize } from "aws-cdk-lib/aws-ec2";
export type Config = {
sample: SampleConfig,
};
type SampleConfig = {
envName: string,
instanceSize: InstanceSize,
instanceClass: InstanceClass,
}
■sample-config/dev.ts
検証環境のConfigファイルです。検証環境ではSmallサイズのインスタンスを作成します。
import { InstanceClass, InstanceSize } from "aws-cdk-lib/aws-ec2";
import { Config} from "./types";
export const sampleConfig:Config["sample"] = {
envName: 'dev',
instanceSize: InstanceSize.SMALL,
instanceClass: InstanceClass.BURSTABLE3
}
export const config: Config = {
sample: sampleConfig
}
■sample-config/prod.ts
本番環境のConfigファイルです。本番環境ではMediumサイズのインスタンスを作成します。
import { InstanceClass, InstanceSize } from "aws-cdk-lib/aws-ec2";
import { Config} from "./types";
export const sampleConfig:Config["sample"] = {
envName: 'prod',
instanceSize: InstanceSize.MEDIUM,
instanceClass: InstanceClass.BURSTABLE3
}
export const config: Config = {
sample: sampleConfig
}
Stack定義を作成する
Stackを作成します。今回はシンプルにEC2一台を作成する例です。EC2を作成するためにはVPCとSubnetが必要なので、今回のStackでは、VPCとSubnetとEC2の作成をするStackを定義します。
■lib/cdk-sample-stack.ts
import { Construct } from "constructs";
import {
Stack,
StackProps,
aws_ec2 as ec2,
} from "aws-cdk-lib";
import { Config } from "../sample-config/types";
interface SampleStackProps extends StackProps {
config: Config;
}
export class SampleStack extends Stack {
constructor(scope: Construct, id: string, props: SampleStackProps) {
super(scope, id, props);
const sampleConfig = props.config.sample;
const my_vpc = new ec2.Vpc(this, `${sampleConfig.envName}-vpc}`, {
ipAddresses: ec2.IpAddresses.cidr("10.0.0.0/24"),
enableDnsHostnames: true,
enableDnsSupport: true,
natGateways: 1,
maxAzs: 1,
subnetConfiguration: [
{ name: "Private", subnetType: ec2.SubnetType.PUBLIC, cidrMask: 28 },
],
});
const my_ec2 = new ec2.Instance(this, `${sampleConfig.envName}-ec2`, {
vpc: my_vpc,
instanceName: `${sampleConfig.envName}-ec2`,
machineImage: ec2.MachineImage.latestAmazonLinux(),
instanceType: ec2.InstanceType.of(
sampleConfig.instanceClass,
sampleConfig.instanceSize,
)
})
}
}
StackにConfigを渡し同一Stack定義から別環境を構築する
上記で定義したSampleStackから、検証環境と本番環境のEC2を作成します。両環境のEC2を作成するため、SampleStackにdevConfig/prodConfigをそれぞれパラメータとして渡しStackを生成します。
■bin/cdk-sample.ts
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { SampleStack } from '../lib/cdk-sample-stack';
import { config as devConfig } from '../sample-config/dev'
import { config as prodConfig } from '../sample-config/prod'
const app = new cdk.App();
new SampleStack(
app,
'SampleStackDev',
{
config: devConfig,
env: {
region: 'ap-northeast-1'
}
}
),
new SampleStack(
app,
'SampleStackProd',
{
config: prodConfig,
env: {
region: 'ap-northeast-1'
}
}
);
Stackのデプロイ
■cdk list
cdk list はデプロイ可能なStackの一覧を表示するコマンドです。デプロイ可能なStack名を確認し、この後のdiffコマンドで差分を確認し、deployコマンドで実際に適用します。
$ cdk list
SampleStackDev
SampleStackProd
■cdk diff {stack名}
cdk diff {stack名} で、 cdk deploy {stack名} コマンドでデプロイされる差分を表示してくれます。deployで変更されるリソースに間違いがないかdiffコマンドを使いdeploy前に確認しましょう。
$ cdk diff SampleStackDev
Stack SampleStackDev
IAM Statement Changes
┌───┬─────────────────────────────┬────────┬────────────────┬───────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼─────────────────────────────┼────────┼────────────────┼───────────────────────────┼───────────┤
│ + │ ${dev-ec2/InstanceRole.Arn} │ Allow │ sts:AssumeRole │ Service:ec2.amazonaws.com │ │
└───┴─────────────────────────────┴────────┴────────────────┴───────────────────────────┴───────────┘
Security Group Changes
┌───┬──────────────────────────────────────────┬─────┬────────────┬─────────────────┐
│ │ Group │ Dir │ Protocol │ Peer │
├───┼──────────────────────────────────────────┼─────┼────────────┼─────────────────┤
│ + │ ${dev-ec2/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>)
Parameters
[+] Parameter SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter: {"Type":"AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>","Default":"/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2"}
[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}
Resources
[+] AWS::EC2::VPC dev-vpc} devvpc875BEBD3
[+] AWS::EC2::Subnet dev-vpc}/PrivateSubnet1/Subnet devvpcPrivateSubnet1SubnetC8A33C23
[+] AWS::EC2::RouteTable dev-vpc}/PrivateSubnet1/RouteTable devvpcPrivateSubnet1RouteTable1DC78C03
[+] AWS::EC2::SubnetRouteTableAssociation dev-vpc}/PrivateSubnet1/RouteTableAssociation devvpcPrivateSubnet1RouteTableAssociationDAFB1727
[+] AWS::EC2::Route dev-vpc}/PrivateSubnet1/DefaultRoute devvpcPrivateSubnet1DefaultRoute8F00ED59
[+] AWS::EC2::EIP dev-vpc}/PrivateSubnet1/EIP devvpcPrivateSubnet1EIPD3F727D5
[+] AWS::EC2::NatGateway dev-vpc}/PrivateSubnet1/NATGateway devvpcPrivateSubnet1NATGateway545D1819
[+] AWS::EC2::InternetGateway dev-vpc}/IGW devvpcIGW9E0BA2FD
[+] AWS::EC2::VPCGatewayAttachment dev-vpc}/VPCGW devvpcVPCGW548A0FFE
[+] AWS::EC2::SecurityGroup dev-ec2/InstanceSecurityGroup devec2InstanceSecurityGroup4829615C
[+] AWS::IAM::Role dev-ec2/InstanceRole devec2InstanceRole730B2650
[+] AWS::IAM::InstanceProfile dev-ec2/InstanceProfile devec2InstanceProfile6D895362
[+] AWS::EC2::Instance dev-ec2 devec25A6C763B
Other Changes
[+] Unknown Rules: {"CheckBootstrapVersion":{"Assertions":[{"Assert":{"Fn::Not":[{"Fn::Contains":[["1","2","3","4","5"],{"Ref":"BootstrapVersion"}]}]},"AssertDescription":"CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."}]}}
■cdk deploy
定義した内容を適用します。
$ cdk deploy
Stackの削除
■cdk destroy
cdk destroy はdeployしたawsリソースを削除します。今回作成したリソースをそのまま残しておくと課金され続けてしまうので、リソースを作成した方はdestroyコマンドを使い削除することをお勧めします。
*一部リソース(S3等)はdestroyコマンドを実行しても削除されないものがあるため、コンソール画面から手動で削除する必要があります。
$ cdk destroy
まとめ
このようにして、一つのStackファイルから渡すConfigを変えるだけで複数の環境を作成することができます。検証環境と本番環境で変更したい値については、Configファイルに追加していくだけで、変えることができます。
以下のgithubに今回作成したサンプルのCDKプロジェクトを用意しました。こちらも併せてご参照ください。
(メディア研究開発センター・村瀬友広)