i-cf27aa8d instance has 54.72.151.117 Public IP address assigned. This IP is taken from general AWS pool. If you stop and start the instance from AWS EC2 console, a different Public IP address will be selected.
Now, imagine instance launch is controlled by an auto-scaling policy. Following explained behavior, a new random Public IP address will be attached each time a new (or replacement) instance is launched attending auto-scaling group needs.
In the context of need a predictable Public IP addresses, general behavior doesn't fit our needs. When instance is launched manually is easy to resolve: you can attach an IP address from Elastic IP pool through AWS EC2 console, for example. But this could be difficult in an auto-scaling context.
A way to resolve this situation could be using ipassign script. Let verify this with an example!
Imagine previous instance (i-cf27aa8d). To use ipassign script we need to:
- Verify AWS CLI and ec2-utils packages are installed. By default, Amazon Linux instances arrive with them pre-installed. For Ubuntu distributions, probably you'll need to install them manually using apt-get commands:
- Login to the instance as root username. If role instance is not assigned, you need to configure AWS CLI with an IAM user allowed to execute describe-addresses, associate-address and disassociate-address EC2 actions.
- Install ipassign script. Just follow next instructions:
- Download ipassign script and copy inside your instance in "/etc/init.d" directory
- Modify script permissions: chmod 755 /etc/init.d/ipassign
- Add script to instance startup process: chkconfig ipassign on
- Review ipassign configuration. At the beginning of the script, there are two parameters you need to review and ensure are correctly configured:
- REGION: Defines the AWS region. Value must be the same used by instance. By default is set to eu-west-1 (Ireland) region.
- IPLOGFILE: Defines log file. By default is set to "/var/log/ipassign.log" and my suggestion is maintain this value.
Done! If we restart the instance, during startup process will try to attach a free Public IP address from Elastic IP pool. Imagine we have three IP address associated to our account, all of them are currently in use:
In this context, instance can't attach any Public IP. Script is designed to avoid changes if an IP from Elastic IP pool can't be attached. Next time we login to the instance, if we review log file will see an error message registered:
Just go to AWS EC2 web console and request a new Elastic IP:
Now (with a free Public IP in Elastic IP pool), if we restart instance again, we'll see ipassign script can find one free IP address in Elastic IP pool and attach it to the instance:
Login to the instance (now, using the new Public IP attached) and checking log file, next information is displayed:
Finally, in instance general information panel, we can review how the instance has a new Public IP address (54.76.166.221) from the Elastic IP pool correctly assigned:
By default, 5 Elastic IP addresses can be associated to an AWS account. But this limit could be increased, if needed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# chkconfig: 2345 99 10 | |
# description: Set Public IP from ElasticIP pool during instance startup | |
# processname: ipassign | |
# Provides: ipassign | |
# Required-Start: | |
# Required-Stop: | |
# Default-Start: 2 3 4 5 | |
# Default-Stop: | |
# Short-Description: Set Public IP from ElasticIP pool during instance startup | |
# | |
# | |
# Developed by: Javier Sianes - jsianes@gmail.com | |
# | |
OUTPUT="text" | |
REGION="eu-west-1" | |
IPLOGFILE="/var/log/ipassign.log" | |
export PATH=/usr/share/pear:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin | |
timestamp() { | |
TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%S.000Z"` | |
} | |
usage() { | |
echo "$0 {start|stop|status}" | |
exit 255 | |
} | |
write_log() { | |
timestamp | |
echo "${TIMESTAMP} - ${LOG}" >> ${IPLOGFILE} | |
} | |
valid_ip() { | |
RX='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])' | |
if [[ ${EC2PUBLICIP} =~ ^${RX}\.${RX}\.${RX}\.${RX}$ ]] | |
then | |
VALIDIP=1 | |
else | |
VALIDIP=0 | |
fi | |
} | |
check_ec2metadata() { | |
ec2-metadata >/dev/null 2>&1 | |
if [ $? -eq 0 ] | |
then | |
# Amazon Linux ec2-metadata command found | |
EC2INSTANCE=`ec2-metadata -i | awk '{ print $NF; }'` | |
EC2PUBLICIP=`ec2-metadata -v | awk '{ print $NF; }'` | |
else | |
# Checking ec2metadata command | |
ec2metadata >/dev/null 2>&1 | |
if [ $? -eq 0 ] | |
then | |
# ec2metadata command found | |
EC2INSTANCE=`ec2metadata --instance-id` | |
EC2PUBLICIP=`ec2metadata --public-ipv4` | |
else | |
# No ec2metadata/ec2-metadata command found. Trying to obtain using curl requests directly | |
IP_AVAILABLE=`curl --connect-timeout 5 -i http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null | grep "200 OK" | wc -l` | |
IS_AVAILABLE=`curl --connect-timeout 5 -i http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null | grep "200 OK" | wc -l` | |
(( INFO=${IP_AVAILABLE}+${IS_AVAILABLE} )) | |
if [ ${INFO} -eq 2 ] | |
then | |
EC2INSTANCE=`curl --connect-timeout 5 http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null` | |
EC2PUBLICIP=`curl --connect-timeout 5 http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null` | |
else | |
# ec2metadata/ec2-metadata command not found and unable to obtain metadata info using curl | |
LOG="ERROR: Unable to obtain metadata information using ec2metadata/ec2-metadata command or curl requests"; write_log | |
exit 127 | |
fi | |
fi | |
fi | |
} | |
check_awscli() { | |
aws ec2 describe-addresses >/dev/null 2>&1 | |
if [ $? -ne 0 ] | |
then | |
# Incorrect instance role or invalid AWS CLI configuration | |
LOG="ERROR: AWS CLI command not available. Check instance role or AWS CLI installation/configuration"; write_log | |
exit 128 | |
fi | |
} | |
start() { | |
check_ec2metadata | |
# Check Public IP | |
valid_ip | |
if [ ${VALIDIP} -eq 0 ] | |
then | |
# No Public IP available. So, AWS CLI unavailable | |
LOG="ERROR: There is no Public IP address attached to ${EC2INSTANCE} instance. Unable to use AWS CLI."; write_log | |
exit 3 | |
fi | |
# Check if AWS CLI is available | |
check_awscli | |
# Check if instance has a public IP from Elastic pool assigned | |
PUBLICIPASSIGNED=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep ${EC2INSTANCE} | wc -l` | |
if [ ${PUBLICIPASSIGNED} -gt 0 ] | |
then | |
# Instance has (at least) one Pulic IP associated from Elastic pool | |
IP=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep ${EC2INSTANCE} | head -1 | awk '{ print $NF; }'` | |
LOG="Instance ${EC2INSTANCE} has (at least) one Public IP address from Elastic pool in ${REGION} region (${IP})"; write_log | |
exit 4 | |
else | |
# Get IP address from Elastic pool | |
IP=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep -v 'i-' | head -1 | awk '{ print $NF; }'` | |
if [ "${IP}" = "" ] | |
then | |
# Public IP on Elastic pool unavailable | |
LOG="ERROR: Free Public IP inside Elastic pool in ${REGION} region unavailable"; write_log | |
exit 5 | |
else | |
# Attach Public IP from Elastic pool | |
BOOL=0 | |
aws ec2 associate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --public-ip ${IP} >/dev/null 2>&1 | |
EXITCODE=$? | |
if [ ${EXITCODE} -eq 0 ] | |
then | |
LOG="${IP} Public IP from Elastic pool assigned to ${EC2INSTANCE} instance"; write_log | |
else | |
LOG="ERROR: (${EXITCODE}) Unable to attach ${IP} Public IP from Elastic pool to ${EC2INSTANCE} instance"; write_log | |
BOOL=1 | |
fi | |
if [ ${BOOL} -eq 0 ] | |
then | |
# Detaching default Public IP | |
aws ec2 disassociate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --public-ip ${EC2PUBLICIP} >/dev/null 2>&1 | |
EXITCODE=$? | |
if [ ${EXITCODE} -eq 0 ] || [ ${EXITCODE} -eq 255 ] | |
then | |
LOG="Default public IP ${EC2PUBLICIP} outside Elastic pool detached from ${EC2INSTANCE} instance"; write_log | |
else | |
LOG="ERROR: (${EXITCODE}) Unable to detach default public IP ${EC2PUBLICIP} from ${EC2INSTANCE} instance"; write_log | |
BOOL=2 | |
fi | |
fi | |
exit ${BOOL} | |
fi | |
fi | |
} | |
stop() { | |
exit 6 | |
} | |
status() { | |
check_ec2metadata | |
valid_ip | |
if [ ${VALIDIP} -eq 0 ] | |
then | |
echo "No Public IP address attached to ${EC2INSTANCE} instance." | |
exit 1 | |
fi | |
check_awscli | |
IPPRESENTINPOOL=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep "${EC2INSTANCE}" | grep ${EC2PUBLICIP} | wc -l` | |
if [ ${IPPRESENTINPOOL} -eq 1 ] | |
then | |
echo "Public IP ${EC2PUBLICIP} attached to ${EC2INSTANCE} instance in ${REGION} region belongs to ElasticIP pool" | |
exit 0 | |
else | |
echo "Public IP ${EC2PUBLICIP} attached to ${EC2INSTANCE} instance in ${REGION} region is a generic public IP NOT present in ElasticIP pool" | |
exit 2 | |
fi | |
} | |
case "$1" in | |
start) | |
start | |
;; | |
stop) | |
stop | |
;; | |
status) | |
status | |
;; | |
*) | |
usage | |
;; | |
esac |
5 comentarios:
Great post :)
Thanks for providing this informative information you may also refer
http://www.s4techno.com/blog/2016/07/11/awk-scripting/
Thanks for providing keep update AWS Online Training
Thank you for sharing this post.
AWS Training in Chennai
AWS Training Institute in Chennai
AWS Training Center in Chennai
Best AWS Training in Chennai
AWS Training Courses in Chennai
This is really very nice post you shared, i like the post, thanks for sharing..
full stack developer course with placement
Publicar un comentario