この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
コンニチハ、千葉です。
最近CloudFormationで20台くらい、どっかーんとEC2立てて気持ちよくなってる私です。 CloudFormationを利用すると、規模が大きかったり環境(dev/stg/prd)がたくさんあっても、かなり楽できます。そうです、早く帰れます。
ということで、使ったTipsをまとめておきます。今回は、よく構築するであろうEC2にフォーカスします。
Tips
Tips1:環境によってパラメータを変える
パラメータを変数化して、1つのCFnファイルで複数の環境(dev/stg/prd)を扱います。Mappings
を使います。コードの例です。*Mappingsに関連する部分だけ抜粋
CFnスタック作成するときに、prd/stgを選ぶと、Mappingsで定義したパラメータを利用できます。これで、1つのCFnでprd/stgを管理できます。
Mappings:
prd:
PublicSubnet1a: { ID: subnet-xxxxx }
stg:
PublicSubnet1a: { ID: subnet-xxxxx }
Parameters:
Environment:
Description: Type of this environment.
Type: String
Default: prd
AllowedValues:
- prd
- stg
BastionEc2Instance:
・・・省略
- SubnetId: !FindInMap [ !Ref Environment, PublicSubnet1a, ID ]
Tips2:命名規則
リソース名など、最初から命名規則を決めて組み込みましょう。
Parameters:
Environment:
Description: Type of this environment.
Type: String
Default: prd
AllowedValues:
- prd
- stg
Parameters:
SystemName:
Description: Name of this system.
Type: String
Default: chiba-system
・・・省略
Tags:
- Key: Name
Value: !Sub ${SystemName}-${Environment}-web1
Tips3:ユーザーデータを使って初期構築windows編
windowsの初期構築です。ユーザーデータを使って、ホスト名、時刻同期、文字コード、タイムゾーンを設定します。
Mappings
と!Sub
をうまく組み合わせて変数を取り込んでます。ちょっと複雑。ただ、ログインしなくていいんですよ、圧倒的です。
Mappings:
prd:
OSSettings:
TimeZone: "Tokyo Standard Time"
BastionEc2Instance:
HostName: chiba-bastion
・・・省略
UserData:
Fn::Base64:
!Sub
- |
# hostname
Rename-Computer -NewName ${HostName} -Force
# TimeZone
Set-TimeZone -id "${TimeZone}"
# time sync
w32tm /config /manualpeerlist:169.254.169.123 /syncfromflags:manual /update
- { HostName: !FindInMap [ !Ref Environment, BastionEc2Instance, HostName ], TimeZone: !FindInMap [ !Ref Environment, OSSettings, TimeZone ] }
Tips4:ユーザーデータを使って初期構築Linux編
Linuxバージョンです。ホスト名、時刻同期、文字コード、タイムゾーンを設定します。
Mappings:
prd:
OSSettings:
Locale: ja_JP.utf8
TimeZone: "Asia/Tokyo"
BastionEc2Instance:
HostName: chiba-bastion
・・・省略
UserData:
Fn::Base64:
!Sub
- |
#!/bin/sh -ex
# timezon
timedatectl set-timezone ${TimeZone}
# hostname
hostnamectl set-hostname --static ${HostName}
echo 'preserve_hostname: true' >> /etc/cloud/cloud.cfg
# time sync
yum erase 'ntp*'
yum install chrony
echo '#Add TimeSync' >> /etc/chrony.conf
echo 'server 169.254.169.123 prefer iburst' >> /etc/chrony.conf
systemctl start chrony
systemctl enable chrony
# locale
localectl set-locale LANG=${Locale}
- { HostName: !FindInMap [ !Ref Environment, BastionEc2Instance, HostName ], TimeZone: !FindInMap [ !Ref Environment, OSSettings, TimeZone ], Locale: !FindInMap [ !Ref Environment, OSSettings, Locale ] }
Tips5:注意:DeviceNameは気をつける
EC2構築時にDeviceNameを利用しますが、デバイス名を意識して指定する必要があります。指定を誤るとEC2が起動できなかったりします。インスタンスタイプ(仮想化方式の違い)やAMIによって違ったりします。こちらを参考にしたり、実際に手動でEC2を作るときに確認できます。
- https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/device_naming.html
- https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/device_naming.html
全部入りコード
これらをまとめたコードを置いておきます!
windows
windows1台構築します。EC2の設定に加え、ホスト名、時刻同期、タイムゾーンを設定します。
AWSTemplateFormatVersion: '2010-09-09'
Description: This CloudFormation template to create EC2 instances.
Mappings:
prd:
PublicSubnet1a: { ID: subnet-xxxxxx }
PublicSubnet1c: { ID: subnet-xxxxxx }
PrivateSubnet1a: { ID: subnet-xxxxxx }
PrivateSubnet1c: { ID: subnet-xxxxxx }
OSSettings:
TimeZone: "Tokyo Standard Time"
BastionEc2Instance:
HostName: xxxx_ec2
InstanceType: t3.small
AmiId: ami-0a2de1c3b415889d2
RootVolumeSize: 30
PrivateIpAddress: xx.xx.xx.xx
SecurityGroupId: sg-xxxxxxx
Parameters:
Environment:
Description: Type of this environment.
Type: String
Default: prd
AllowedValues:
- prd
- stg
SystemName:
Description: Name of this system.
Type: String
Default: chiba-web
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Name of an existing EC2 KeyPair to enable access to instances.
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Environment Configuration
Parameters:
- SystemName
- Environment
- Label:
default: EC2 Instance Keypair Name
Parameters:
- KeyName
Resources:
BastionEc2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !FindInMap [ !Ref Environment, BastionEc2Instance, InstanceType ]
ImageId: !FindInMap [ !Ref Environment, BastionEc2Instance, AmiId ]
KeyName: !Ref KeyName
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
VolumeType: gp2
VolumeSize: !FindInMap [ !Ref Environment, BastionEc2Instance, RootVolumeSize ]
DeleteOnTermination: true
NetworkInterfaces:
- SubnetId: !FindInMap [ !Ref Environment, PublicSubnet1a, ID ]
PrivateIpAddress: !FindInMap [ !Ref Environment, BastionEc2Instance, PrivateIpAddress ]
AssociatePublicIpAddress: false
GroupSet:
- !FindInMap [ !Ref Environment, BastionEc2Instance, SecurityGroupId ]
DeviceIndex: 0
DeleteOnTermination: true
DisableApiTermination: true
UserData:
Fn::Base64:
!Sub
- |
# hostname
Rename-Computer -NewName ${HostName} -Force
# TimeZone
Set-TimeZone -id "${TimeZone}"
# time sync
w32tm /config /manualpeerlist:169.254.169.123 /syncfromflags:manual /update
- { HostName: !FindInMap [ !Ref Environment, BastionEc2Instance, HostName ], TimeZone: !FindInMap [ !Ref Environment, OSSettings, TimeZone ] }
Tags:
- Key: Name
Value: !FindInMap [ !Ref Environment, BastionEc2Instance, HostName ]
Linux
Linux1台構築します。EC2の設定に加え、ホスト名、時刻同期、タイムゾーンを設定します。
AWSTemplateFormatVersion: '2010-09-09'
Description: This CloudFormation template to create EC2 instances.
Mappings:
prd:
PublicSubnet1a: { ID: subnet-xxxxxx }
PublicSubnet1c: { ID: subnet-xxxxxx }
PrivateSubnet1a: { ID: subnet-xxxxxx }
PrivateSubnet1c: { ID: subnet-xxxxxx }
OSSettings:
Locale: ja_JP.utf8
TimeZone: "Asia/Tokyo"
BastionEc2Instance:
HostName: xxxx_ec2
InstanceType: t3.small
AmiId: ami-0a2de1c3b415889d2
RootVolumeSize: 50
PrivateIpAddress: xx.xx.xx.xx
SecurityGroupId: sg-xxxxxxx
Parameters:
Environment:
Description: Type of this environment.
Type: String
Default: prd
AllowedValues:
- prd
- stg
SystemName:
Description: Name of this system.
Type: String
Default: chiba-web
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Name of an existing EC2 KeyPair to enable access to instances.
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Environment Configuration
Parameters:
- SystemName
- Environment
- Label:
default: EC2 Instance Keypair Name
Parameters:
- KeyName
Resources:
# Bastion instance
BastionEc2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !FindInMap [ !Ref Environment, BastionEc2Instance, InstanceType ]
ImageId: !FindInMap [ !Ref Environment, BastionEc2Instance, AmiId ]
KeyName: !Ref KeyName
CreditSpecification:
CPUCredits: standard
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp2
VolumeSize: !FindInMap [ !Ref Environment, BastionEc2Instance, RootVolumeSize ]
DeleteOnTermination: true
NetworkInterfaces:
- SubnetId: !FindInMap [ !Ref Environment, PublicSubnet1a, ID ]
PrivateIpAddress: !FindInMap [ !Ref Environment, BastionEc2Instance, PrivateIpAddress ]
AssociatePublicIpAddress: false
GroupSet:
- !FindInMap [ !Ref Environment, BastionEc2Instance, SecurityGroupId ]
DeviceIndex: 0
DeleteOnTermination: true
DisableApiTermination: true
UserData:
Fn::Base64:
!Sub
- |
#!/bin/sh -ex
# timezon
timedatectl set-timezone ${TimeZone}
# hostname
hostnamectl set-hostname --static ${HostName}
echo 'preserve_hostname: true' >> /etc/cloud/cloud.cfg
# time sync
yum erase 'ntp*'
yum install chrony
echo '#Add TimeSync' >> /etc/chrony.conf
echo 'server 169.254.169.123 prefer iburst' >> /etc/chrony.conf
systemctl start chrony
systemctl enable chrony
# locale
localectl set-locale LANG=${Locale}
- { HostName: !FindInMap [ !Ref Environment, BastionEc2Instance, HostName ], TimeZone: !FindInMap [ !Ref Environment, OSSettings, TimeZone ], Locale: !FindInMap [ !Ref Environment, OSSettings, Locale ] }
Tags:
- Key: Name
Value: !FindInMap [ !Ref Environment, BastionEc2Instance, HostName ]
まとめ
仕事はサクッと終わらせて早く帰りたい派のみなさま。早く帰って家族と過ごしたり、自分のスキル磨いたり、ゲームしたり、温泉入ったりライフワークバランスを大切にしたいものです。