この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
AWS上で何らかの検証を行うため、VPCとサブネットを用意し、その中にEC2インスタンスを作成することはしばしばあるかと思います。 これらをパッと作れるよう、以下のような点を考慮しつつAWS CDKで作成してみました。
- VPC、パブリックサブネット、プライベートサブネットを作成。それぞれのサブネットにEC2インスタンスを作成する。
- EC2インスタンスにはSession Managerで接続できるようにする。
- セキュリティグループを作成するが、Ingressは何も許可しない(必要な時に手動で許可する想定)。
- CDKのbootstrapコマンドで使用するバケット名を指定できるようにする。
- CDKのToolkitのスタック名を指定できるようにする。
- CloudFormationスタックに説明を入れる。
以下、作成した時に行ったことやソースについて書きたいと思います。
実装について
前提条件
AWS CDKを実行するにあたり、AWS CLIやNode.js、CDKなど必要なものはローカルにインストール済みであるものとします。 今回使用したCDKのバージョンは「2.56.0」となります。
$ cdk --version
2.56.0 (build 1485f48)
プロジェクト作成
ローカルに作業用のフォルダを作成します。今回は「cdk-vpc-ec2」というフォルダ名としました。
$ mkdir cdk-vpc-ec2
$ cd cdk-vpc-ec2
以下のコマンドを実行してプロジェクトを作成します。
$ cdk init sample-app --language typescript
実装したソース
AWS CDKのソースは以下のようになります。
cdk-vpc-ec2.ts
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { CdkVpcEc2Stack } from '../lib/cdk-vpc-ec2-stack';
import { DefaultStackSynthesizer } from 'aws-cdk-lib';
const app = new cdk.App();
new CdkVpcEc2Stack(app, 'CdkVpcEc2Stack', {
synthesizer: new DefaultStackSynthesizer({
fileAssetsBucketName: 'cdk-vpc-ec2-assets', // bootstrapのバケット名を指定
}),
description: 'This is a cdk-vpc-ec2-sample-stack', // CloudFormationスタックに説明を追加
});
cdk-vpc-ec2-stack.ts
import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import { CfnOutput } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class CdkVpcEc2Stack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// バケット
const bucket = new s3.Bucket(this, 'SampleBucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
bucketName: "cdk-vpc-ec2-sample-bucket",
});
// VPC
const vpc = new ec2.Vpc(this, 'SampleVpc', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
vpcName: 'cdk-sample-vpc'
});
// セキュリティグループ
const securityGroup = new ec2.SecurityGroup(this, 'SampleSecurityGroup', {
vpc: vpc,
securityGroupName: 'cdk-vpc-ec2-security-group',
});
// (Session Mangerを使うための)IAMロール
const instanceRole = new iam.Role(this, 'SampleRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName(
"AmazonSSMManagedInstanceCore"
),
],
description: 'cdk-vpc-ec2-instance-role',
});
// EC2インスタンス作成
const createInstance = (id: string, name: string, subnet: ec2.SubnetSelection) : ec2.Instance => {
return new ec2.Instance(this, id, {
vpc,
vpcSubnets: subnet,
instanceType: new ec2.InstanceType(this.node.tryGetContext('instanceType')),
machineImage: ec2.MachineImage.latestAmazonLinux({
generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
}),
securityGroup: securityGroup,
role: instanceRole,
instanceName: name
});
};
const instance1 = createInstance('SampleInstance1', 'cdk-vpc-ec2-instance1', vpc.selectSubnets({
subnetType: ec2.SubnetType.PUBLIC
}));
const instance2 = createInstance('SampleInstance2', 'cdk-vpc-ec2-instance2', vpc.selectSubnets({
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS
}));
// CloudFormationに出力
new CfnOutput(this, 'S3', { value: bucket.bucketName });
new CfnOutput(this, 'VPC', { value: vpc.vpcId });
new CfnOutput(this, 'Security Group', { value: securityGroup.securityGroupId });
new CfnOutput(this, 'EC2Instance1', { value: instance1.instanceId });
new CfnOutput(this, 'EC2Instance2', { value: instance2.instanceId });
}
}
cdk.json
{
(中略)
"context": {
(中略。context内に以下をインスタンスタイプの定義を追記)
"instanceType": "t2.micro"
}
}
コメントに書いてあるように、bootstrapで使用する任意のバケット名を指定しています。 また作成されるCloudFormationに説明を追加したり、出力値に作成したリソースの名称等を出力するようにしています。
実行したコマンド
bootstrapではバケット名、ToolKitのスタック名を指定しました。以下のようなコマンドとなります。
$ cdk bootstrap \
--bootstrap-bucket-name cdk-vpc-ec2-assets \
--toolkit-stack-name cdk-vpc-ec2-toolkit \
diffやdeployなどのコマンドは特に引数などは必要ありません。
$ cdk diff
$ cdk deploy
実行結果
CDKのコマンドを実行するとCloudFormationやリソースが作成されるかと思います。以下に作成されたもののキャプチャの一部を挙げて起きます。
スタックの説明
スタックの出力値
インスタンス
まとめ
個人的にしばしば使うリソースをAWS CDKを使って作ってみました。何かの役にたてば幸いです。