Jenkins: восстановление Aurora Cluster и простого RDS со снапшота

Описание

Иногда, но требуется поднимать кластера RDS со снапшотов для тестов или восстановления данных (когда что-то пошло не так). Раньше все делалось руками, быстро наклацал в AWS Console и кластер восстановился или скопировал заготовленные aws-cli команды, использовал их в терминале и все готово. Как не крути, но хочется все манипуляции как то автоматизировать. Давно всю автоматизацию описываем в Jenkins, по этому попробуем очень просто и доступно организовать восстановление и удаления Aurora RDS Сluster c снапшотов.

Идея состоит в том, чтоб облегчить работу команде, использовать для восстановления Aurora Clusters или RDS Instance, передавая нужные нам параметры через Jenkins Job.

Что же должно уметь задание:

  • принимать параметры для восстановления (sg, vpc, parametergroup, etc).
  • возможность выбирать дату снапшотов.
  • восстанавливать кластера аврора и обычные rds.
  • удалять кластер и обычные rds.

В голове крутиться несколько вариантов, но я решил выбрать тот который посчитал оптимальным:

  1. Создадим директорию в Jenkins c именем RDS_RESTORE, в ней под директории с именами команд (web, game, etc).
  2. В директориях команд разместить задание для восстановления только их ресурсов, а в дескрипшин добавим таблицу с описанием параметров RDS. Таким образом таблица не будет загромождать интерфейс и по ней легко ориентироваться, выбирать нужные параметры.
  3. Что касается самого крипта, используем конструкцию switch case где опишем нужные action (восстановить, удалить) и одну функцию в которой будем выводить нужный нам snapshot. Все остальные параметры передаем через Jenkins Parameters в UI. В основном используем модуль sh и aws-cli под капотом, все добро будем выполнять в docker контейнере на master ноде.

Что понадобиться:

  • Jenkins groovy script.
  • docker images c aws-cli.
  • список кластеров Aurora и RDS.
  • AWS iAM пользователь c полным доступом к RDS.

Создание Jenkins Job

Создаем директорию RDS_Restoreдалее в ней добавим 4 под директории для команд, в конечном результате выйдет следующее:

Тесты и задание будем проводить в директории Game, а после настройки и написания скрипта просто копируем его и изменять значения параметров.

В директории Game выбираем New Item, создаем задание с именем RDS_Gaming_Restore_from_Snapshot и типом Pipeline, далее добавляем параметры:

  • AWS_REGION (choose parameter): регион в котором находятся RDS или кластера аврора, по умолчанию установим us-east-2.
  • CHOSE_ACTION (choose parameter):  действие, которое ходим выполнить.
    • restore-aurora-cluster: восстановит кластер аврора.
    • delete-restored-aurora-cluster: удалит кластер аврора.
    • restore-rds-instance: восстановить RDS инстанс.
    • delete-restored-rds-instance: удалить RDS инстанс.
  • RDS_TO_DEL (choose parameter): список восстановленных кластеров или RDS на удаление. Их будем обозначать добавлением префикса restored. По умолчанию выставлено значение none.
  • RDS_TO_RESTORE (choose parameter):  список аврора кластеров или RDS которые доступны для восстановления. Сюда же добавим html таблицу с параметрами RDS, подробнее таблицу можно будет скачать здесь или воспользоваться ресурсом https://www.w3schools.com/html/html_tables.asp для создания нужной Вам таблицы.
  • RESTORE_DATE (string parameter):  название говорит само за себя, будем передавать дату снапшота в формате 2021-12-10.
  • RDS_ENGINE(choose parameter):
    • aurora-postgresql
    • aurora-mysql
    • mysql
    • postgres
  • RDS_ENGINE_VERSION (choose parameter) версии движков баз данных.
  • RDS_VPC_SG_ID (string parameter): id cекюрити группы, которая будет закреплена.
  • RDS_SUBNET_GROUP_NAME (string parameter): сабнет группа.
  • RDS_PARAMETER_GROUP_NAME (string parameter): кастомная или дефолтная параметр группа, лучше всего создавать свою, тогда в ней можно будет вносить изменения в настройках баз.
  • RDS_INSTANCE_TYPE (string parameter):тип инстанса, здесь добавим типы, которые используют текущие сервера.
  • AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY (password paramater): по классике, данные пользователя для доступа в AWS с правами создание и удаление RDS.

В конечном результате после добавление всех параметров имеем следующую картину: 

Далее переходим к написанию скрипта.

Создание Jenkins groovy

Весь скрипт можно скачать здесь. Описание скрипта разделим на две части, в первой опишем и проверим восстановление RDS а во второй удаление, приступаем.

Восстановление

Все мануальные или финальные идут без префикса rds:, а те которые создавались автоматически начинаются с rds:, пример:

$ aws rds describe-db-cluster-snapshots --query 'DBClusterSnapshots[].DBClusterSnapshotIdentifier[]'
....
"*****-dev-*****-*****-instance-1-final-snapshot", # manual snap 
"rds:aurora-backend-dev-2021-12-17-05-17", # auto snap
.....

Создадим функцию, которая будет выводить нужные снапшоты, назовем ee rdsSnapshot. В ней будет выполняться две команды, которые на основе переданных параметров будут выводить необходимое имя снапшота за нужную дату:

def rdsSnapshot(){ 
 // sort and filter rds snapshot for last day
 aurora_snap = sh (returnStdout: true, script:"aws rds describe-db-cluster-snapshots --query 'DBClusterSnapshots[].DBClusterSnapshotIdentifier[]' | grep ${RDS_TO_RESTORE} | grep ${RESTORE_DATE} |cut -d '\"' -f2 | tr -d '\n'")
 rds_snap = sh (returnStdout: true, script:"aws rds describe-db-snapshots --query 'DBSnapshots[].DBSnapshotIdentifier[]' | grep ${RDS_TO_RESTORE} | grep ${RESTORE_DATE} | cut -d '\"' -f2 | tr -d '\n'")
}

где:

  • aurora_snap – здесь выводим список доступных снапшотов, фильтруем их по имени аврора кластеров ${RDS_TO_RESTORE}, далее по дате ${RESTORE_DATE}, удаляем символ ” cut -d ‘\”‘ -f2  , в конце убираем все пробелы со строки tr -d ‘\n’, пример:
$ aws rds describe-db-cluster-snapshots --query 'DBClusterSnapshots[].DBClusterSnapshotIdentifier[]' | grep rds:aurora-gaming-stage-psql-cluster| grep 2021-12-10 | cut -d '"' -f2 | tr -d '\n'
rds:aurora-gaming-stage-psql-cluster-2021-12-10-04-11%
  • rds_napто же самое что и с aurora_snap, но здесь выводиться список RDS снапшотов, пример:
aws rds describe-db-snapshots --query 'DBSnapshots[].DBSnapshotIdentifier[]' | grep psql*** | grep 2021-12-10 | cut -d '"' -f2 | tr -d '\n'
rds:psql****-qa-*******-2021-12-10-05-24%

Для определения action добавим конструкцию switch case, с действиями про которые говорили выше:

node('master'){

    docker.image('amazon/aws-cli:2.2.33').inside("-v /var/run/docker.sock:/var/run/docker.sock -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} -e AWS_DEFAULT_REGION=${AWS_REGION} --entrypoint=''") {
        
        rdsSnapshot()
        
        switch("${CHOSE_ACTION}"){
            
            case "restore-aurora-cluster":
                stage("RDS: Restore Aurora Cluster") {
                    echo "===================================  AWS RDS: Restore Aurora Cluster  ========================================"
                    sh "aws rds restore-db-cluster-from-snapshot \
                            --snapshot-identifier ${aurora_snap} \
                            --engine ${RDS_ENGINE} \
                            --engine-version ${RDS_ENGINE_VERSION} \
                            --vpc-security-group-ids ${RDS_VPC_SG_ID} \
                            --db-cluster-identifier restored-${RDS_TO_RESTORE} \
                            --db-subnet-group-name ${RDS_SUBNET_GROUP_NAME} \
                            --db-cluster-parameter-group-name ${RDS_PARAMETER_GROUP_NAME}"

                    echo "==================================  AWS RDS: Create Aurora instance-1  ======================================="
                    sh "aws rds create-db-instance \
                            --engine ${RDS_ENGINE} \
                            --publicly-accessible \
                            --db-cluster-identifier restored-${RDS_TO_RESTORE} \
                            --db-instance-identifier restored-${RDS_TO_RESTORE}-instance-1 \
                            --db-instance-class ${RDS_INSTANCE_TYPE}"

                    echo "=================================  AWS RDS: Create Aurora instance-2  ======================================="
                    sh "aws rds create-db-instance \
                            --publicly-accessible \
                            --engine ${RDS_ENGINE} \
                            --db-cluster-identifier restored-${RDS_TO_RESTORE} \
                            --db-instance-identifier restored-${RDS_TO_RESTORE}-instance-2 \
                            --db-instance-class ${RDS_INSTANCE_TYPE}"

                    echo "=========================== AWS RDS: Wait when Aurora Instance have been created  ==========================="
                    sh "sleep 500"
                    sh "aws rds wait db-instance-available --db-instance-identifier restored-${RDS_TO_RESTORE}-instance-1"
                    sh "aws rds wait db-instance-available --db-instance-identifier restored-${RDS_TO_RESTORE}-instance-2"
                }
                break

 

Расскажу немного про sh “sleep 500”. При использовании aws rds wait есть один нюанс, если кластер не перешёл в статус avalible за 30 минут, команда выдаст ошибку и задание завершиться со статусом Failed. При этом кластер будет продолжать восстановление в AWS. Пока что я не нашел решения на просторах интернета и форумах, по этому подсчитал сколько примерно восстанавливаются большие кластера и добавил sleep интервалом в 5 минут.

Таким образом перед запуском команды wait выполняется задержка в 5 минут, а уже после запуск команды, такой задержки хватает чтоб кластер успел восстановиться и задание завершилось успешно.

Проверяем работу скрипта, добавим его в задание и сохраним. Жмем Build with Parameters выбираем нужные параметры, имя кластера для восстановления и дату, запускаем нажав Build.

Для проверки статуса перейдем в AWS Console –> RDS —–> DataBases, ищем наш кластер по началу имени restored:

как видим, кластер в процессе восстановления, ожидаем  и проверим еще раз:

кластер восстановился, переходим к описанию удаления.

Удаление

Добавляем возможность удаления аврора кластера и простого RDS:

            case "delete-restored-aurora-cluster":
                stage("RDS: Delete Aurora Cluster") {

                    sh "aws rds delete-db-instance --skip-final-snapshot --db-instance-identifier ${RDS_TO_DEL}-instance-1"
                    sh "aws rds delete-db-instance --skip-final-snapshot --db-instance-identifier ${RDS_TO_DEL}-instance-2"

                    sh "aws rds wait db-instance-deleted --db-instance-identifier ${RDS_TO_DEL}-instance-1"
                    sh "aws rds wait db-instance-deleted --db-instance-identifier ${RDS_TO_DEL}-instance-2"
                    sh "aws rds delete-db-cluster --skip-final-snapshot --db-cluster-identifier ${RDS_TO_DEL}"

                }
                break

            case "delete-restored-rds-instance":
                stage("RDS: Delete DB Instance"){

                    sh "aws rds delete-db-instance --skip-final-snapshot --db-instance-identifier ${RDS_TO_DEL}"

                    sh "aws rds wait db-instance-deleted --db-instance-identifie ${RDS_TO_DEL}"
                }
                break
        }
    }
}

выбираем CHOSE_ACTION: delete-restored-aurora-cluster и в RDS_TO_DEL: restored-aurora-gaming-psql-dev имя восстановленного кластера который хотим удалить, после жмем Build:

ожидаем завершение задания:

задание завершилось успешно, теперь осталось проверить удалился ли кластер. Воспользуемся терминалом и aws-cli:

$ aws rds describe-db-clusters --db-cluster-identifier restored-aurora-gaming-psql-dev                                                                                                                                                 
An error occurred (DBClusterNotFoundFault) when calling the DescribeDBClusters operation: DBCluster restored-aurora-gaming-psql-dev not found.

кластер удалился.

Полезные ссылки

https://www.tutorialspoint.com/groovy/index.html
https://docs.aws.amazon.com/cli/latest/reference/rds/restore-db-instance-from-db-snapshot.html
https://docs.aws.amazon.com/cli/latest/reference/rds/restore-db-cluster-from-snapshot.html
https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/BackupRestoreAurora.html
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_CommonTasks.BackupRestore.html

Click to rate this post!
[Total: 0 Average: 0]