Резервная копия Jenkins Home: восстановление в новый том
Проверьте резервную копию восстановлением в новый том и запуском Jenkins с него. Само наличие архива не подтверждает, что контроллер сможет его использовать.
Лаборатория останавливает новый, иначе не использовавшийся контроллер перед копированием home. Она хранит master.key отдельно, восстанавливает приватный архив в другой новый том, запускает тот же digest и сверяет маркер и исходный начальный пароль, не печатая ни одного значения пароля. Она не проверяет производственный контроллер, активное задание или миграцию плагинов.
Остановите, скопируйте, восстановите и запустите
Руководство резервирования Jenkins отличает содержимое копии от проверки восстановления. Остановленный источник исключает копирование во время записи этим контроллером. Это не согласованный snapshot внешних БД, агентов или других пишущих процессов.
Используйте полный jenkins_lab.py из лаборатории пересоздания контроллера, затем сохраните рядом второй файл. Нужны Python3 и работающий Docker engine с Linux-контейнерами.
jenkins_restore.py
import json
import tempfile
from jenkins_lab import DockerLab
with DockerLab() as lab, \
tempfile.TemporaryDirectory(prefix='jenkins-private-backup-') as backup, \
tempfile.TemporaryDirectory(prefix='jenkins-private-key-') as keys:
original = lab.start()
password = lab.password(original)
assert password, 'Missing initial password'
lab.cli('exec', original, 'sh', '-c', 'printf restored > /var/jenkins_home/lab-marker')
lab.cli('stop', '-t', '30', original)
lab.cli('run', '--rm', '--user', '0:0', '--entrypoint', 'sh',
'--mount', f'type=volume,source={lab.home},target=/source,readonly',
'--mount', f'type=bind,source={backup},target=/backup',
'--mount', f'type=bind,source={keys},target=/keys', lab.image,
'-c', 'set -e; umask 077; tar -C /source --exclude=./secrets/master.key -czpf /backup/home.tgz .; cp -p /source/secrets/master.key /keys/master.key')
members = lab.cli('run', '--rm', '--user', '0:0', '--entrypoint', 'tar',
'--mount', f'type=bind,source={backup},target=/backup,readonly', lab.image,
'-tzf', '/backup/home.tgz')
assert './secrets/master.key' not in members.splitlines()
restored_home = lab.volume()
lab.cli('run', '--rm', '--user', '0:0', '--entrypoint', 'tar',
'--mount', f'type=bind,source={backup},target=/backup,readonly',
'--mount', f'type=volume,source={restored_home},target=/restore', lab.image,
'-xzpf', '/backup/home.tgz', '-C', '/restore')
lab.cli('run', '--rm', '--user', '0:0', '--entrypoint', 'cp',
'--mount', f'type=bind,source={keys},target=/keys,readonly',
'--mount', f'type=volume,source={restored_home},target=/restore', lab.image,
'-p', '/keys/master.key', '/restore/secrets/master.key')
restored = lab.start(restored_home)
assert lab.marker(restored) == 'restored'
assert lab.password(restored) == password
print(json.dumps({'image': lab.image, 'jenkins': lab.version, 'sourceStopped': True,
'restoredToNewVolume': True, 'masterKeyExcluded': True, 'keyCopiedSeparately': True, 'markerRestored': True,
'passwordRestored': True, 'result': 'passed'}))
Выполните:
python3 jenkins_restore.py
Вспомогательные контейнеры заменяют entrypoint инструментами копирования, не запуская другой Jenkins. Они работают от root только для сохранения владельцев и прав источника при копировании. Список архива должен исключать master.key; отдельный помощник восстанавливает ключ до запуска Jenkins. Исходный том монтируется только для чтения после остановки; целевой — другой том этой лаборатории. Digest выбран при входе в лабораторию.
Успех содержит sourceStopped, restoredToNewVolume, markerRestored, passwordRestored, masterKeyExcluded, keyCopiedSeparately и result: passed. Запущенное восстановление также должно пройти HTTP-проверку DockerLab.start. Совпадение начального пароля подтверждает сохранность выбранного секрета, а не завершённое управление пользователями или все плагины credentials.
Относитесь к архиву как к данным контроллера
Это временное упражнение восстановления. Архив исключает secrets/master.key; ключ копируется отдельно и применяется после распаковки. Остальные секреты контроллера остаются в архиве. Оба временных каталога приватны и удаляются при выходе. Не загружайте архив как CI-артефакт, не коммитьте и не используйте эту объединённую копию как производственную политику.
В производстве руководство Jenkins по ключу требует обрабатывать master.key отдельно от обычных копий. До внедрения определите восстановление ключа, шифрование архива, хранение, доступ, внешнее размещение и внешнее состояние. Временный архив той же машины не даёт этих гарантий долговечности.
Восстановленный контроллер также удаляется после лаборатории. Это позволяет повторять упражнения, но успешные маркер, секрет и HTTP не доказывают восстановление всех заданий, плагинов, credentials и интеграций. Добавьте представительные нагрузки и расшифровку секретов в запланированную репетицию реальной системы.
Обсуждение