On Ubuntu 20 LTS
Reference
Create CFn
Preparing helper scripts
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
Install CloudWatch Agent
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}
Creating amazon-cloudwatch-agent.json
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.
Creating a helper script
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.
- cfn-hup It is a daemon that detects changes in resource metadata and executes the operation specified by the user when the changes are made. This time, the stack update event is detected as a trigger, and when it is detected, the action in the configuration file under hooks.d is executed.
–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.
For CloudWatch agent Configuration refer to
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.
Create roles for CloudWatch Agent
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
Creating an instance profile
Finally, create an instance profile to pass the role you just created to EC2.
CWAgentInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - !Ref CloudwatchRole