cloudpack あら便利カレンダー 2019 の記事となります。誕生秘話 はこちら。
AWS CloudFormation(CFn)でEC2インスタンスを作成するのに、AWS::CloudFormation::Init
タイプを利用すると、インスタンス起動後にパッケージのインストールやファイル作成、コマンド実行を含めることができて便利そうだったのでお試ししてみました。
個人的に一番のメリットはスタック更新時にメタデータの変更も検知して再実行させることができる点です。
AWS::CloudFormation::Init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
利用するのにいくつかのドキュメントを渡り歩く必要があったので、必要最低限のテンプレートと利用方法、ポイントをまとめました。
前提
- AWSアカウントがある
- AWS CLIがインストール済みで利用可能
- CFn、EC2関連の権限がある
テンプレート
EC2インスタンスを作成・管理するテンプレートとなります。
EC2インスタンスを起動するVPCやサブネットは既存のリソースを利用前提となります。
SSHアクセスする際のキーペアは事前に作成し、セキュリティグループはインスタンスとあわせて作成しています。
作成するリージョンは検証なので、us-east-1
のみとしています。
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
SubnetId:
Type: AWS::EC2::Subnet::Id
EC2KeyPairName:
Type: AWS::EC2::KeyPair::KeyName
InstanceType:
Type: String
Default: t3.small
MyInstanceSSHCidrIp:
Type: String
Default: '0.0.0.0/0'
Mappings:
AWSRegionToAMI:
us-east-1:
HVM64: ami-0080e4c5bc078760e
Resources:
MyInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Join
- " "
- - !Ref AWS::StackName
- "SecurityGroup"
GroupDescription: "MyInstance SecurityGroup"
VpcId: !Ref VpcId
SecurityGroupEgress:
-
CidrIp: "0.0.0.0/0"
IpProtocol: "-1"
SecurityGroupIngress:
-
CidrIp: !Ref MyInstanceSSHCidrIp
Description: !Join
- " "
- - !Ref AWS::StackName
- "SSH Port"
IpProtocol: "tcp"
FromPort: 22
ToPort: 22
Tags:
-
Key: "Name"
Value: !Join
- " "
- - !Ref AWS::StackName
- "SecurityGroup"
MyInstance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
files:
/etc/cfn/cfn-hup.conf:
content: !Sub |
[main]
stack = ${AWS::StackName}
region = ${AWS::Region}
interval = 1
mode: "000400"
owner: "root"
group: "root"
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
content: !Sub |
[cfn-auto-reloader-hook]
triggers = post.update
path = Resources.MyInstance.Metadata.AWS::CloudFormation::Init
action = /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource MyInstance --region ${AWS::Region}
runas = root
mode: "000400"
owner: "root"
group: "root"
commands:
test:
command: "echo $STACK_NAME test"
env:
STACK_NAME: !Ref AWS::StackName
services:
sysvinit:
cfn-hup:
enabled: "true"
files:
- /etc/cfn/cfn-hup.conf
- /etc/cfn/hooks.d/cfn-auto-reloader.conf
Properties:
InstanceType: !Ref InstanceType
KeyName: !Ref EC2KeyPairName
ImageId: !FindInMap [ AWSRegionToAMI, !Ref "AWS::Region", HVM64 ]
IamInstanceProfile: !Ref AWS::NoValue
NetworkInterfaces:
- AssociatePublicIpAddress: True
DeviceIndex: 0
GroupSet:
- !Ref MyInstanceSecurityGroup
SubnetId: !Ref SubnetId
Tags:
- Key: 'Name'
Value: !Ref AWS::StackName
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
echo "start UserData"
/opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource MyInstance --region ${AWS::Region}
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MyInstance --region ${AWS::Region}
echo "finish UserData"
CreationPolicy:
ResourceSignal:
Timeout: PT5M
Outputs:
ClientInstanceId:
Value: !Ref MyInstance
ClientPublicIp:
Value: !GetAtt MyInstance.PublicIp
ポイント
AWS::CloudFormation::Init
タイプを利用する
AWS::CloudFormation::Init
タイプを利用すると、EC2インスタンスでcfn-init
ヘルパースクリプト用のメタデータとして取り込まれて実行されます。
cfn-init
ヘルパースクリプトはメタデータに応じて以下のような操作を行います。
- CFnのメタデータの取得と解析
- パッケージのインストール
- ディスクへのファイルの書き込み
- Linux/UNIXグループ・ユーザー作成
- ソースのダウンロード・展開
- コマンド実行
- サービスの有効化/無効化と開始/停止
詳しくは下記が参考になります。
AWS::CloudFormation::Init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
cfn-init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-init.html
今回のテンプレートではメタデータでファイル書き込み、コマンド実行とサービス有効化する定義をしています。詳細は後ほど。
MyInstance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
files:
/etc/cfn/cfn-hup.conf:
content: !Sub |
[main]
stack = ${AWS::StackName}
region = ${AWS::Region}
interval = 1
mode: "000400"
owner: "root"
group: "root"
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
(略)
commands:
test:
command: "echo $STACK_NAME test2"
env:
STACK_NAME: !Ref AWS::StackName
services:
sysvinit:
cfn-hup:
(略)
cfn-init
ヘルパースクリプトをUserData
で実行する
AWS::CloudFormation::Init
タイプを利用してメタデータを定義しただけだと、スタック作成時にcfn-init
ヘルパースクリプトは実行されないため、ユーザーデータを定義して実行します。
ユーザーデータについては下記が参考になります。
Linux インスタンスでの起動時のコマンドの実行 - Amazon Elastic Compute Cloud
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html
今回のテンプレートでは/opt/aws/bin/cfn-init
でエラーとなった場合、リソース作成失敗となるように/opt/aws/bin/cfn-signal
も実行するようにしています。/opt/aws/bin/cfn-signal
を利用する場合には、CreationPolicy
を定義しておく必要があります。
cfn-signal
ヘルパースクリプトについては下記が参考になります。
cfn-signal - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-signal.html
MyInstance:
(略)
Properties:
(略)
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
echo "start UserData"
/opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource MyInstance --region ${AWS::Region}
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MyInstance --region ${AWS::Region}
echo "finish UserData"
CreationPolicy:
ResourceSignal:
Timeout: PT5M
cfn-hup
ヘルパーでメタデータ更新時に対応する
メタデータとユーザーデータの定義だけだと、メタデータを変更してスタック更新しても変更が検知されず、EC2インスタンスに反映されないため、cfn-hup
ヘルパーを利用する必要があります。cfn-hup
ヘルパーはEC2インスタンスでデーモンとして実行が可能です。
cfn-hup
デーモンを実行するためにはcfn-hup.conf
とhooks.conf
ファイルを用意する必要があるため、メタデータで定義しています。
cfn-hup
ヘルパーについては下記が参考になります。
cfn-hup - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-hup.html
MyInstance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
files:
/etc/cfn/cfn-hup.conf:
content: !Sub |
[main]
stack = ${AWS::StackName}
region = ${AWS::Region}
interval = 1
mode: "000400"
owner: "root"
group: "root"
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
content: !Sub |
[cfn-auto-reloader-hook]
triggers = post.update
path = Resources.MyInstance.Metadata.AWS::CloudFormation::Init
action = /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource MyInstance --region ${AWS::Region}
runas = root
mode: "000400"
owner: "root"
group: "root"
commands:
(略)
services:
sysvinit:
cfn-hup:
enabled: "true"
files:
- /etc/cfn/cfn-hup.conf
- /etc/cfn/hooks.d/cfn-auto-reloader.conf
利用方法
パラメータ値を取得
キーペア
EC2インスタンスへSSHログインするのに利用するキーペアを作成します。
既存のキーペアを利用する場合は作成不要です。
# Create KeyPair
> aws ec2 create-key-pair \
--key-name cfn-init-test-ec2-key \
--query "KeyMaterial" \
--output text > cfn-init-test-ec2-key.pem
> chmod 400 cfn-init-test-ec2-key.pem
VPC、サブネット
既存のVPC、サブネット配下にEC2インスタンスを作成する前提ですので各IDを取得します。
# VpcId
> aws ec2 describe-vpcs \
--query "Vpcs"
[
{
"CidrBlock": "172.31.0.0/16",
"DhcpOptionsId": "dopt-b06bd8c8",
"State": "available",
"VpcId": "vpc-xxxxxxxx",
"OwnerId": "xxxxxxxxxxxx",
"InstanceTenancy": "default",
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-2b23e646",
"CidrBlock": "172.31.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": true
},
]
# SubnetId
> aws ec2 describe-subnets \
--filters '{"Name": "vpc-id", "Values": ["vpc-xxxxxxxx"]}' \
--query "Subnets"
[
{
"AvailabilityZone": "us-east-1a",
"AvailabilityZoneId": "use1-az2",
"AvailableIpAddressCount": 4089,
"CidrBlock": "172.31.80.0/20",
"DefaultForAz": true,
"MapPublicIpOnLaunch": true,
"State": "available",
"SubnetId": "subnet-xxxxxxxx",
"VpcId": "vpc-xxxxxxxx",
"OwnerId": "xxxxxxxxxxxx",
"AssignIpv6AddressOnCreation": false,
"Ipv6CidrBlockAssociationSet": [],
"SubnetArn": "arn:aws:ec2:us-east-1:xxxxxxxxxxxx:subnet/subnet-xxxxxxxx"
},
]
自身のグローバルIP
SSHアクセスするためのセキュリティグループに指定するIPアドレスを取得します。
ここではifconfig.io
を利用していますが他の手段でもOKです。
## GlobalIP
> curl ifconfig.io
xxx.xxx.xxx.xxx
スタック作成
aws cloudformation create-stack
コマンドを利用してスタック作成します。
AWSマネジメントコンソールから作成してもOKです。
> aws cloudformation create-stack \
--stack-name cfn-init-test \
--template-body file://cfn-init-template.yaml \
--capabilities CAPABILITY_IAM \
--region us-east-1 \
--parameters '[
{
"ParameterKey": "VpcId",
"ParameterValue": "vpc-xxxxxxxx"
},
{
"ParameterKey": "SubnetId",
"ParameterValue": "subnet-xxxxxxxx"
},
{
"ParameterKey": "EC2KeyPairName",
"ParameterValue": "cfn-init-test-ec2-key"
},
{
"ParameterKey": "MyInstanceSSHCidrIp",
"ParameterValue": "xxx.xxx.xxx.xxx/32"
}
]'
スタック作成結果を確認
スタック作成ができたか確認します。
> aws cloudformation describe-stacks \
--stack-name cfn-init-test
{
"Stacks": [
{
"StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-init-test/a1dc6aa0-a9e6-11e9-b171-0a515b01a4a4",
"StackName": "cfn-init-test",
"Parameters": [
{
"ParameterKey": "MyInstanceSSHCidrIp",
"ParameterValue": "xxx.xxx.xxx.xxx/32"
},
{
"ParameterKey": "VpcId",
"ParameterValue": "vpc-xxxxxxxx"
},
{
"ParameterKey": "EC2KeyPairName",
"ParameterValue": "cfn-init-test-ec2-key"
},
{
"ParameterKey": "SubnetId",
"ParameterValue": "subnet-xxxxxxxx"
},
{
"ParameterKey": "InstanceType",
"ParameterValue": "t3.small"
}
],
"CreationTime": "2019-07-19T05:32:43.477Z",
"RollbackConfiguration": {},
"StackStatus": "CREATE_COMPLETE",
"DisableRollback": false,
"NotificationARNs": [],
"Capabilities": [
"CAPABILITY_IAM"
],
"Outputs": [
{
"OutputKey": "ClientPublicIp",
"OutputValue": "xxx.xxx.xxx.xxx"
},
{
"OutputKey": "ClientInstanceId",
"OutputValue": "i-xxxxxxxxxxxxxxxxx"
}
],
"Tags": [],
"EnableTerminationProtection": false,
"DriftInformation": {
"StackDriftStatus": "NOT_CHECKED"
}
}
]
}
EC2インスタンスで確認
テンプレートのOutputs
でEC2インスタンスのIPアドレス('ClientPublicIp' )が出力されるようにしているので、SSHログインして各ログを確認します。
CFnでEC2インスタンスを作成するといくつかのログファイルが作成されますが、下記のファイル確認しておくとだいたいは把握できます。
> ssh -i cfn-init-test-ec2-key.pem ec2-user@xxx.xxx.xxx.xxx
$ cat /var/log/cfn-init.log
2019-07-19 06:53:00,454 [INFO] -----------------------Starting build-----------------------
2019-07-19 06:53:00,455 [INFO] Running configSets: default
2019-07-19 06:53:00,455 [INFO] Running configSet default
2019-07-19 06:53:00,456 [INFO] Running config config
2019-07-19 06:53:00,460 [INFO] Command test succeeded
2019-07-19 06:53:00,467 [INFO] enabled service cfn-hup
2019-07-19 06:53:00,768 [INFO] Restarted cfn-hup successfully
2019-07-19 06:53:00,769 [INFO] ConfigSets completed
2019-07-19 06:53:00,769 [INFO] -----------------------Build complete-----------------------
2019-07-19 06:53:01,055 [DEBUG] CloudFormation client initialized with endpoint https://cloudformation.us-east-1.amazonaws.com
2019-07-19 06:53:01,055 [DEBUG] Signaling resource MyInstance in stack cfn-init-test with unique ID i-xxxxxxxxxxxxxxxxx and status SUCCESS
$ cat /var/log/cfn-init-cmd.log
2019-07-19 06:53:00,455 P2208 [INFO] ************************************************************
2019-07-19 06:53:00,455 P2208 [INFO] ConfigSet default
2019-07-19 06:53:00,456 P2208 [INFO] ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2019-07-19 06:53:00,456 P2208 [INFO] Config config
2019-07-19 06:53:00,457 P2208 [INFO] ============================================================
2019-07-19 06:53:00,457 P2208 [INFO] Command test
2019-07-19 06:53:00,460 P2208 [INFO] -----------------------Command Output-----------------------
2019-07-19 06:53:00,460 P2208 [INFO] cfn-init-test test
2019-07-19 06:53:00,460 P2208 [INFO] ------------------------------------------------------------
2019-07-19 06:53:00,460 P2208 [INFO] Completed successfully.
$ cat /var/log/cloud-init-output.log
(略)
Updated:
java-1.7.0-openjdk.x86_64 1:1.7.0.211-2.6.17.1.79.amzn1
kernel-tools.x86_64 0:4.14.128-87.105.amzn1
perl.x86_64 4:5.16.3-294.43.amzn1
perl-Pod-Escapes.noarch 1:1.04-294.43.amzn1
perl-libs.x86_64 4:5.16.3-294.43.amzn1
perl-macros.x86_64 4:5.16.3-294.43.amzn1
python27-jinja2.noarch 0:2.7.2-3.16.amzn1
wget.x86_64 0:1.18-5.30.amzn1
Complete!
Cloud-init v. 0.7.6 running 'modules:final' at Fri, 19 Jul 2019 05:33:29 +0000. Up 19.60 seconds.
start UserData
finish UserData
Cloud-init v. 0.7.6 finished at Fri, 19 Jul 2019 05:33:31 +0000. Datasource DataSourceEc2. Up 20.79 seconds
スタック更新に関わるログとファイルは以下となります。
cfn-hup
デーモンが定期的にCFnスタックのメタデータを取得しmetadata_db.json
に保存、メタデータとファイルに差分があるとcfn-auto-reloader.conf
で指定したアクション(コマンド)が実行される仕組みになっています。
なので、スタック作成後、cfn-hup
デーモンが1度もメタデータ取得していないタイミングでスタック更新しても、metadata_db.json
が存在していないと変更が検知されないみたいです。(1敗
$ cat /var/log/cfn-hup.log
2019-07-19 06:53:00,750 [DEBUG] CloudFormation client initialized with endpoint https://cloudformation.us-east-1.amazonaws.com
2019-07-19 06:53:00,750 [DEBUG] Creating /var/lib/cfn-hup/data
2019-07-19 06:53:00,756 [INFO] No umask value specified in config file. Using the default one: 022
$ sudo cat /var/lib/cfn-hup/data/metadata_db.json
{"cfn-auto-reloader-hook|Resources.MyInstance.Metadata.AWS::CloudFormation::Init": {"config": {"files": {"/etc/cfn/cfn-hup.conf": {"owner": "root", "content": "[main]\nstack = cfn-init-test\nregion = us-east-1\ninterval = 1\n", "group": "root", "mode": "000400"}, "/etc/cfn/hooks.d/cfn-auto-reloader.conf": {"owner": "root", "content": "[cfn-auto-reloader-hook]\ntriggers = post.update\npath = Resources.MyInstance.Metadata.AWS::CloudFormation::Init\naction = /opt/aws/bin/cfn-init -v --stack cfn-init-test --resource MyInstance --region us-east-1\nrunas = root\n", "group": "root", "mode": "000400"}}, "services": {"sysvinit": {"cfn-hup": {"files": ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"], "enabled": "true"}}}, "commands": {"test": {"command": "echo $STACK_NAME test", "env": {"STACK_NAME": "cfn-init-test"}}}}}}
メタデータを編集してスタック更新する
メタデータに実行するコマンドを追加してスタック更新してみます。
(略)
commands:
test:
command: "echo $STACK_NAME test"
env:
STACK_NAME: !Ref AWS::StackName
test2:
command: "echo $STACK_NAME test2"
env:
STACK_NAME: !Ref AWS::StackName
(略)
aws cloudformation update-stack
コマンドを実行してスタック更新します。
> aws cloudformation update-stack \
--stack-name cfn-init-test \
--template-body file://cfn-init-template.yaml \
--capabilities CAPABILITY_IAM \
--region us-east-1 \
--parameters '[
{
"ParameterKey": "VpcId",
"ParameterValue": "vpc-xxxxxxxx"
},
{
"ParameterKey": "SubnetId",
"ParameterValue": "subnet-xxxxxxxx"
},
{
"ParameterKey": "EC2KeyPairName",
"ParameterValue": "cfn-init-test-ec2-key"
},
{
"ParameterKey": "MyInstanceSSHCidrIp",
"ParameterValue": "xxx.xxx.xxx.xxx/32"
}
]'
スタック更新結果を確認
> aws cloudformation describe-stacks \
--stack-name cfn-init-test
{
"Stacks": [
{
"StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-init-test/a1dc6aa0-a9e6-11e9-b171-0a515b01a4a4",
"StackName": "cfn-init-test",
"Parameters": [
{
"ParameterKey": "MyInstanceSSHCidrIp",
"ParameterValue": "xxx.xxx.xxx.xxx/32"
},
{
"ParameterKey": "VpcId",
"ParameterValue": "vpc-xxxxxxxx"
},
{
"ParameterKey": "EC2KeyPairName",
"ParameterValue": "cfn-init-test-ec2-key"
},
{
"ParameterKey": "SubnetId",
"ParameterValue": "subnet-xxxxxxxx"
},
{
"ParameterKey": "InstanceType",
"ParameterValue": "t3.small"
}
],
"CreationTime": "2019-07-19T05:32:43.477Z",
"LastUpdatedTime": "2019-07-19T05:41:40.446Z",
"RollbackConfiguration": {},
"StackStatus": "UPDATE_COMPLETE",
"DisableRollback": false,
"NotificationARNs": [],
"Capabilities": [
"CAPABILITY_IAM"
],
"Outputs": [
{
"OutputKey": "ClientPublicIp",
"OutputValue": "xxx.xxx.xxx.xxx"
},
{
"OutputKey": "ClientInstanceId",
"OutputValue": "i-xxxxxxxxxxxxxxxxx"
}
],
"Tags": [],
"EnableTerminationProtection": false,
"DriftInformation": {
"StackDriftStatus": "NOT_CHECKED"
}
}
]
}
EC2インスタンスで確認
CFnのリソース更新されてもEC2インスタンス側への変更反映は、cfn-hup
ヘルパーが担当しますので、反映にはタイムラグが発生します。cfn-hup
ヘルパーがメタデータの変更確認する間隔は初期設定で15分となっており、/etc/cfn/cfn-hup.conf
ファイルのinterval
で指定ができます。(今回は1分で指定)
cfn-hup - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-hup.html
> ssh -i cfn-init-test-ec2-key.pem ec2-user@xxx.xxx.xxx.xxx
$ cat /var/log/cfn-init.log
2019-07-19 06:53:00,454 [INFO] -----------------------Starting build-----------------------
2019-07-19 06:53:00,455 [INFO] Running configSets: default
2019-07-19 06:53:00,455 [INFO] Running configSet default
2019-07-19 06:53:00,456 [INFO] Running config config
2019-07-19 06:53:00,460 [INFO] Command test succeeded
2019-07-19 06:53:00,467 [INFO] enabled service cfn-hup
2019-07-19 06:53:00,768 [INFO] Restarted cfn-hup successfully
2019-07-19 06:53:00,769 [INFO] ConfigSets completed
2019-07-19 06:53:00,769 [INFO] -----------------------Build complete-----------------------
2019-07-19 06:53:01,055 [DEBUG] CloudFormation client initialized with endpoint https://cloudformation.us-east-1.amazonaws.com
2019-07-19 06:53:01,055 [DEBUG] Signaling resource MyInstance in stack cfn-init-test with unique ID i-xxxxxxxxxxxxxxxxx and status SUCCESS
2019-07-19 06:56:01,457 [DEBUG] CloudFormation client initialized with endpoint https://cloudformation.us-east-1.amazonaws.com
2019-07-19 06:56:01,458 [DEBUG] Describing resource MyInstance in stack cfn-init-test
2019-07-19 06:56:01,522 [INFO] -----------------------Starting build-----------------------
2019-07-19 06:56:01,523 [DEBUG] Not setting a reboot trigger as scheduling support is not available
2019-07-19 06:56:01,524 [INFO] Running configSets: default
2019-07-19 06:56:01,525 [INFO] Running configSet default
2019-07-19 06:56:01,525 [INFO] Running config config
2019-07-19 06:56:01,526 [DEBUG] No packages specified
2019-07-19 06:56:01,526 [DEBUG] No groups specified
2019-07-19 06:56:01,526 [DEBUG] No users specified
2019-07-19 06:56:01,526 [DEBUG] No sources specified
2019-07-19 06:56:01,526 [DEBUG] /etc/cfn/cfn-hup.conf already exists
2019-07-19 06:56:01,526 [DEBUG] Moving /etc/cfn/cfn-hup.conf to /etc/cfn/cfn-hup.conf.bak
2019-07-19 06:56:01,526 [DEBUG] Writing content to /etc/cfn/cfn-hup.conf
2019-07-19 06:56:01,526 [DEBUG] Setting mode for /etc/cfn/cfn-hup.conf to 000400
2019-07-19 06:56:01,526 [DEBUG] Setting owner 0 and group 0 for /etc/cfn/cfn-hup.conf
2019-07-19 06:56:01,527 [DEBUG] /etc/cfn/hooks.d/cfn-auto-reloader.conf already exists
2019-07-19 06:56:01,527 [DEBUG] Moving /etc/cfn/hooks.d/cfn-auto-reloader.conf to /etc/cfn/hooks.d/cfn-auto-reloader.conf.bak
2019-07-19 06:56:01,527 [DEBUG] Writing content to /etc/cfn/hooks.d/cfn-auto-reloader.conf
2019-07-19 06:56:01,527 [DEBUG] Setting mode for /etc/cfn/hooks.d/cfn-auto-reloader.conf to 000400
2019-07-19 06:56:01,527 [DEBUG] Setting owner 0 and group 0 for /etc/cfn/hooks.d/cfn-auto-reloader.conf
2019-07-19 06:56:01,527 [DEBUG] Running command test
2019-07-19 06:56:01,527 [DEBUG] No test for command test
2019-07-19 06:56:01,531 [INFO] Command test succeeded
2019-07-19 06:56:01,531 [DEBUG] Command test output: cfn-init-test test
2019-07-19 06:56:01,531 [DEBUG] Running command test2
2019-07-19 06:56:01,531 [DEBUG] No test for command test2
2019-07-19 06:56:01,535 [INFO] Command test2 succeeded
2019-07-19 06:56:01,536 [DEBUG] Command test2 output: cfn-init-test test!
2019-07-19 06:56:01,536 [DEBUG] Using service modifier: /sbin/chkconfig
2019-07-19 06:56:01,536 [DEBUG] Setting service cfn-hup to enabled
2019-07-19 06:56:01,538 [INFO] enabled service cfn-hup
2019-07-19 06:56:01,539 [DEBUG] Not modifying running state of service cfn-hup
2019-07-19 06:56:01,539 [INFO] ConfigSets completed
2019-07-19 06:56:01,539 [DEBUG] Not clearing reboot trigger as scheduling support is not available
2019-07-19 06:56:01,539 [INFO] -----------------------Build complete-----------------------
$ cat /var/log/cfn-init-cmd.log
2019-07-19 06:53:00,455 P2208 [INFO] ************************************************************
2019-07-19 06:53:00,455 P2208 [INFO] ConfigSet default
2019-07-19 06:53:00,456 P2208 [INFO] ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2019-07-19 06:53:00,456 P2208 [INFO] Config config
2019-07-19 06:53:00,457 P2208 [INFO] ============================================================
2019-07-19 06:53:00,457 P2208 [INFO] Command test
2019-07-19 06:53:00,460 P2208 [INFO] -----------------------Command Output-----------------------
2019-07-19 06:53:00,460 P2208 [INFO] cfn-init-test test
2019-07-19 06:53:00,460 P2208 [INFO] ------------------------------------------------------------
2019-07-19 06:53:00,460 P2208 [INFO] Completed successfully.
2019-07-19 06:56:01,525 P2337 [INFO] ************************************************************
2019-07-19 06:56:01,525 P2337 [INFO] ConfigSet default
2019-07-19 06:56:01,525 P2337 [INFO] ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2019-07-19 06:56:01,526 P2337 [INFO] Config config
2019-07-19 06:56:01,527 P2337 [INFO] ============================================================
2019-07-19 06:56:01,527 P2337 [INFO] Command test
2019-07-19 06:56:01,530 P2337 [INFO] -----------------------Command Output-----------------------
2019-07-19 06:56:01,531 P2337 [INFO] cfn-init-test test
2019-07-19 06:56:01,531 P2337 [INFO] ------------------------------------------------------------
2019-07-19 06:56:01,531 P2337 [INFO] Completed successfully.
2019-07-19 06:56:01,531 P2337 [INFO] ============================================================
2019-07-19 06:56:01,531 P2337 [INFO] Command test2
2019-07-19 06:56:01,535 P2337 [INFO] -----------------------Command Output-----------------------
2019-07-19 06:56:01,535 P2337 [INFO] cfn-init-test test!
2019-07-19 06:56:01,535 P2337 [INFO] ------------------------------------------------------------
2019-07-19 06:56:01,535 P2337 [INFO] Completed successfully.
$ cat /var/log/cloud-init-output.log
(略)
Updated:
java-1.7.0-openjdk.x86_64 1:1.7.0.211-2.6.17.1.79.amzn1
kernel-tools.x86_64 0:4.14.128-87.105.amzn1
perl.x86_64 4:5.16.3-294.43.amzn1
perl-Pod-Escapes.noarch 1:1.04-294.43.amzn1
perl-libs.x86_64 4:5.16.3-294.43.amzn1
perl-macros.x86_64 4:5.16.3-294.43.amzn1
python27-jinja2.noarch 0:2.7.2-3.16.amzn1
wget.x86_64 0:1.18-5.30.amzn1
Complete!
Cloud-init v. 0.7.6 running 'modules:final' at Fri, 19 Jul 2019 06:52:59 +0000. Up 18.81 seconds.
start UserData
finish UserData
Cloud-init v. 0.7.6 finished at Fri, 19 Jul 2019 06:53:01 +0000. Datasource DataSourceEc2. Up 20.07 seconds
メタデータに追加したコマンドが実行されるのを確認できました。
やったぜ。
スタック更新時にメタデータで定義しているすべての処理を実行したくない場合、Configset
を用いるとグルーピングや実行順の制御をして特定の処理ができます。詳細は下記をご参考ください。
AWS::CloudFormation::Init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
まとめ
CFnでEC2インスタンスを作成する際に、インスタンス起動後の処理もテンプレートで定義して管理できる仕組みになっていますので、非常に使い勝手が良さそうです。
参考
AWS::CloudFormation::Init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
AWS::CloudFormation::Init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
cfn-init - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-init.html
Linux インスタンスでの起動時のコマンドの実行 - Amazon Elastic Compute Cloud
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html
cfn-signal - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-signal.html
cfn-hup - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-hup.html