Резервное копирование и восстановление конфигурации Jenkins

Beginner

Введение

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

Резюме

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