Я рассказывал в своих заметках о установке, настройке, масштабировании и о джобах в Jenkins-е. В голову пришло еще то, что нужно еще и иметь бэкапы для того, чтобы можно было откатится назад. Я нагуглил пару решений. Но еще не решил какое лучше. По этому, расскажу о них.
Полезное чтиво:
Установка Jenkins в Unix/Linux
Работа с Jenkins-CLI в Unix/Linux
Установка Jenkins и Jenkins-slave в Unix/Linux
Создание Jenkins backup/restore в Unix/Linux
И так, нам понадобится установить плагин(ы) (можно и один на выбор, я использовал несколько для сравнения):
- Thin backup
- Backup Plugin
- Periodic Backup
- SCM Sync configuration
Можно заюзать и другие решения:
- Использовать Git и взять «$JENKINS_HOME» под него.
- Написать BASH скрипт и создать джобу на ее выполнение.
Перейдем к решениям!
Использование Thin backup плагина для backup/restore Jenkins-а в Unix/Linux
Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Thin backup». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.
PS: Для перезагрузки дженкинс-сервера, я использую «Restart Safely» плагин.
Настройки бекапа, переходим в «Manage Jenkins» -> «ThinBackup»:
В данном плагине имеются:
- Backup Now — Кнопка чтобы сделать бекап сейчас.
- Restore — Служит для рестора данных.
- Settings — Настройка для бэкапа.
Начнем с настройки, нажимаем по нему:
Я отметил нужные мне поля и нажал на кнопку «Save». Т. е у меня будут выполнятся бэкапы по заданному расписанию и складыватся в «/backups» папку. Теперь можно запустить «Backup now» чтобы выполнился бэкап.
Вот и все. Можно юзать данный плагин для бэкаа и рестора.
Использование Backup Plugin плагина для backup/restore Jenkins-а в Unix/Linux
Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Backup plugin». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.
Настройки бекапа, переходим в «Manage Jenkins» -> «Backup manager»:
В данном плагине имеются:
- Setup — Служит для настройки бэкапов.
- Backup Hudson configuration — Чтобы создать бэкап.
- Restore Hudson configuration — Для рестора бэкапа.
Я привел настройку к такому виду:
После настроек нажимаем на «Save». Нажимаем на «Backup Hudson configuration» для создания бэкапа.
Использование Periodic Backup плагина для backup/restore Jenkins-а в Unix/Linux
Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Periodic Backup». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.
Настройки бекапа, переходим в «Manage Jenkins» -> «Periodic Backup Manager»:
Плагин не сконфигурирован и его нужно отконфигурить. Что я и сделаю сейчас, нажимаем на «Configure»:
Вот и все. Можно выполнить бэкап! Данный плагин понравился больше чем другие!
Использование SCM Sync configuration плагина для backup/restore Jenkins-а в Unix/Linux
Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «SCM Sync configuration». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.
Создам проект в гитлабе, например «configurations/jenkins».В данной проекте я буду хранить все настройки.
Переходим в «Manage Jenkins» -> «Configure System» и находим поле «SCM» и заполняем поля. У меня не получилось подружится с этим плагином вообще. Снес его!
Использование bash-скрипта для backup/restore Jenkins-а в Unix/Linux
Можно написать скрипты на любой вкус, используя bash. Есть плагин для запуска скриптов через джобу. Сейчас поставим данный плагин.
Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Exclusive Execution». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало. Создам структуру: Projects->Configurations. Т.е папка Projects в ней будут проекты, в данном случае «Configurations» — конфиги (Для создания папки, нажмите «New item» и выбирете «folder»).
Переходим в проект и нажимаем на «New item» и кликаем по «Freestyle project». Вводим имя для проекта, у меня — «jenkins-backup» и нажимаем на «OK»:
Потом переходим в созданный проект и нажимаем на «Configure» и находим поле «Source Code Management» и прописываем УРЛ где будет лежать скрипт для бэкапа у меня это готовое решение какого-то чела, например:
Идем дальше и переходим во «Build Triggers» вкладку и заполним:
Т.е заполним переодичность с которой будет запускаться скрипт.sh1 lines
H 3 * * *
После этого переходим во «Build» вкладку и затем, из списка выбираем «Execute shell». и прописываем параметры для запуска:
Добавляем в поле следующий текст:sh1 lines
./jenkins-backup.sh $JENKINS_HOME /backups/backup_`date +"%Y_%m_%d_%H:%M:%S"`.tar.gz
И на этом все, нажимаем на «Save». После этого, будет выполнятся бекап по заданному времени. Если есть необходимость, то можно запустить джобу маннуалли (Нажав на «Build Now»).
PS: Можно сделать бэкап-ротейт чтобы все старые бэкапы удалялись автоматом, например, можно добавить еще один «Execute shell» команду:sh1 lines
find /backups/backup_* -mtime +7 -delete
Т.е бэкапы будут хранится 7 дней, остальные будут удалены.
Вот еще один пример скрипта, который можно использовать:sh42 lines
#!/bin/bash
# Setup
#
# - Create a new Jenkins Job
# - Mark "None" for Source Control Management
# - Select the "Build Periodically" build trigger
# - configure to run as frequently as you like
# - Add a new "Execute Shell" build step
# - Paste the contents of this file as the command
# - Save
#
# NOTE: before this job will work, you'll need to manually navigate to the $JENKINS_HOME directory
# and do the initial set up of the git repository.
# Make sure the appropriate remote is added and the default remote/branch set up.
#
# Jenkins Configuraitons Directory
cd $JENKINS_HOME
# Add general configurations, job configurations, and user content
git add -- *.xml jobs/*/*.xml userContent/*
# only add user configurations if they exist
if [ -d users ]; then
user_configs=`ls users/*/config.xml`
if [ -n "$user_configs" ]; then
git add $user_configs
fi
fi
# mark as deleted anything that's been, well, deleted
to_remove=`git status | grep "deleted" | awk '{print $3}'`
if [ -n "$to_remove" ]; then
git rm --ignore-unmatch $to_remove
fi
git commit -m "Automated Jenkins commit"
git push -q -u origin master
Как по мне, все тут логично и понятно что он делаеет… Аналогичным способом можно сделать джобу и запускать переодически. Тем самым, все конфиг-файлы, будут попадать в гит.
Вывод: Я протестировал несколько плагинов и выбрал — использовать скрипты или Thin backup, Periodic Backup плагины. Но если есть другие решения, — пишите, дополню материал.
Я для клиента писал вот такой скрипт:sh38 lines
#!/usr/bin/env bash
# JENKINS_HOME
# +- config.xml (jenkins root configuration)
# +- *.xml (other site-wide configuration files)
# +- userContent (files in this directory will be served under your http://server/userContent/)
# +- fingerprints (stores fingerprint records)
# +- nodes (slave configurations)
# +- plugins (stores plugins)
# +- secrets (secretes needed when migrating credentials to other servers)
# +- workspace (working directory for the version control system)
# +- [JOBNAME] (sub directory for each job)
# +- jobs
# +- [JOBNAME] (sub directory for each job)
# +- config.xml (job configuration file)
# +- latest (symbolic link to the last successful build)
# +- builds
# +- [BUILD_ID] (for each build)
# +- build.xml (build result summary)
# +- log (log file)
# +- changelog.xml (change log)
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
echo "==================== Jenkins backup ====================";
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
JENKINS_DIR="/mnt/data/jenkins"
JENKINS_BACKUP_DIR="/mnt/data/jenkins_backup"
cp -r ${JENKINS_DIR}/*.xml ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/userContent ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/fingerprints ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/nodes ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/plugins ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/secrets ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/workspace ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/jobs ${JENKINS_BACKUP_DIR}
Проверялось, — работает!
Резервное копирование для Jenkins
Все, кто занимается задачами CI/CD, так или иначе знают про Jenkins, даже если им посчастливилось не иметь с ним дела.
Этот непотопляемый кадавр продолжает жить и процветать по следующим причинам:
- гибкость настроек (от настраиваемых диалоговых окон до встроенного Groovy);
- архитектура с поддержкой плагинов и обширный набор готовых плагинов на все случаи жизни;
- и самое главное — большой накопленный объём пользовательских проектов, которые проще продолжать развивать и поддерживать в среде Дженкинса, чем пытаться мигрировать на более современные и приятные платформы.
Очевидно, что чем важнее данные внутри Дженкинса для тех, кто им пользуется, тем актуальнее для них резервное копирование этих данных.
Однако здесь возникают два небольших препятствия:
- настройки, временные данные и файлы проектов смешаны внутри рабочего каталога в одну кучу;
- штатного механизма не существует, вместо него есть энное число посторонних костылей, распространяемых в виде плагинов, описаний и копипаст.
Поэтому, взяв за основу один из таких костылей, мы написали свой собственный.
Список предварительных пожеланий к нему был примерно таким:
- резервная копия должна иметь минимальный размер и максимальную скорость создания (например, дамп виртуальной машины или снимок ZFS с сотнями гигабайт проектов не годится);
- после восстановления нам достаточно иметь полностью настроенный сервер без предыдущего состояния — который знает, как выполнять новые job’ы, но ничего не помнящий про старые;
- поскольку настройки имеют текстовый вид, пусть они сохраняются в Git-репозиторий;
- если Jenkins предназначен для автоматического выполнения заданий, пусть самостоятельно выполняет всю работу по своему обслуживанию.
Общая схема:
- в $JENKINS_HOME создаётся Git-репозиторий;
- на Git-сервере для него создаётся origin (далее приводятся настройки для Gitlab);
- в Дженкинсе создаётся периодическое задание, которое сохраняет в Git ключевые файлы;
- для уменьшения размера от плагинов сохраняются только манифесты, при восстановлении плагины скачиваются заново.
Сначала создайте пользователя и репозиторий в Gitlab’e:
- пользователь = jenkins-backup-robot;
- репозиторий = jenkins-configs;
- URL репозитория скопируйте в буфер обмена;
- откройте Repository => Settings => Members;
- назначьте jenkins-backup-robot мантейнером (иначе Gitlab не даст сделать ему первый push в пустой репозиторий).
Теперь идите в командную строку сервера, на котором работает Jenkins:
- нам требуется создать SSH-ключ и Git-репозиторий:
sudo -Hiu jenkins
cd ~
git init
git config --global user.name Jenkins
git config --global user.email "jenkins@$(hostname -f)"
git remote add origin ВСТАВЬТЕ_ЗДЕСЬ_URL_GIT_РЕПОЗИТОРИЯ
test -s ~/.ssh/id_rsa.pub || ssh-keygen
cat ~/.ssh/id_rsa.pub
Созданный SSH-ключ надо импортировать в Gitlab:
- Это делается в разделе Admin => Users => jenkins-backup-robot => Impersonate => Personal Settings => SSH keys.
Создайте в Дженкинсе новое задание:
- Name: Backup Jenkins configs to Git
- Type: Free job
- Label: master
- SCM: None
- Build: Build Periodically
- Schedule: 20 04 * * *
- Build step: Execute Shell
- Command:
#!/bin/sh -e
cd "$JENKINS_HOME"
# Add general configurations, secrets, job configurations, nodes, user content, users and plugins info:
ls -1d *.xml secrets/ jobs/*/*.xml nodes/*/*.xml userContent/* users/*/config.xml
plugins/*/META-INF/MANIFEST.MF 2>/dev/null | grep -v '^queue.xml$' | xargs -r -d 'n' git add --
# Track deleted files:
LANG=C git status | awk '$1 == "deleted:" { print $2; }' | xargs -r git rm --ignore-unmatch
LANG=C git status | grep -q '^nothing to commit' || {
git commit -m "Automated Jenkins commit at $(date '+%Y-%m-%d %H:%M')"
git push -q -u origin master
}
- SAVE
Пояснения:
- Метка “master” нужна, если у Дженкинса есть slave-узлы. Если их нет, метку в задании можете не указывать. Если они есть, то в списке узлов отредактируйте свойства мастера и в поле “Labels” добавьте “master”. Если вы этого не сделаете, Дженкинс попытается выполнять задание через агентов на всех узлах, а это явно не то, что нам требуется.
- Если для подключения к Git-серверу используется SSH, перед выполнением задания не забудьте подключиться к нему вручную, чтобы git push не завершался с ошибкой из-за StrictHostKeyChecking.
Заключительный шаг в Gitlab’e после успешного git push:
- в свойствах репозитория откройте раздел Members и понизьте уровень доступа для Дженкинса с Maintainer до Developer;
- в Settings => Repository => Protected branches поменяйте для ветки “master” разрешение “Allow to push” с Maintainers на Maintainers+Developers.
Восстановление плагинов:
- Т.к. мы сохраняем только манифесты плагинов, после восстановления из резервной копии нам потребуется просканировать каталог с манифестами и составить список команд для загрузки дистрибутивов:
sudo -Hiu jenkins
cd ~/plugins/
gawk 'BEGIN { RS = "rn" }
BEGINFILE { n = v = "" }
ENDFILE { printf "curl -sS -L -O http://updates.jenkins-ci.org/download/plugins/%s/%s/%s.hpin", n, v, n }
$1 == "Short-Name:" { n = $2 }
$1 == "Plugin-Version:" { v = $2 }
' ./*/META-INF/MANIFEST.MF > ./download_all_plugins.sh
- Обратите внимание, что вместо awk используется gawk (GNU awk), т.к. классический awk не понимает BEGINFILE и ENDFILE. В некоторых дистрибутивах gawk устанавливается по умолчанию, в некоторых его потребуется установить вручную.
- Если gawk отработает без ошибок, запустите сгенерированный им файл:
sudo -Hiu jenkins
cd ~/plugins/
gawk 'BEGIN { RS = "rn" }
BEGINFILE { n = v = "" }
ENDFILE { printf "curl -sS -L -O http://updates.jenkins-ci.org/download/plugins/%s/%s/%s.hpin", n, v, n }
$1 == "Short-Name:" { n = $2 }
$1 == "Plugin-Version:" { v = $2 }
' ./*/META-INF/MANIFEST.MF > ./download_all_plugins.sh
- Самостоятельно распаковывать и устанавливать скачанные hpi-файлы не требуется — перезапустите Дженкинс и он сделает это сам.
Источники: https://linux-notes.org/sozdanie-jenkins-backup-restore-v-unix-linux/ и https://cdnnow.ru/blog/jenkins-backup/