CodeDeploy with AutoScalingGroups is a bit of a complex mess to get working correctly. Especially with an app that has been working and needs to be updated for more modern functionality
Update the startups scripts with the latest versions from https://github.com/aws-samples/aws-codedeploy-samples/tree/master/load-balancing/elb-v2
I found even the latest scripts there still not working. My instances were starting up then dying shortly afterward. CodeDeploy was failing with the error
LifecycleEvent - ApplicationStart
Script - /deploy/scripts/4_application_start.sh
Script - /deploy/scripts/register_with_elb.sh
[stderr]Running AWS CLI with region:
[stderr][FATAL] Unable to get this instance's ID; cannot continue.
Upon troubleshooting, I found that common_functions.sh has the get_instance_id() function that was running this curl command to get the instance ID
curl -s http://169.254.169.254/latest/meta-data/instance-id
Running that command by itself while an instance was still running returned nothing, which is why it was failing.
It turns out that newer instances use IMDSv2 by default, and it is required (no longer optional). With that configuration, this curl command will fail. In order to fix, this, I replaced the get_instance_id() function with this version:
# Usage: get_instance_id # # Writes to STDOUT the EC2 instance ID for the local instance. Returns non-zero if the local # instance metadata URL is inaccessible. get_instance_id() { TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" -s -f) if [ $? -ne 0 ] || [ -z "$TOKEN" ]; then echo "[FATAL] Failed to obtain IMDSv2 token; cannot continue." >&2 return 1 fi INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id -s -f) if [ $? -ne 0 ] || [ -z "$INSTANCE_ID" ]; then echo "[FATAL] Unable to get this instance's ID; cannot continue." >&2 return 1 fi echo "$INSTANCE_ID" return 0 }
This version uses the IMDSv2 API to get a token and uses that token to get the instance-id
With that code replaced, the application successfully registered with the Target Group and the AutoScaling group works correctly
Alternatively (and for troubleshooting), I was able to make IMDSv2 Optional using the AWS Console, and via CloudFormation with this part of the Launch Template:
Resources: MyLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: my-launch-template LaunchTemplateData: ImageId: ami-1234567890abcdef0 InstanceType: t4g.micro MetadataOptions: HttpTokens: optional