はじめに
先日からApp RunnerとかElastiCacheとかを使った検証をしていましたが、マネージメントコンソールで作業をするのは時間がかかり、料金節約のためにリソースを削除するのも大変なので、AWS CDKで実装してみることにしました。
プロジェクト作成
プロジェクトは以下のドキュメントを見ながら作業をすることに。
NodeJS環境にてnpx cdk init --language typescript
を実行すればOK。
ネットワーク関係を作成する
各種リソースを作成するためにAWS CDKのAPIドキュメントに目を通します。
まずはVPCを作るので、aws-ec2のVpcクラスに目を通します。
lib/construct/network.ts
というディレクトリ・ファイルを作成し、以下の内容として保存します。
import { Construct } from "constructs"; import * as ec2 from 'aws-cdk-lib/aws-ec2'; export class Network extends Construct { readonly vpc: ec2.Vpc; readonly appRunnerSecurityGroup: ec2.SecurityGroup; readonly cacheSecurityGroup: ec2.SecurityGroup; // VPCとサブネットを作る constructor(scope: Construct, id: string) { super(scope, id); this.vpc = new ec2.Vpc(scope, 'VPC', { vpcName: 'myapp-vpc', cidr: '10.0.0.0/16', maxAzs: 2, subnetConfiguration: [ // Redis用のサブネット { cidrMask: 24, name: 'myapp-cache', subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }, // AppRunner用のサブネット { cidrMask: 24, name: 'myapp-Public', subnetType: ec2.SubnetType.PUBLIC, } ], natGateways: 0, }); // App Runnerに設定するセキュリティグループ this.appRunnerSecurityGroup = new ec2.SecurityGroup(scope, 'AppRunnerSecurityGroup', { vpc: this.vpc, description: 'for myapp-app-runner', securityGroupName: 'myapp-app-runner-sg' }); //Cacheに設定するセキュリティグループ this.cacheSecurityGroup = new ec2.SecurityGroup(scope, 'CacheSecurityGroup', { vpc: this.vpc, description: 'for myapp-cache', securityGroupName: 'myapp-cache-sg' }); // App RunnerセキュリティグループからCacheセキュリティグループへのポート6379を許可 this.cacheSecurityGroup.addIngressRule(this.appRunnerSecurityGroup, ec2.Port.tcp(6379)); } }
あとは、lib/cdk-stack.ts
を更新します。
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { Network } from './construct/network'; export class CdkStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // VPCを作成する const { vpc, appRunnerSecurityGroup, cacheSecurityGroup } = new Network(this, 'Network'); } }
これで実装は完了。
実行する
まずはcdk bootstrap
を実行し、CDKに関するリソースを作成します。必要なロールやcdk-
からはじまるS3バケットが作成されました。ちなみにこのS3バケットにはDeletionPolicy: Retain
が指定されています。
このため、cdk bootstrap
で生成された以下スクリーンショットのCloudFormationのスタックを削除してもこのS3バケットは残ります。
あとはcdk deploy
を実行することでAWSリソースが作成されます。
ちなみに、今回はCloud9上で実行してみたのですが、t2.microですとTypeScriptのビルドがメモリ不足で異常終了しましたので実行するにはt3.small以上のインスタンスが必要かと思います。
削除する
作成したAWSリソースはcdk destroy
を実行すれば削除されます。
他のリソースを作成する
VPC以外のリソースを作成してみます。まずはECR。ドキュメントは以下のもの。
実装例は以下のもの。lib/construct/ecr-repository.ts
として保存します。
import { RemovalPolicy } from 'aws-cdk-lib'; import * as ecr from 'aws-cdk-lib/aws-ecr'; import { Construct } from 'constructs'; export class EcrRepository extends Construct { readonly repository: ecr.Repository; constructor(scope: Construct, id: string) { super(scope, id); // リポジトリを作成する this.repository = new ecr.Repository(scope, 'MyAppRepository', { repositoryName: 'myapp-repository', removalPolicy: RemovalPolicy.DESTROY, imageScanOnPush: false }); } }
ElastiCacheの作成。ドキュメントは以下のもの。
実装例は以下のもの。lib/construct/cache.ts`として保存します。
import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as elasticache from 'aws-cdk-lib/aws-elasticache'; import { Construct } from 'constructs'; interface CacheProps { vpc: ec2.Vpc cacheSecurityGroup: ec2.SecurityGroup } export class Cache extends Construct { readonly cacheCluster: elasticache.CfnCacheCluster; constructor(scope: Construct, id: string, props: CacheProps) { super(scope, id); const { vpc, cacheSecurityGroup } = props; const cacheSubnetGroup = new elasticache.CfnSubnetGroup(this, "CacheSubnetGroup", { subnetIds: vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds, description: "Group of subnets to place Cache into", }); this.cacheCluster = new elasticache.CfnCacheCluster(this, "CacheCluster", { engine: "redis", cacheNodeType: "cache.t3.micro", numCacheNodes: 1, cacheSubnetGroupName: cacheSubnetGroup.ref, vpcSecurityGroupIds: [cacheSecurityGroup.securityGroupId], }); } }
その後、lib/cdk-stack.ts
を以下のように更新します。
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { Network } from './construct/network'; import { EcrRepository } from './construct/ecr-repository'; import { Cache } from './construct/cache'; export class CdkStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // VPCを作成する const { vpc, appRunnerSecurityGroup, cacheSecurityGroup } = new Network(this, 'Network'); // ECRを作成する const { repository } = new EcrRepository(this, 'Ecr'); // Cacheを作成する const { cacheCluster } = new Cache(this, 'ElastiCache', { vpc, cacheSecurityGroup }); } }
あとは、cdk deploy
を実行すればOK。ElastiCacheの作成には10分ぐらいかかるのでちょっと気長に待ちましょう。