CloudFormation helper scripts are very useful, aren't they? Just by defining a script in the template, you can install the software and start the service when creating EC2.
This time, I had the opportunity to install the Cloudwatch agent and create a configuration file using that helper script, so I'd like to write it so that I don't forget it.
Immediately install the cloudwatch agent using the helper script! Unfortunately, it is not installed on Ubuntu by default. So, first download the aws-cfn-bootstrap package. Add the following script to the helper script in UserDate that is executed when EC2 starts.
apt-get update
apt-get install -y python-setuptools
mkdir -p /opt/aws/bin
apt-get install -y wget
wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
python3 -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-py3-latest.tar.gz
Then install the cloudwatch agent. Add this to UserDate as well.
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb -O /tmp/amazon-cloudwatch-agent.deb
dpkg -i /tmp/amazon-cloudwatch-agent.deb
/opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource EC2 --region ${AWS::Region} --configsets default
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource EC2 --region ${AWS::Region}
Now that we have installed the helper script and cloudwatch agent, let's create the configuration file amazon-cloudwatch-agent.json
. For how to write the configuration file, I referred to Official Document.
Next is finally the helper script.
You can bring metadata for the cfn-init helper script into EC2 by using the AWS :: CloudFormation :: Init
type.
--hooks.conf configuration file A user action that the cfn-hup daemon calls on a regular basis is defined.
--cfn-hup.conf configuration file Contains the name of the stack targeted by the cfn-hup daemon and AWS credentials.
This time, when creating a new stack, go to default
, and when updating the metadata by updating the stack, go to UpdateEnvironment
.
EC2:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
configSets:
default:
- "01_setupCfnHup"
- "02_config_amazon-cloudwatch-agent"
- "03_restart_amazon-cloudwatch-agent"
UpdateEnvironment:
- "02_config_amazon-cloudwatch-agent"
- "03_restart_amazon-cloudwatch-agent"
01_setupCfnHup:
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.EC2.Metadata.AWS::CloudFormation::Init
action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource EC2 --configsets UpdateEnvironment --region ${AWS::Region}
runas=root
mode: '000400'
owner: root
group: root
/lib/systemd/system/cfn-hup.service:
content: !Sub |
[Unit]
Description=cfn-hup daemon
[Service]
Type=simple
ExecStart=/opt/aws/bin/cfn-hup
Restart=always
[Install]
WantedBy=multi-user.target
commands:
01enable_cfn_hup:
command: "systemctl enable cfn-hup.service"
02start_cfn_hup:
command: "systemctl start cfn-hup.service"
02_config_amazon-cloudwatch-agent:
files:
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json:
content: !Sub |
{
//Here amazon-cloudwatch-agent.write json//
}
mode: '000644'
owner: root
group: root
03_restart_amazon-cloudwatch-agent:
commands:
01_stop_service:
command: "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a stop"
02_start_service:
command: "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json"
It's a bit of a mess, but the "03_restart_amazon-cloudwatch-agent" command
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
Then, it seems that the agent is started by converting the json file to the toml format configuration file amazon-cloudwatch-agent.toml
. Therefore, the file amazon-cloudwatch-agent.json
does not exist in EC2 created with this CFn.
You must have permission to access AWS resources. Let's create an IAM role that gives EC2 the necessary privileges.
I have created a role CloudwatchRole
with the following policy attached.
--AWS Managed Policy - CloudWatchAgentServerPolicy - CloudWatchAgentAdminPolicy - AmazonSSMManagedInstanceCore --Custom policy --This time, I added a policy to allow access to S3 and logs. Good luck with the situation.
CloudwatchRole:
Type: AWS::IAM::Role
Properties:
RoleName: "CloudwatchRole"
Path: /
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: CloudwatchRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
//abridgement//
Resource: '*'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
- arn:aws:iam::aws:policy/CloudWatchAgentAdminPolicy
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Finally, create an instance profile to pass the role you just created to EC2.
CWAgentInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- !Ref CloudwatchRole
I've been addicted to creating CloudFormation, but it's easier to do it with CFn than to set it up with a wizard!
CloudFormation is full of things I still don't understand. It's deep.
(I would be grateful if you could tell me if there is another better way, I'm making a mistake here!)
--CloudFormation Helper Script Reference --AWS CloudFormation
--Manually create or edit CloudWatch agent configuration file --Amazon CloudWatch
--Install AWS CloudFormation helper scripts on Ubuntu or RHEL AMI
-First CloudWatch Agent introduction (SSM & CentOS) --Serverworks Engineer Blog
-(For beginners) Install CloudWatch Agent on EC2 and launch it on SSM | Developers.IO
-Try CloudWatch Agent-ngyuki's diary
Recommended Posts