问题
I am attempting to create my own bastion host for a VPC, and created an auto-scaling group with min/max instances of 1. In my launch configurations, I specify the following for the ec2 user data:
#!
INSTANCE_ID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`
aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id eipalloc-my-eip-id --allow-reassociation
The goal of this user data is to immediately associate an Elastic IP address with my newly created EC2 instance - I've read from other StackOverflow posts that this must be explicitly done when using ASGs.
However, after the ASG instance spins up and finishes initializing, I still do not see any Elastic IP in my console output for the instance:
I've confirmed that the user data is indeed being used by the instance:
I tried to look inside the system log to see if there were any error messages during the initialization, but I couldn't see anything at first that would suggest that the associate-address
command failed (inside /var/log/cloud-init-output
).
Edit: Attempt to debug:
However, I then manually associated the Elastic IP with my instance, SSHed, and attempted to run the user data commands above. Interestingly, when I got to the aws ec2 associate-address
portion, I ran into
Unable to locate credentials. You can configure credentials by running "aws configure".
This appears to be at the root of the issue - my AWS profile is not configured. However, I've always been under the impression that a default AWS instance profile is set up for you with access to the AWS CLI when the instance finishes initializing.
Could anyone point me in the direction of why my user data to associate elastic IP addresses might not be executing properly?
回答1:
It looks the instance profile attached to this EC2 instance does not have permission to perform the above task.
Referring to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-policies-ec2-console.html#ex-eip,
Can you make sure your Instance profile has the following action allowed?
ec2:AllocateAddress: To allocate an Elastic IP address.
ec2:ReleaseAddress: To release an Elastic IP address.
ec2:AssociateAddress: To associate an Elastic IP address with an instance or a network interface.
ec2:DescribeNetworkInterfaces and ec2:DescribeInstances: To work with the Associate address screen. The screen displays the available instances or network interfaces to which you can associate an Elastic IP address.
ec2:DisassociateAddress: To disassociate an Elastic IP address from an instance or a network interface.
Sample policy would look like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeAddresses",
"ec2:AllocateAddress",
"ec2:DescribeInstances",
"ec2:AssociateAddress"
],
"Resource": "*"
}
]
}
Hope this helps.
回答2:
Are you running your EC2 instance with the amazon provided AMI?
If so, the profile should be set up indeed.
However, we've noticed the default region is not set in your profile. So when running aws cli
commands, you'll either need to give the region using --region <your region>
or set the AWS_DEFAULT_REGION
environment variable.
We use the following script to provision our servers with an EIP at startup as part of our CloudFormation template:
#!/bin/bash
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
MAXWAIT=3
ALLOC_ID=<your eip allocation id>
AWS_DEFAULT_REGION=<your region>
# Make sure the EIP is free
echo "Checking if EIP with ALLOC_ID[$ALLOC_ID] is free...."
ISFREE=$(aws ec2 describe-addresses --allocation-ids $ALLOC_ID --query Addresses[].InstanceId --output text)
STARTWAIT=$(date +%s)
while [ ! -z "$ISFREE" ]; do
if [ "$(($(date +%s) - $STARTWAIT))" -gt $MAXWAIT ]; then
echo "WARNING: We waited 30 seconds, we're forcing it now."
ISFREE=""
else
echo "Waiting for EIP with ALLOC_ID[$ALLOC_ID] to become free...."
sleep 3
ISFREE=$(aws ec2 describe-addresses --allocation-ids $ALLOC_ID --query Addresses[].InstanceId --output text)
fi
done
# Now we can associate the address
echo Running: aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id $ALLOC_ID --allow-reassociation}
aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id $ALLOC_ID --allow-reassociation}
We've added the part where we check if the EIP is free as this is used inside an autoscaling group and we've noticed sometimes the EIP is still in use even though the old instance is already terminated and the new instance is at the point of running the userdata script.
回答3:
A User Data script must start with #!
to be recognized as a script. For example:
#!
INSTANCE_ID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`
aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id eipalloc-xxx --allow-reassociation
You can view the resulting log in: /var/log/cloud-init-output.log
来源:https://stackoverflow.com/questions/53919530/aws-ec2-user-data-script-to-allocate-elastic-ip