Новый проект переносит свои домены на DNS Azure, для чего требовалось создать возможность управления ими.
Схема получается следующая:
- файлы зон хранятся в Stash;
- GoCD проверяет обновления в Stash, и триггерит билд;
- во время билда — файлы зон заливаются на Azure DNS.
Обновление данных выполняется bash-скриптом с помощью Azure CLI.
Больше про Azure CLI и работу с Azure DNS можно найти в посте Azure: работа с DNS из Azure CLI.
Содержание
Stash репозиторий
Репозиторий выглядит так:
$ tree azure-dns/ azure-dns/ ├── scripts │ └── dns_update.sh ├── zone-backup │ └── domain.ms.txt └── zone-files └── domain.ms.txt
- каталог
zone-files
: содержит файлы зон, которые могут быть отредактированы командой проекта; - каталог
zone-backup
: при каждом билде — скрипт с помощью Azure CLI сохраняет текущие файлы зон сюда; - каталог
scripts
: скрипты 🙂
Файлы зон — это обычные txt-файлы в том виде, как их можно увидеть на BIND-сервере, например:
$ cat zone-files/domain.ms.txt ; Exported zone file from Azure DNS ; Resource Group Name: DNS ; Zone name: domain.ms ; Date and time (UTC): Fri Mar 25 2016 11:42:14 GMT+0000 $TTL 3600 $ORIGIN domain.ms. @ 3600 IN SOA ns1-02.azure-dns.com. msnhst.microsoft.com. ( 2016032514 3600 300 2419200 300 ) @ 3600 IN A 104.40.183.236 @ 3600 IN MX 10 mx.domain.net. @ 172800 IN NS ns1-02.azure-dns.com. 172800 IN NS ns2-02.azure-dns.net. 172800 IN NS ns3-02.azure-dns.org. 172800 IN NS ns4-02.azure-dns.info. www 3600 IN CNAME domain.ms. test 3600 IN CNAME domain.ms.
GoCD билд
В GoCD имеется pipeline:
Который состоит из трех шагов:
- DNSverify: вызывается
azure network dns zone import
с опцией--parse-only
, и в цикле проверяет все файлы зон из каталогаzone-files
; - DNSbackup: использует
azure network dns zone export
для выгрузки все имеющихся на данный момент зон в каталогzone-backup
; - DNSupdate: собственно, обновление данных — с помощью
azure network dns zone import
каждый файл зоны изzone-files
загружается в Azure DNS.
Для авторизации используется пользователь и пароль, которые передаются через Secure variables:
А так выглядит один из шагов билда:
Bash скрипт и Azure CLI
Основная часть всей схемы:
#!/usr/bin/env bash # must be present from CI variables USER=$AZURE_USER PASS=$AZURE_PASS SUB_ID=$SUBSCRIPTION_ID # группа ресурсов RES_GR="DNS" me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")" # reset all options # изврат делать это через массив - но выглядит приятнее declare -A opts opts=([verify]=0 [backup]=0 [import]=0) if [ -z $* ]; then echo "No options found!" exit 1 fi # скрипт принимает три опции, по кол-ву шагов в билде # -v: verify zone-files before import # -b: backup zones before import # -i: import zones to Azure DNS while getopts "vbi" opt; do case $opt in v) opts[verify]=1 ;; b) opts[backup]=1 ;; i) opts[import]=1 ;; *) echo "No reasonable options found!" exit 0 ;; esac done main () { # main() - используется как "инициализатор" Azure CLI # которому первым аргументом передается следующая функция для вызова echo -e "\n[$me] Azure CLI initialization started\n" # go to HOME and save curr path pushd $HOME &> /dev/null # "хак", что бы пропустить установку Azure CLI, если пакет уже установлен if [ $(node -p "require('azure-cli/package.json').version") ]; then echo -e "[$me] Azure CLI already installed, skip.\n" else npm install azure-cli fi export PATH="$PATH":"$HOME/node_modules/azure-cli/bin" # go back to /var/lib/go-agent-2/pipelines/AzureDNSupdate popd if azure login -v -u $USER -p $PASS; then azure account set -v $SUB_ID else exit 1 fi azure config mode arm azure provider register --namespace Microsoft.Network # after initialization - call function specified in first argument $1 } dns_import () { echo -e "\n[$me] Azure DNS zones import started.\n" if [ -d zone-files ];then # create zone names from zone file name for i in $(ls -1 zone-files); do # получаем имя домена из имени файла, вырезая .txt zone=$(echo $i | sed 's/.txt//') # force используется, что бы не спрашивать при перезаписи зоны azure network dns zone import -v -g $RES_GR -n "$zone" -f zone-files/"$zone".txt --force done else echo -e "\nERROR: can not find zone files directory in $(pwd). Exit.\n" ls -l exit 1 fi } dns_verify () { echo -e "\n[$me] Azure DNS zones verify started.\n" if [ -d zone-files ];then # create zone names from zone file name for i in $(ls -1 zone-files); do zone=$(echo $i | sed 's/.txt//') echo -e "[$me] Checking $zone..." if [ -e zone-files/"$zone".txt ]; then # grep "warn" or "error" from Azure CLI output # не нашел адекватного способа получить exit code, грепаем warn или error azure network dns zone import -v -g $RES_GR -n "$zone" --parse-only -f zone-files/"$zone".txt | grep "warn\|error" && {echo -e "\nERROR during parsing zone file $zone.txt. Exit." && exit 1} || echo "$zone check passed" else echo -e "\nERROR: can not find zone-files/"$zone".txt file. Exit.\n" exit 1 fi done echo -e "\n[$me] All zone files checked successfully.\n" else echo -e "\nERROR: can not find zone files directory in $(pwd). Exit.\n" ls -l exit 1 fi } dns_backup() { echo -e "\n[$me] Azure DNS zones backup started.\n" # получаем список всех доменов, которые сейчас есть на NS zones=$(azure network dns zone list -g $RES_GR --json | grep "name" | cut -d":" -f 2 | sed 's/"//g' | sed 's/,//' | tr -d " ") if [ -z $zones ]; then echo -e "WARNING: zones files not found. Skip.\n" exit 0 fi for zone in $zones; do echo -e "Zone found: $zone.\n" # и выгружаем их в zone-backup if azure network dns zone export -q -v -g $RES_GR -n "$zone" -f zone-backup/"$zone".txt; then echo -e "\n$zone exported to zone-backup/"$zone".txt\n" else echo -e "\nERROR during $zone export. Exit.\n" exit 1 fi done git add -A git commit -m "$(date +%Y%m%d) zones backup" git push origin } # проверяем полученные аргументы, и запускаем те, для которых значение == 1 # первой вызывается main(), которой первым аргументом передается следующая функция # $act in ${!opts[@]} == "verify" or "backup" or "import" for act in "${!opts[@]}"; do # i.e.: if ${oprts[verify]} == 1 if [ "${opts[$act]}" == 1 ]; then # main() with first argument like "dns_verify()" main dns_$act fi done
Сами билды выглядят так:
Ссылки по теме
Manage DNS records and record sets using CLI
Create DNS record sets and records using CLI
Import and export a DNS zone file
How to manage DNS Zones using CLI