AWS Tips and Tricks -
James Land - 14 Jan 2024
Intro
Studying for the AWS Solutions Architect exam and wanted to capture a couple neat tricks I learned from Cloud Guru
EC2
MetaData Web Page
The following little command block creates a neat web page that shows information about your EC2 instance assuming that Apache is installed. Could be useful for a future little demo.
Creating a Launch Template using this is great for showing off load balancers
#!/bin/bash
yum update -y
yum install httpd -y
systemctl start httpd
systemctl enable httpd
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
cd /var/www/html
echo '<html><h1>Bootstrap Demo</h1><h3>Availability Zone: ' > /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/availability-zone >> /var/www/html/index.html
echo '</h3> <h3>Instance Id: ' >> /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id >> /var/www/html/index.html
echo '</h3> <h3>Public IP: ' >> /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-ipv4 >> /var/www/html/index.html
echo '</h3> <h3>Local IP: ' >> /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4 >> /var/www/html/index.html
echo '</h3></html> ' >> /var/www/html/index.html
Note: The AWS Images have a package installed that lets you grab the meta data in a little bit cleaner way, by just doing something like
{ instance_id }
. You can get more information about how that works exactly here
Getting more Metadata information
When inside of the console you can run the following command in order to get top level metadata info:
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
This will return a list like this
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
managed-ssh-keys/
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
And you can dig into the subpaths by adding them to the original curl from above for example if you wanted to see what placement info you could use you would look at this:
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement -w "\n"
Examples
Note still need to clean up the examples below but just wanted to capture them for now.
Set up Logging Agent (Agent needs to be started manually)
{
"LaunchTemplateVersions": [
{
"LaunchTemplateName": "logging-example-template",
"VersionNumber": 2,
"CreateTime": "2024-01-21T16:51:16+00:00",
"CreatedBy": "arn:aws:iam::622679310130:user/jland@redhat.com-9752k",
"DefaultVersion": false,
"LaunchTemplateData": {
"EbsOptimized": true,
"IamInstanceProfile": {
"Arn": "arn:aws:iam::622679310130:instance-profile/EC2-Push-Permissions"
},
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"Encrypted": false,
"DeleteOnTermination": true,
"Iops": 3000,
"VolumeSize": 8,
"VolumeType": "gp3",
"Throughput": 125
}
}
],
"NetworkInterfaces": [
{
"AssociatePublicIpAddress": true,
"DeleteOnTermination": true,
"DeviceIndex": 0,
"Groups": [
"sg-084e1a1a570f46307"
],
"SubnetId": "subnet-0541ab44bc7136d6f"
}
],
"ImageId": "ami-04f767d954fe2d2d1",
"InstanceType": "t3.medium",
"KeyName": "my-key-pair",
"Monitoring": {
"Enabled": false
},
"Placement": {
"Tenancy": "default"
},
"DisableApiTermination": false,
"InstanceInitiatedShutdownBehavior": "stop",
"UserData": "IyEvYmluL2Jhc2gKCnN1ZG8geXVtIHVwZGF0ZSAteQpzdWRvIHl1bSBpbnN0YWxsIGFtYXpvbi1jbG91ZHdhdGNoLWFnZW50IC15CmRuZiBpbnN0YWxsIHJzeXNsb2cgLXkKc3lzdGVtY3RsIGVuYWJsZSByc3lzbG9nIC0tbm93CgpzdWRvIGNhdCA8PEVPRiA+Pi9vcHQvYXdzL2FtYXpvbi1jbG91ZHdhdGNoLWFnZW50L2V0Yy9hbWF6b24tY2xvdWR3YXRjaC1hZ2VudC5qc29uCnsKICAgICJhZ2VudCI6IHsKICAgICAgICAibWV0cmljc19jb2xsZWN0aW9uX2ludGVydmFsIjogNjAsCiAgICAgICAgInJ1bl9hc191c2VyIjogInJvb3QiLAogICAgICAgICJyZWdpb24iOiAidXMtZWFzdC0xIiwKICAgICAgICAiZGVidWciOiB0cnVlCiAgICB9LAogICAgImxvZ3MiOiB7CiAgICAgICAgImxvZ3NfY29sbGVjdGVkIjogewogICAgICAgICAgICAiZmlsZXMiOiB7CiAgICAgICAgICAgICAgICAiY29sbGVjdF9saXN0IjogWwogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgImZpbGVfcGF0aCI6ICIvdmFyL2xvZy9tZXNzYWdlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJsb2dfZ3JvdXBfbmFtZSI6ICJ7aW5zdGFuY2VfaWR9IiwKICAgICAgICAgICAgICAgICAgICAgICAgImxvZ19zdHJlYW1fbmFtZSI6ICJtZXNzYWdlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ0aW1lem9uZSI6ICJVVEMiCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICJmaWxlX3BhdGgiOiAiL3Zhci9sb2cvc2VjdXJlIiwKICAgICAgICAgICAgICAgICAgICAgICAgImxvZ19ncm91cF9uYW1lIjogIntpbnN0YW5jZV9pZH0iLAogICAgICAgICAgICAgICAgICAgICAgICAibG9nX3N0cmVhbV9uYW1lIjogInNlY3VyZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ0aW1lem9uZSI6ICJVVEMiCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgXQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CkVPRgoKCgojIERvIG5vdCBjb3B5IHRoaXMgaWYgeW91IHdhbnQgdG8gbWFudWFsbHkgc3RhcnQgdGhpcyBhZ2VudC4Kc3VkbyAvb3B0L2F3cy9hbWF6b24tY2xvdWR3YXRjaC1hZ2VudC9iaW4vYW1hem9uLWNsb3Vkd2F0Y2gtYWdlbnQtY3RsIC1hIGZldGNoLWNvbmZpZyAtbSBlYzIgLXMgLWMgZmlsZTovb3B0L2F3cy9hbWF6b24tY2xvdWR3YXRjaC1hZ2VudC9ldGMvYW1hem9uLWNsb3Vkd2F0Y2gtYWdlbnQuanNvbg==",
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [
{
"Key": "Name",
"Value": "logging-example"
}
]
}
],
"CreditSpecification": {
"CpuCredits": "unlimited"
},
"CpuOptions": {
"CoreCount": 1,
"ThreadsPerCore": 2
},
"CapacityReservationSpecification": {
"CapacityReservationPreference": "open"
},
"HibernationOptions": {
"Configured": false
},
"MetadataOptions": {
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2,
"HttpEndpoint": "enabled",
"HttpProtocolIpv6": "disabled",
"InstanceMetadataTags": "disabled"
},
"PrivateDnsNameOptions": {
"HostnameType": "ip-name",
"EnableResourceNameDnsARecord": false,
"EnableResourceNameDnsAAAARecord": false
},
"MaintenanceOptions": {
"AutoRecovery": "default"
},
"DisableApiStop": false
}
}
]
}
Decrypted User Data:
#!/bin/bash
sudo yum update -y
sudo yum install amazon-cloudwatch-agent -y
dnf install rsyslog -y
systemctl enable rsyslog --now
sudo cat <<EOF >>/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "root",
"region": "{item("meta-data/placement/availability-zone")}",
"debug": true
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/messages",
"log_group_name": "{instance_id}",
"log_stream_name": "messages",
"timezone": "UTC"
},
{
"file_path": "/var/log/secure",
"log_group_name": "{instance_id}",
"log_stream_name": "secure",
"timezone": "UTC"
}
]
}
}
}
}
EOF
# Do not copy this if you want to manually start this agent.
sudo /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
Set up basic WebServer
{
"LaunchTemplateVersions": [
{
"LaunchTemplateId": "lt-0217c0c6db5666424",
"LaunchTemplateName": "webserver-template",
"VersionNumber": 5,
"CreateTime": "2024-01-21T14:58:59+00:00",
"CreatedBy": "arn:aws:iam::622679310130:user/jland@redhat.com-9752k",
"DefaultVersion": true,
"LaunchTemplateData": {
"NetworkInterfaces": [
{
"AssociatePublicIpAddress": true,
"DeviceIndex": 0
}
],
"ImageId": "ami-04f767d954fe2d2d1",
"InstanceType": "t2.micro",
"KeyName": "my-key-pair",
"UserData": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQp5dW0gaW5zdGFsbCBodHRwZCAteQpzeXN0ZW1jdGwgc3RhcnQgaHR0cGQKc3lzdGVtY3RsIGVuYWJsZSBodHRwZApUT0tFTj1gY3VybCAtWCBQVVQgImh0dHA6Ly8xNjkuMjU0LjE2OS4yNTQvbGF0ZXN0L2FwaS90b2tlbiIgLUggIlgtYXdzLWVjMi1tZXRhZGF0YS10b2tlbi10dGwtc2Vjb25kczogMjE2MDAiYApjZCAvdmFyL3d3dy9odG1sCmVjaG8gJzxodG1sPjxoMT5Cb290c3RyYXAgRGVtbzwvaDE+PGgzPkF2YWlsYWJpbGl0eSBab25lOiAnID4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1sCmN1cmwgLUggIlgtYXdzLWVjMi1tZXRhZGF0YS10b2tlbjogJFRPS0VOIiBodHRwOi8vMTY5LjI1NC4xNjkuMjU0L2xhdGVzdC9tZXRhLWRhdGEvcGxhY2VtZW50L2F2YWlsYWJpbGl0eS16b25lID4+IC92YXIvd3d3L2h0bWwvaW5kZXguaHRtbAplY2hvICc8L2gzPiA8aDM+SW5zdGFuY2UgSWQ6ICcgPj4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1sCmN1cmwgLUggIlgtYXdzLWVjMi1tZXRhZGF0YS10b2tlbjogJFRPS0VOIiBodHRwOi8vMTY5LjI1NC4xNjkuMjU0L2xhdGVzdC9tZXRhLWRhdGEvaW5zdGFuY2UtaWQgPj4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1sCmVjaG8gJzwvaDM+IDxoMz5QdWJsaWMgSVA6ICcgPj4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1sCmN1cmwgLUggIlgtYXdzLWVjMi1tZXRhZGF0YS10b2tlbjogJFRPS0VOIiBodHRwOi8vMTY5LjI1NC4xNjkuMjU0L2xhdGVzdC9tZXRhLWRhdGEvcHVibGljLWlwdjQgPj4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1sCmVjaG8gJzwvaDM+IDxoMz5Mb2NhbCBJUDogJyA+PiAvdmFyL3d3dy9odG1sL2luZGV4Lmh0bWwKY3VybCAtSCAiWC1hd3MtZWMyLW1ldGFkYXRhLXRva2VuOiAkVE9LRU4iIGh0dHA6Ly8xNjkuMjU0LjE2OS4yNTQvbGF0ZXN0L21ldGEtZGF0YS9sb2NhbC1pcHY0ID4+IC92YXIvd3d3L2h0bWwvaW5kZXguaHRtbAplY2hvICc8L2gzPjwvaHRtbD4gJyA+PiAvdmFyL3d3dy9odG1sL2luZGV4Lmh0bWw="
}
}
]
}
Decrypted User Data:
#!/bin/bash
yum update -y
yum install httpd -y
systemctl start httpd
systemctl enable httpd
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
cd /var/www/html
echo '<html><h1>Bootstrap Demo</h1><h3>Availability Zone: ' > /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/availability-zone >> /var/www/html/index.html
echo '</h3> <h3>Instance Id: ' >> /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id >> /var/www/html/index.html
echo '</h3> <h3>Public IP: ' >> /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-ipv4 >> /var/www/html/index.html
echo '</h3> <h3>Local IP: ' >> /var/www/html/index.html
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4 >> /var/www/html/index.html
echo '</h3></html> ' >> /var/www/html/index.html