Debugging Tips: cfn-init and configsets
Here are some debugging tips that will help when working with cfn-init.
How It Works
The cfn-init script is usually called by the UserData script to kick off a bootstrap process. The cfn-init call is what actually applies the configset.
UserData cfn-init
You can make sure configsets are applied when instances are launched by calling the cfn-init
script in UserData. Here’s an example UserData script.
#!/bin/bash
yum install -y aws-cfn-bootstrap # install cfn-init
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource Instance --region ${AWS::Region}
The ${AWS::StackName}
and ${AWS::Region}
will be substituted for their actual values at CloudFormation runtime. The --resource Instance
specifies which resource logical id in the CloudFormation template that has the metadata with configset instructions to apply.
Note: On AmazonLinux2 cfn-init is already installed.
Run Manually
The UserData script runs at launch time automatically. But you can also invoke the cfn-init
script manually. Just log into the instance and call it. This can be especially useful for debugging. Here’s an example of running the script.
/opt/aws/bin/cfn-init -v --stack my-stack --resource Instance --region us-west-2
The command above downloads the Configset from CloudFormation template Instance
resource and applies it.
Where is the metadata.json downloaded?
The cfn-init
downloads the configset metadata to:
/var/lib/cfn-init/data/metadata.json
Note, this file gets overwritten each time cfn-init
runs.
Run With a File
One quick way to debug configsets is to copy the generated /var/lib/cfn-init/data/metadata.json
, modify it, and provide it directly to the cfn-init
command. Example:
cp /var/lib/cfn-init/data/metadata.json /root/configset.json
/opt/aws/bin/cfn-init -v /root/configset.json
The cfn-init script itself only supports JSON when providing a file.
Here’s a YAML to JSON One Liner to help you convert it.
Running repeatedly with lono
Though knowing how to run the configset on the local machine is very helpful in understanding how configsets work, have found that is is quickest to just use lono to repeatedly apply the configsets in one terminal and while watching the logs in another terminal. In one terminal:
lono up BLUEPRINT -y
In another terminal, ssh into the machine and tail the logs with:
tail -f /var/log/cfn-init.log
Where are the Logs?
Knowing where the cfn-init related logs are can also save a ton of time.
Path | Description |
---|---|
/var/log/cfn-init-cmd.log | cfn-init and command output with timestamps. |
/var/log/cfn-init.log | cfn-init and command output. Useful for when cfn-init is manually ran. |
/var/log/cloud-init.log | cloud-init logs from UserData launch script. |
/var/log/cloud-init-output.log | Output from the cloud-init UserData commands themselves. Useful for when the instance is launched for the first time. |
cfn-hup reloader
The UserData script runs only at launch time. This means if you make changes to the CloudFormation Metadata.AWS::CloudFormation::Init
configset, they do not magically get applied. The cfn-hup daemon must be set up. The cfn-hup daemon listens for changes in the metadata and applies them automatically.
It is recommended to set up cfn-hup reloader, so you do not have to log into the instance and kick off the cfn-init script manually.
Here’s the cfn-hup configset that sets up the cfn-hup reloader. The BoltOps Pro cfn-hup configset is available for free.
cfn-hup retries
Notice that cfn-hup will repeatedly retry running the configsets until it has successfully completed. So if you have an instruction in the the configset that is failing, you’ll see in the /var/log/cfn-init.log
repeatedly running every minute or so. Unsure if there’s a way to control this behavior.