Skip to content

Instantly share code, notes, and snippets.

@chhibber
Created January 14, 2014 06:35
Show Gist options
  • Save chhibber/8414078 to your computer and use it in GitHub Desktop.
Save chhibber/8414078 to your computer and use it in GitHub Desktop.
AWS - NAT Bootstrap Example
#!/bin/bash -
#===============================================================================
# vim: softtabstop=4 shiftwidth=4 expandtab fenc=utf-8 spell spelllang=en
#===============================================================================
set -x
SALT_BOOTSTRAP_SCRIPT="salt-bootstrap.sh"
SALT_BOOTSTRAP_DOWNLOAD="http://bootstrap.saltstack.org"
exec 2>&1 > /tmp/awsbootstrap.log
# ===== FUNCTION ================================================================
# NAME: log
# DESCRIPTION:
# ===============================================================================
log() {
echo `date` : "$@"
}
# ===== FUNCTION ================================================================
# NAME: jsonvalue
# DESCRIPTION: Extracts the key value from json - magic. UGLY
# ===============================================================================
function jsonvalue {
temp=`echo $JSON | \
sed 's/\\\\\//\//g' | \
sed 's/[{}]//g' | \
awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | \
sed 's/\"\:\"/\|/g' | \
sed 's/[\,]/ /g' | \
sed 's/\"//g' | grep -w $PROP | \
awk '{print $2}'`
echo ${temp##*|}
}
# ===== FUNCTION ================================================================
# NAME: __download_salt_bootstrap_script
# DESCRIPTION: Retrieves a URL and writes it to a given path
# ===============================================================================
__download_salt_bootstrap_script() {
curl -L --insecure -o ${SALT_BOOTSTRAP_SCRIPT} ${SALT_BOOTSTRAP_DOWNLOAD} >/dev/null 2>&1 ||
wget --no-check-certificate -O ${SALT_BOOTSTRAP_SCRIPT} ${SALT_BOOTSTRAP_DOWNLOAD} >/dev/null 2>&1 ||
fetch -q -o ${SALT_BOOTSTRAP_SCRIPT} "$SALT_BOOTSTRAP_DOWNLOAD" >/dev/null 2>&1
}
log "#################################################################################################"
log "# Starting System Bootstrap #"
log "#################################################################################################"
#
# Setup variables needed for script
#
export EC2_HOME=/opt/aws/apitools/ec2
export JAVA_HOME=/usr/lib/jvm/jre
export INSTANCE_ID=`/opt/aws/bin/ec2-metadata -i | awk '{print $2}'`
export PLACEMENT=`/opt/aws/bin/ec2-metadata | grep -w ^placement | awk '{ print $2 }'`
export AVAILABILITY_ZONE=`/opt/aws/bin/ec2-metadata -z | awk '{print $2}'`
export AWS_DEFAULT_REGION=${AVAILABILITY_ZONE%?}
export AWS_DEFAULT_REGION=${AVAILABILITY_ZONE%?}
export SERVER_ROLE=`aws ec2 describe-tags --filters "Name=resource-id,Values=${INSTANCE_ID}" --output=text | \
grep -w Role | awk '{print $3}'`
export SERVER_ENV=`aws ec2 describe-tags --filters "Name=resource-id,Values=${INSTANCE_ID}" --output=text | \
grep -w Env | awk '{print $3}'`
export SALTVERSION=`aws ec2 describe-tags --filters "Name=resource-id,Values=${INSTANCE_ID}" --output=text | \
grep -w Saltversion | awk '{print $3}'`
export ETH0_MAC=`/sbin/ifconfig | /bin/grep eth0 | \
awk '{print tolower($5)}' | grep '^[0-9a-f]\{2\}\(:[0-9a-f]\{2\}\)\{5\}$'`
export VPC_CIDR_URI="http://169.254.169.254/latest/meta-data/network/interfaces/macs/${ETH0_MAC}/vpc-ipv4-cidr-block"
export VPC_CIDR_RANGE=`curl --retry 3 --retry-delay 0 --silent --fail ${VPC_CIDR_URI}`
export DFG=`ip route | grep default | awk '{print $3}' | head -n1`
#
# Disable source destination check on the instance
#
/usr/bin/aws ec2 modify-instance-attribute --instance-id $INSTANCE_ID --source-dest-check '{ "Value": false }'
#
# Enable forwarding
#
/bin/echo 1 > /proc/sys/net/ipv4/ip_forward
#
# Determine which ENI we need based on region
#
[[ $AVAILABILITY_ZONE == "us-west-2a" ]] && NATNIC='NATANIC'
[[ $AVAILABILITY_ZONE == "us-west-2b" ]] && NATNIC='NATBNIC'
[[ $AVAILABILITY_ZONE == "us-west-2c" ]] && NATNIC='NATCNIC'
[[ $AVAILABILITY_ZONE == "us-east-1b" ]] && NATNIC='NATANIC'
[[ $AVAILABILITY_ZONE == "us-east-1c" ]] && NATNIC='NATBNIC'
[[ $AVAILABILITY_ZONE == "us-east-1d" ]] && NATNIC='NATCNIC'
#
# Determine Network Interface ID
#
JSON=`/usr/bin/aws ec2 describe-network-interfaces \
--filter Name=availability-zone,Values=$AVAILABILITY_ZONE \
--filter Name=status,Values=available \
--filter Name=tag-value,Values=$NATNIC`
PROP="NetworkInterfaceId"
ENI_ID=`jsonvalue`
echo $ENI_ID
#
# Disable Source Desintation Check on the Network Interface
#
/usr/bin/aws ec2 modify-network-interface-attribute --network-interface-id $ENI_ID --source-dest-check '{ "Value": false }'
#
# Attach the network interface to the instance
#
/usr/bin/aws ec2 attach-network-interface --network-interface-id $ENI_ID --instance-id $INSTANCE_ID --device-index 1
sleep 5
#
# Using ec2 interface tools, scan for a new interface
#
/sbin/ec2ifscan
sleep 5
#
# Bring the new interface up
#
/sbin/ec2ifup eth1
sleep 2
#
# Start NATing out the ENI with the static IP address and delete
# the original entry
#
/sbin/iptables -t nat -A POSTROUTING -o eth1 -s ${VPC_CIDR_RANGE} -j MASQUERADE
sleep 2
/sbin/iptables -t nat -D POSTROUTING -o eth0 -s ${VPC_CIDR_RANGE} -j MASQUERADE
#
# Delete the default route that tells traffic to go out ETH0
# The AWS tools put an default entry via eth1 with a higher metric.
# e.g. default via 10.204.4.1 dev eth1 metric 10001
#
/sbin/ip route del default via ${DFG} dev eth0
/sbin/ip route flush cache
log "#################################################################################################"
log "# Starting salt bootstrap #"
log "#################################################################################################"
#
# Download Salt bootstrap file
#
sleep 5
# Removed as we are not using DNS on the instances anymore. Just another thing to manage.
# Download Salt Bootstrap File
# echo "Downloading Salt Bootstrap file and setting permissions"
__download_salt_bootstrap_script
chmod 550 ${SALT_BOOTSTRAP_SCRIPT}
#
# Set the hostname and Name tag. We want to set the hostname before the install and starts
# the salt-minion. This way the key name stays consistent on the salt master.
# ie. Instead of getting a host named ip_10_20_125_12 we get us-east1-production-www-c123433
#
AWS_NAME="${PLACEMENT}-${SERVER_ENV}-${SERVER_ROLE}-${INSTANCE_ID}"
hostname $AWS_NAME
#/usr/bin/aws ec2 create-tags --resources ${INSTANCE_ID} --tags Key=Name,Value=${AWS_NAME}
#
# Enable the EPEL repo that is already installed on AMI image
#
yum-config-manager --enable epel
yum -y install git
mkdir -p /etc/salt
# Install all things salt!
/salt-bootstrap.sh -P git v${SALTVERSION}
#
#
# Determine what salt server to point to. Need to make this smarter...
#
[[ "$SERVER_ENV" != "production" ]] && SALTMASTER="${AWS_DEFAULT_REGION}-development-salt.FOOBAR.com"
[[ "$SERVER_ENV" == "production" ]] && SALTMASTER="${AWS_DEFAULT_REGION}-production-salt.FOOBAR.com"
#SALTMASTER="${AWS_DEFAULT_REGION}-${SERVER_ENV}-salt.FOOBAR.com"
echo "master: ${SALTMASTER}" > /etc/salt/minion
echo '' >> /etc/salt/minion
echo 'grains:' >> /etc/salt/minion
echo ' roles:' >> /etc/salt/minion
echo " - ${SERVER_ROLE}" >> /etc/salt/minion
echo " environment: ${SERVER_ENV}" >> /etc/salt/minion
echo '' >> /etc/salt/minion
echo 'log_level: info' >> /etc/salt/minion
#
# Start the salt-minion
#
/usr/bin/salt-minion -d -c /etc/salt
# Wait for salt to start
sleep 5
#
# Ensure the salt-minion is connected to salt-master
#
TIMEOUT=90
COUNT=0
while [ ! -f /etc/salt/pki/minion/minion_master.pub ]; do
echo "Waiting for salt to register with master."
if [ "$COUNT" -ge "$TIMEOUT" ]; then
echo "minion_master.pub not detected by timeout"
exit 1
fi
sleep 5
COUNT=$((COUNT+5))
done
sleep 5
echo "Install base requirements"
salt-call state.sls baseRequirements
#
# Send a notification to hip chat
#
curl -d \
"room_id=Development+Notifications&from=AWS+Bootstrap&\
message=\
AMI+Info:+${INSTANCE_ID}+\
Environment:+${SERVER_ENV}+\
Role:+${SERVER_ROLE}+\
+::+Calling+salt.highsate\
&color=green"\
https://api.hipchat.com/v1/rooms/message?auth_token=YOURTOKEN&format=json
echo "Calling salt.highstate"
salt-call state.highstate
log "#################################################################################################"
log "# Done System Bootstrap #"
log "#################################################################################################"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment