среда, 1 марта 2017 г.

AWS. Создать Route 53 record set and Health Check при старте EC2 в ASG и чистка при удалении

Задача - при старте новой EC2 в ASG мы создаем запись в Route53, создаем Health Check и связываем их. При удалении EC2 - чистим за собой.
Скрипт при старте:

cp /tmp/r53 /etc/init.d
chmod 0755 /etc/init.d/r53
touch /var/lock/subsys/r53
chkconfig --add r53
chkconfig r53 on
/etc/init.d/r53 start

Это создает нам структуру для старт-стопа-терминации. Будут созданы линки согласно правилам в файле r53:

#!/bin/sh
#
# chkconfig: - 80 20
# description: R53 manupalations
#
### BEGIN INIT INFO
# Provides:       r53
# Required-Start:
# Required-Stop:  $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: S 0 1 6
# Description: create Route53 HealthCheck and Record Set
### END INIT INFO

FUNCTIONS_EXIST=false
if [ -f /etc/rc.d/init.d/functions ] ; then
     . /etc/rc.d/init.d/functions
     FUNCTIONS_EXIST=true
fi
if [ -f /etc/init.d/functions ] ; then
     . /etc/init.d/functions
     FUNCTIONS_EXIST=true
fi

if ! $FUNCTIONS_EXIST ; then

failure() {
  return 0
}
success() {
  return 0
}
fi

# define vars
RETVAL=0
HOME=/usr/local/tmp
LOCK_FILE=/var/lock/subsys/r53

# See how we were called.
case "$1" in
  start)
echo -n "Calling the R53 create HealthCheck and RecordSet"
 ${HOME}/r53-create.sh
echo
;;

  stop)
echo -n "Calling the R53 delete HealthCheck and RecordSet"
 ${HOME}/r53-delete.sh
 rm ${LOCK_FILE}
 RETVAL=0
 echo -n "Finished R53 delete HC and RS"
echo
;;

  *)
echo "Usage: r53 {start|stop}"
RETVAL=2
esac

exit 0

chkconfig создаст линки в /etc/rc0.d для чистки записей и в /etc/rc3.d для создания записей.

Для создания Health Check AWS предлагает также и способ CLI:
aws route53 create-health-check --caller-reference CallerId --health-check-config bath-file

Для создания Record  Set:
aws route53 change-resource-record-sets --hosted-zone-id ZoneId --change-batch batch-file

Когда я поднимаю EC2 в составе ASG, по правилам задачи я закрепляю также EIP для EC2.
Мне нужно собрать все данные для batch-files и только тогда я смогу сделать то что требуется.

Общий скрипт для создания записей а также подготовки файлов для последующего удаления выглядит так:

r53-create.sh

#!/bin/sh
HOME=/usr/local/tmp
EIP=`curl --silent http://169.254.169.254/latest/meta-data/public-ipv4`
HNAME=`curl --silent http://169.254.169.254/latest/meta-data/public-hostname`
#health check parameters file
HCFILE=${HOME}/hc-create.json
#record set paameteres file
RSFILE=${HOME}/rs-create.json
RSFILEDEL=${HOME}/rs-delete.json
#HealthCheckIdFIle
HCIDFILE=${HOME}/HealthCheckId
#caller identifier. Unique ID of request
#CALLER=`date +%s`
CALLER=${EIP}
# hosted zone
HOSTEDZONE="XXXXXXXXXXX"

#insert current EIP
sed -i -re 's/("IPAddress": )(".*")/\1"'"${EIP}"'"/' ${HCFILE}
aws route53 create-health-check --caller-reference ${CALLER} --health-check-config file://${HCFILE} |jq ".HealthCheck.Id"|cut -d "\"" -f 2 >${HCIDFILE}
sleep 10
#We have Health Check. Creating R53 record set with Health Check
HCID=`cat ${HCIDFILE}`
sed -i -re 's/("HealthCheckId": )(".*")/\1"'"${HCID}"'"/' ${RSFILE}
sed -i -re 's/("Value": )(".*")/\1"'"${EIP}"'"/' ${RSFILE}
sed -i -re 's/("SetIdentifier": )(".*")/\1"'"${EIP}"'"/' ${RSFILE}

#prepare batch file for deleteing on terminate EC2
sed -i -re 's/("HealthCheckId": )(".*")/\1"'"${HCID}"'"/' ${RSFILEDEL}
sed -i -re 's/("Value": )(".*")/\1"'"${EIP}"'"/' ${RSFILEDEL}
sed -i -re 's/("SetIdentifier": )(".*")/\1"'"${EIP}"'"/' ${RSFILEDEL}

aws route53 change-resource-record-sets --hosted-zone-id ${HOSTEDZONE} --change-batch file://${RSFILE} 2>&1 >${HOME}/r53-create.log


Статические переменные как то HOSTEDZONEID нужно взять как константу.
Теперь batch-files.

hc-create.json: (файлик для создания Health Check):
{
  "IPAddress": "",
  "Port": 1935,
  "Type": "TCP",
  "RequestInterval": 30,
  "FailureThreshold": 3
}

В поле IPAddress скрипт вставит актуальный EIP нашей EC2.

rs-create.json:
{
  "Comment": "Script update ",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "MYNAME.DOMAIN.COM",
        "Type": "A",
        "SetIdentifier": "",
        "Weight": 1,
        "TTL": 60,
        "ResourceRecords": [
          {
            "Value": ""
          }
        ],
        "HealthCheckId": ""
      }
    }
  ]
}

MYNAME.DOMAIN.COM - здесь нужно присать руками запись которую мы создаём (имя). Это константа для моей задачи, ведь я создаю Round Robin Weighted записи.
HealhCheckId, Value, SetIdentifier - их значения будут изменены скриптов на актуальные данные.

rs-delete.json:
{
  "Comment": "Script update ",
  "Changes": [
    {
      "Action": "DELETE",
      "ResourceRecordSet": {
        "Name": "MYNAME.DOMAIN.COM",
        "Type": "A",
        "SetIdentifier": "",
        "Weight": 1,
        "TTL": 60,
        "ResourceRecords": [
          {
            "Value": ""
          }
        ],
        "HealthCheckId": ""
      }
    }
  ]
}

Нужные значения добавит срипт.

и остался срипт для зачистки:

r53-delete.sh
echo -n "R53-delete: Start r53-delete.sh"
HOME="/usr/local/tmp"
#record set pameteres file
RSFILE="$HOME/rs-delete.json"
# hosted zone for Public 
HOSTEDZONE="XXXXXXXXX"
HCIDFILE=${HOME}/HealthCheckId
HCID=`cat ${HCIDFILE}`
aws route53 change-resource-record-sets --hosted-zone-id ${HOSTEDZONE} --change-batch file://${RSFILE}
aws route53 delete-health-check --health-check-id ${HCID} 
echo -n "R53-delete: All done"

Если что-то идет не так (не удаляются записи), смотрите по состоянию Terminated Get System Log. В нем должны быть выводы команд echo r53-delete.sh. Там можно увидеть что не так.
Так же смотрите при старте EC2 на файлы rs-delete.json, это заранее подготовленый batch, который будет использован при удалении. Возможно, что он создан не корректно.

Основная проблема, с которой сталкивался при не удалении записей - это не уникальный CollerId. Я специально кстати его сделал не уникальным (он у меня равен EIP). Что бы не создавать такой же запрос в Route53. Ошибка есть ошибка, и ее нужно исправить. 


Комментариев нет: