AWS CDKでVPC周りとEC2を作ってみる。
次の記事で、session managerのセットアップ、nginxのセットアップも続けて行うが、本記事ではスコープ外とする。
特にVPC周りを作ろうする際には、関連リソースのセキュリティグループ、ルートテーブル、NAT Gatewayなどを自動作成してくれるが、
気をつけておかないと高額課金の可能性がある。
この辺も、実際に作成される予定のリソースを確認しながら進めてみる。
関連資料
-
API Reference · AWS CDK
- API Referenceを追いかけながら、リソースを作成していく
-
料金 - Amazon VPC | AWS
- 関連リソースの価格帯は理解しておきたい
前提
- aws cdkでスタック作成→削除を行える
リポジトリ内でcdkの初期設定ファイルを生成する
$ mkdir sample-cdk-ec2-nginx
$ cd sample-cdk-ec2-nginx
$ cdk init --language typescript
$ cdk ls
# SampleCdkEc2NginxStack
必要なリソース
- VPC
- セキュリティグループ
- ルートテーブル
- EIP
- EC2
VPC作成
まずは雑にVPCを作成させてみる
import * as ec2 from 'aws-cdk-lib/aws-ec2';
const vpc = new ec2.Vpc(this, 'SampleCdkEc2NginxVpc', {
maxAzs: 2,
vpcName: 'web-service'
});
cdk synthで作成予定のリソースを見てみると、結構えげつない量のリソースを作成してくれる事がわかる。
デフォルトで2AZ指定しているせいもあるが、2️AZにPublic Subnet, Private Subnet,4サブネット分作成するというベストプラクティスに沿った構成のようだ。
だたこれをやってしまうと、例えばNatGatewayは1ヶ月立ち上げっぱなしで 0.062(USD/h) * 155(JPY/USD) * 24(h) * 31(day) * 2個 = 14298(JPY)
掛かってしまう。
# 出力予定のCFnを確認
$ cdk synth > out.yml
# 作成予定のリソースを数える
$ grep 'Type:' out.yml|sort|uniq -c
1 Type: AWS::CDK::Metadata
2 Type: AWS::EC2::EIP
1 Type: AWS::EC2::InternetGateway
2 Type: AWS::EC2::NatGateway # これだけで14298円/月
4 Type: AWS::EC2::Route
4 Type: AWS::EC2::RouteTable
4 Type: AWS::EC2::Subnet
4 Type: AWS::EC2::SubnetRouteTableAssociation
1 Type: AWS::EC2::VPC
1 Type: AWS::EC2::VPCGatewayAttachment
1 Type: AWS::IAM::Role
1 Type: AWS::Lambda::Function
1 Type: AWS::SSM::Parameter::Value<String>
1 Type: Custom::VpcRestrictDefaultSG
必要最小限のリソースに絞る
- NATGatewayは不要
- シングルサブネット(Publicサブネットオンリー)、シングルAZで作成
const vpc = new ec2.Vpc(this, 'SampleCdkEc2NginxVpc', {
maxAzs: 1,
subnetConfiguration: [
{
cidrMask: 24,
name: 'public',
subnetType: ec2.SubnetType.PUBLIC
}
],
vpcName: 'web-service'
});
大分マシになった。
NATGatewayもないので、リソースを維持していたとして、コスト上も大きく影響するものはない。
$ cdk synth > out2.yml
$ grep 'Type:' out2.yml|sort|uniq -c
1 Type: AWS::CDK::Metadata
1 Type: AWS::EC2::InternetGateway
1 Type: AWS::EC2::Route
1 Type: AWS::EC2::RouteTable
1 Type: AWS::EC2::Subnet
1 Type: AWS::EC2::SubnetRouteTableAssociation
1 Type: AWS::EC2::VPC
1 Type: AWS::EC2::VPCGatewayAttachment
1 Type: AWS::IAM::Role
1 Type: AWS::Lambda::Function
1 Type: AWS::SSM::Parameter::Value<String>
1 Type: Custom::VpcRestrictDefaultSG
デプロイしておく
- 今回のリソースの中にLambdaが存在しているが、デフォルトで作成されるセキュリティグループを操作するためのもののよう。
- 今回は深ぼらない
$ cdk deploy
# 略
# ✨ Total time: 65.61s
EC2作成
再びEC2作成に必要な最低限のコードを追記する
// EC2
const instance = new ec2.Instance(this, 'SampleCdkEc2NginxInstance', {
vpc,
instanceType: new ec2.InstanceType('t3a.micro'),
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
});
作成される予定のリソースを確認する
今回は既存スタックへの追加なのでcdk diff
で差分を確認してみる
作成される予定のリソースは以下。
- AWS::EC2::SecurityGroup
- AWS::IAM::Role
- AWS::IAM::InstanceProfile
- あまり馴染みが無いが、EC2インスタンスにIAMロールを紐づけるためのもの。
- AWS::EC2::Instance
$ cdk diff
# 略
Resources
[+] AWS::EC2::SecurityGroup SampleCdkEc2NginxInstance/InstanceSecurityGroup SampleCdkEc2NginxInstanceInstanceSecurityGroup0DD5BDE2
[+] AWS::IAM::Role SampleCdkEc2NginxInstance/InstanceRole SampleCdkEc2NginxInstanceInstanceRole7F91D057
[+] AWS::IAM::InstanceProfile SampleCdkEc2NginxInstance/InstanceProfile SampleCdkEc2NginxInstanceInstanceProfile2CB6865B
[+] AWS::EC2::Instance SampleCdkEc2NginxInstance SampleCdkEc2NginxInstance262C66EB
デプロイしておく
$ cdk deploy
# 略
# ✨ Total time: 183.62s
EC2ができたことを確認
$ aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,PublicIpAddress]' --output text
# i-0dae143923cb3d2b2 t3a.micro running 52.69.50.147
CFnスタックを削除
$ cdk destroy
# ✅ SampleCdkEc2NginxStack: destroyed
終わりに
ここまでやって、ネットワーク周りの構築とEC2で素のAmazonLinux2023を立ち上げることができた。
ただ、これではEC2に入って何かをすることができない。
次回はsession manager経由でシェルに入れるようにする。