Введение
Jenkins хранит большинство конфигураций контроллера и заданий в виде файлов в директории JENKINS_HOME. Эффективный план резервного копирования должен включать файлы, определяющие задания и настройки контроллера, а план восстановления должен подтверждать, что Jenkins способен корректно загрузить восстановленные данные.
В этой лабораторной работе вы создадите демонстрационное задание, выполните резервное копирование его файла config.xml, удалите задание, восстановите его из tar-архива, перезагрузите Jenkins и убедитесь, что задание снова работает.
Создание состояния Jenkins для резервного копирования
На этом этапе вы создадите Freestyle-задание с именем backup-restore-demo. Это даст вам реальный файл конфигурации Jenkins для резервного копирования и восстановления.
Создайте конфигурацию задания:
cat > /home/labex/project/backup-restore-demo-config.xml <<'XML'
<?xml version='1.1' encoding='UTF-8'?>
<project>
<actions/>
<description>Job used to practice Jenkins backup and restore.</description>
<keepDependencies>false</keepDependencies>
<properties/>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Shell>
<command>echo "Restored Jenkins job is running"</command>
<configuredLocalRules/>
</hudson.tasks.Shell>
</builders>
<publishers/>
<buildWrappers/>
</project>
XML
Скопируйте задание в Jenkins и выполните перезагрузку:
docker exec -u root jenkins mkdir -p /var/jenkins_home/jobs/backup-restore-demo
docker cp /home/labex/project/backup-restore-demo-config.xml jenkins:/var/jenkins_home/jobs/backup-restore-demo/config.xml
docker exec -u root jenkins chown -R jenkins:jenkins /var/jenkins_home/jobs/backup-restore-demo
/home/labex/project/reload-jenkins.sh
Убедитесь, что Jenkins успешно загрузил задание:
curl -fsS http://localhost:8080/job/backup-restore-demo/api/json | grep -o '"name":"backup-restore-demo"'
Резервное копирование конфигурации задания
На этом этапе вы скопируете конфигурацию задания из контейнера Jenkins и заархивируете её. Резервная копия сохраняет относительный путь jobs/backup-restore-demo/config.xml, что делает процесс восстановления прозрачным.
Создайте рабочую директорию для резервной копии и скопируйте конфигурацию задания:
mkdir -p /home/labex/project/jenkins-backup-work/jobs/backup-restore-demo
docker cp jenkins:/var/jenkins_home/jobs/backup-restore-demo/config.xml /home/labex/project/jenkins-backup-work/jobs/backup-restore-demo/config.xml
Создайте сжатый tar-архив:
cd /home/labex/project/jenkins-backup-work
tar -czf /home/labex/project/backup-restore-demo.tar.gz jobs/backup-restore-demo/config.xml
Выведите содержимое архива:
tar -tzf /home/labex/project/backup-restore-demo.tar.gz
Вывод должен содержать:
jobs/backup-restore-demo/config.xml
Удаление задания для имитации потери данных
На этом этапе вы удалите задание из Jenkins. Это имитирует случайное удаление и создает четкую цель для восстановления.
Удалите директорию задания и перезагрузите Jenkins:
docker exec -u root jenkins rm -rf /var/jenkins_home/jobs/backup-restore-demo
/home/labex/project/reload-jenkins.sh
Убедитесь, что задание больше недоступно. В приведенной ниже команде ответ 404 намеренно считается успешным результатом проверки:
if curl -fsS http://localhost:8080/job/backup-restore-demo/api/json >/dev/null 2>&1; then
echo "Job still exists"
exit 1
else
echo "Job is absent and ready to restore"
fi
Восстановление задания из резервной копии
На этом этапе вы распакуете архив, скопируете восстановленную директорию задания обратно в Jenkins и перезагрузите контроллер.
Распакуйте архив в директорию восстановления:
rm -rf /home/labex/project/restore-work
mkdir -p /home/labex/project/restore-work
tar -xzf /home/labex/project/backup-restore-demo.tar.gz -C /home/labex/project/restore-work
Скопируйте восстановленную директорию задания в Jenkins и перезагрузите:
docker cp /home/labex/project/restore-work/jobs/backup-restore-demo jenkins:/var/jenkins_home/jobs/backup-restore-demo
docker exec -u root jenkins chown -R jenkins:jenkins /var/jenkins_home/jobs/backup-restore-demo
/home/labex/project/reload-jenkins.sh
Убедитесь, что Jenkins успешно загрузил восстановленное задание:
curl -fsS http://localhost:8080/job/backup-restore-demo/api/json | grep -o '"name":"backup-restore-demo"'
Запуск восстановленного задания
На этом этапе вы запустите восстановленное задание. Восстановление полезно только в том случае, если Jenkins может загрузить и выполнить восстановленную конфигурацию.
Запустите сборку. Jenkins сначала возвращает элемент очереди, поэтому сохраните заголовки ответа и считайте заголовок Location:
CRUMB=$(curl -fsS -c /tmp/jenkins-backup-build.cookies 'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -fsS -D /tmp/backup-restore-build.headers -o /dev/null -b /tmp/jenkins-backup-build.cookies -H "$CRUMB" -X POST http://localhost:8080/job/backup-restore-demo/build
QUEUE_URL=$(awk 'tolower($1)=="location:" {print $2}' /tmp/backup-restore-build.headers | tr -d '\r')
echo "Jenkins queued the restored job at ${QUEUE_URL}"
Дождитесь, пока элемент в очереди превратится в реальную сборку. Jenkins может потратить несколько секунд на период ожидания (quiet period), прежде чем назначит окончательный номер сборки:
until BUILD_NUMBER=$(python3 - "$QUEUE_URL" <<'PY'
import json
import sys
import urllib.request
with urllib.request.urlopen(sys.argv[1] + 'api/json') as response:
data = json.load(response)
executable = data.get('executable')
if not executable:
raise SystemExit(1)
print(executable['number'])
PY
); do
echo "Waiting for Jenkins to assign a build number..."
sleep 3
done
echo "The restored job is running as build #${BUILD_NUMBER}"
Дождитесь завершения сборки:
until curl -fsS "http://localhost:8080/job/backup-restore-demo/${BUILD_NUMBER}/api/json" >/tmp/backup-restore-build.json 2>/dev/null && grep -q '"building":false' /tmp/backup-restore-build.json; do
echo "Waiting for restored job build #${BUILD_NUMBER}..."
sleep 3
done
Проверьте вывод консоли:
curl -fsS "http://localhost:8080/job/backup-restore-demo/${BUILD_NUMBER}/consoleText" | grep -E 'Restored Jenkins job is running|Finished: SUCCESS'
Откройте Firefox в графическом интерфейсе рабочего стола и перейдите по URL консоли для номера сборки, отображенного в терминале, например http://localhost:8080/job/backup-restore-demo/2/console. На странице консоли должно быть видно, что восстановленное задание успешно выполнено.

Резюме
Вы создали конфигурацию Jenkins, выполнили резервное копирование файла config.xml задания, удалили задание, восстановили его из архива, перезагрузили Jenkins и подтвердили успешное восстановление, запустив сборку.