はじめに
AWS CloudFormationで複数のスタックを使用してEC2を構築したので、その検証結果を記事に残したいと思います。なお、別記事を作成予定となりますが、最終的にはCloudFormationで作成したEC2にAnsibleを導入し、OS設定まで自動化を目標としています。
構成図
VPCは東京リージョンに作成し、パブリックサブネットはap-northeast-1aに作成しています。
EC2へのアクセスは指定した固定IPからのSSH, HTTPアクセスのみ許可しています。
テンプレートファイルの構成
ファイル構成は以下のように行います。テンプレートファイルをVPC、EC2等、サービスごとに分けることで、今後のメンテナンス性も上がると思います。
├── main.yaml
│
└── vpc
│ └── vpc.yaml
│
├── subnet
│ └── public
│ └── subnet.yaml
│
├── ec2
│ ├── ec2.yaml
│ └── sg.yaml
親テンプレート(main.yaml)の作成
AWSTemplateFormatVersion: "2010-09-09"
Description: testCFn stack
Resources:
VPC:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: vpc/vpc.yaml
Parameters:
TagName : "VPCTEST"
PublicSubnet:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: subnet/public/subnet.yaml
Parameters:
VPC: !GetAtt VPC.Outputs.VPCID
EC2Instance:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ec2/ec2.yaml
Parameters:
VPC: !GetAtt VPC.Outputs.VPCID
KeyName: test CFn
Subnet: !GetAtt PublicSubnet.Outputs.SubnetID
- VPCテンプレート(vpc.yaml)の作成
AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC for testCFn '
Parameters:
VPCCIDR:
Type: String
Default: "10.0.0.0/16"
TagName :
Type: String
Default: "testCFn"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
Tags:
- Key: Name
Value: !Ref TagName
Outputs:
VPCID:
Value: !Ref VPC
- サブネットテンプレート(subnet.yaml)の作成
AWSTemplateFormatVersion: '2010-09-09'
Description: 'public subnet for testCFn'
Parameters:
AZ:
Type: AWS::EC2::AvailabilityZone::Name
Default: ap-northeast-1a
TagName:
Type: String
Default: "subnettestCFn"
VPC:
Type: AWS::EC2::VPC::Id
Resources:
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AZ
VpcId: !Ref VPC
CidrBlock: 10.1.2.0/24
Tags:
- Key: Name
Value: !Ref TagName
PublicRouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Ref TagName
InternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: !Ref TagName
InternetGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
PublicRoute:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
PublicSubnetTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTable
Outputs:
SubnetID:
Value: !Ref PublicSubnet
- EC2テンプレートの作成(ec2.yaml)の作成
AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC for testCFn'
Parameters:
ImageId:
Type: String
Default: "ami-0701e21c502689c31"
KeyName:
Type: String
Subnet:
Type: AWS::EC2::Subnet::Id
VPC:
Type: AWS::EC2::VPC::Id
TagName :
Type: String
Default: "testCFn"
Resources:
EC2SG:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: sg.yaml
Parameters:
VPC: !Ref VPC
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ImageId
KeyName: !Ref KeyName
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref Subnet
GroupSet:
- !GetAtt EC2SG.Outputs.SGID
Tags:
- Key: Name
Value: !Ref TagName
- EC2テンプレートの作成(sg.yaml)の作成
AWSTemplateFormatVersion: '2010-09-09'
Description: 'SG for testCFn'
Parameters:
MyIP:
Type: String
Default: "0.0.0.0/0"
VPC:
Type: AWS::EC2::VPC::Id
TagName :
Type: String
Default: "testCFn"
Resources:
EC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "test demo"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref MyIP
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref MyIP
Tags:
- Key: Name
Value: !Ref TagName
Outputs:
SGID:
Value: !Ref EC2SG
テンプレートファイルをCloudShell→S3へアップロードする
CloudShellとは?
AWS関連のツールがあらかじめインストールされたAmazon Linux 2の環境をAWS管理コンソールからボタン一つで作成でき、スクリプトの実行やAPIの呼び出しなどが簡単に行えます。また、ファイルのアップロード、ダウンロードも可能です。
AWS CLIの実行権限はAWS管理コンソールにログインしているIAMユーザの権限をそのまま使用できますので、非常に便利です。また、AWS CloudShellは追加費用なしで利用でき、リージョンごとに1GBの無料ストレージが含まれます。このストレージをホームディレクトリとして利用でき、スクリプトファイルや構成ファイル、追加のコマンドファイルなどを保存できます。
- CloudShellを起動して以下のディレクトリ、ファイルを配置します。
/home/cloudshell-user/
├── main.yaml
│
└── vpc
│ └── vpc.yaml
│
├── subnet
│ └── public
│ └── subnet.yaml
│
├── ec2
│ ├── ec2.yaml
│ └── sg.yaml
- S3バケットの作成
以下のコマンドでtest-CFnというバケットを作成します。
aws s3 mb s3://test-CFn
- S3へアップロード
以下のコマンドでS3へアップロードします。
aws cloudformation package --template-file main.yaml \
--s3-bucket test-CFn \
--output-template-file test-CFn.yml
作成されたtest-CFn.ymlは以下となっています。
ファイル参照先がs3となっています。
AWSTemplateFormatVersion: '2010-09-09'
Description: test-CFn stack
Resources:
VPC:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.ap-northeast-1.amazonaws.com/test-CFn/hogehoge.template
Parameters:
TagName: VPCTEST
PrivateSubnet:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.ap-northeast-1.amazonaws.com/test-CFn/hogehoge.template
Parameters:
VPC:
Fn::GetAtt:
- VPC
- Outputs.VPCID
PublicSubnet:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.ap-northeast-1.amazonaws.com/test-CFn/hogehoge.template
Parameters:
VPC:
Fn::GetAtt:
- VPC
- Outputs.VPCID
EC2Instance:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.ap-northeast-1.amazonaws.com/test-CFn/hogehoge.template
Parameters:
VPC:
Fn::GetAtt:
- VPC
- Outputs.VPCID
KeyName: hogehoge
Subnet:
Fn::GetAtt:
- PublicSubnet
- Outputs.SubnetID
Cloudformationリソース作成
- test-CFn.ymlの実行
以下のコマンドを実行します。
aws cloudformation deploy --template-file test-CFn.yml --stack-name test-CFn
コンソールを確認すると、各リソースが作成できた(CREATE_COMPLETE)ことが確認できます。
おわりに
サービスごとにスタックを分けて作成すると今後のメンテナンスが楽になると思いました。今後はCloudFormationの追加/変更時、運用面で考慮する部分を検討できたらと思います。本記事の続編としてCloudFormationで作成したEC2にAnsibleを導入し、OS設定するまでの記事を次回、投稿したいと思います。
本記事が何かのお役に立てれば幸いです。
ありがとうございました。