Пока ты возишься с Jenkins на ноутбуке, потеря данных - это неприятность на пять минут. В проде все иначе. Если контроллер - это единственное место, где живут описания всех джоб, история билдов, креды и настройки плагинов, то он мгновенно превращается в критичную инфраструктуру. Падает Jenkins - встают релизы, не катятся хотфиксы, команда сидит без CI. И самое обидное, что чаще всего Jenkins умирает не от хакеров, а от банальных вещей: кончилось место на диске, кривое обновление снесло половину плагинов, кто-то руками поправил конфиг и забыл. Это и есть jenkins администрирование в реальной жизни - не клики по UI, а бэкап, обновление и масштабирование под нагрузкой.
В этом уроке разберем три кита эксплуатации Jenkins в продакшене. Как делать jenkins backup так, чтобы из него реально можно было восстановиться. Как проводить jenkins обновление контроллера и плагинов без сюрпризов. И как делать jenkins масштабирование, не убивая контроллер лишней работой. Свяжем все это с Configuration as Code из урока 6 - именно JCasC превращает хрупкий сервер в воспроизводимую систему.
Сразу про версии, чтобы ты ориентировался в 2026 году. Апрельская LTS-линейка 2.555.x требует Java 21 или Java 25, поддержка Java 17 в ней уже выпилена (январская 2.541.x была последней с Java 17). Так что перед любым апгрейдом первым делом смотри на свою JVM. Blue Ocean окончательно в статусе legacy - команда его забросила, и для визуализации конвейеров теперь штатный Pipeline Graph View прямо в основном UI. Строить на Blue Ocean новое не надо.

Jenkins backup: что именно бэкапить
Все состояние Jenkins живет в одной директории - JENKINS_HOME (обычно /var/jenkins_home в контейнере). Это не база данных, а просто дерево XML-файлов и каталогов. Хорошая новость: бэкап концептуально прост. Плохая: там лежит абсолютно все, включая мусор, который раздувает архив до десятков гигабайт.
Что обязательно входит в jenkins backup:
- config.xml - глобальная конфигурация контроллера
- jobs/*/config.xml - описания всех джоб (для пайплайнов из SCM сам Jenkinsfile в Git, но настройки джобы тут)
- plugins/ - установленные плагины и их версии (либо бэкапь, либо фиксируй список через plugins.txt - см. ниже)
- users/, secrets/, credentials.xml - пользователи и креды. Без файлов из secrets/ зашифрованные креды не расшифруются, имей в виду
- nodes/ - конфигурация статических агентов
Простейший рабочий вариант - снапшот всего тома средствами инфраструктуры. На железе это tar по расписанию, в k8s - VolumeSnapshot для PVC. Главное правило: бэкапить консистентно. Лучше всего на остановленном Jenkins или хотя бы в режиме Prepare for Shutdown (новые билды не стартуют). Скрипт-минимум:
Код: Выделить всё
#!/usr/bin/env bash
set -euo pipefail
JENKINS_HOME=/var/jenkins_home
DEST=/backup/jenkins-$(date +%F-%H%M).tar.gz
tar -czf "$DEST" \
--exclude="$JENKINS_HOME/workspace" \
--exclude="$JENKINS_HOME/builds" \
--exclude="$JENKINS_HOME/caches" \
--exclude="$JENKINS_HOME/war" \
-C "$JENKINS_HOME" .
# держим только 14 последних архивов
ls -1t /backup/jenkins-*.tar.gz | tail -n +15 | xargs -r rm -f
echo "backup ready: $DEST"
Jenkins обновление: контроллер и плагины без боли
Тут кроется главная ловушка эксплуатации. Обновлять Jenkins надо - в нем регулярно чинят дыры в безопасности. Но именно jenkins обновление чаще всего и роняет прод. Причина почти всегда одна: несовместимость плагинов. Ядро уехало вперед, а какой-нибудь старый плагин рассчитан на прежний API и при старте отваливается, утаскивая за собой половину функциональности.
Дисциплина обновления в 2026:
- Сиди на LTS-линейке, не на weekly. LTS выходит раз в 12 недель и собирает уже обкатанные фиксы.
- Перед апгрейдом проверь требования к Java. Прыжок на 2.555.x без Java 21/25 просто не стартует.
- Никогда не обновляйся сразу в проде. Подними стейдж - копию контроллера из свежего бэкапа - и накати обновление сначала туда.
- Сначала ядро, потом плагины (или наоборот - но по очереди и с проверкой). Читай Update Center: он подсвечивает плагины, несовместимые с целевой версией ядра.
- Фиксируй версии плагинов. Обновление "все сразу на последнее" - это лотерея. Поднимай по группам.
Код: Выделить всё
pipeline {
agent { label 'linux' }
options { timeout(time: 10, unit: 'MINUTES') }
stages {
stage('Sanity') {
steps {
sh 'java -version'
sh 'echo "agent online: $(hostname)"'
}
}
stage('Creds check') {
steps {
withCredentials([string(credentialsId: 'smoke-token', variable: 'TOK')]) {
sh 'test -n "$TOK" && echo "creds OK"'
}
}
}
stage('Build probe') {
steps {
git url: 'https://git.example.com/team/sample.git', branch: 'main'
sh 'make build'
}
}
}
post {
failure { echo 'Апгрейд сломал базовый сценарий - откатываемся' }
}
}
Jenkins масштабирование: разгружаем контроллер
Главный принцип масштабирования Jenkins звучит так: контроллер не должен ничего собирать. Его задача - оркестрация, веб-морда, хранение конфигов и распределение работы. Любая реальная сборка должна уходить на агента. Если у тебя стоит executor на самом контроллере и на нем что-то компилируется - это первое, что надо выключить. Перегруженный контроллер тормозит весь jenkins prod: UI лагает, очередь растет, агенты отваливаются по таймауту.
Дальше есть два пути.
Статические агенты - выделенные машины (VM или железо), которые постоянно подключены к контроллеру. Просто, предсказуемо, но ты платишь за простой: ночью агенты стоят без дела, а в час пик их не хватает.
Эфемерные агенты в Kubernetes - современный стандарт 2026. Через kubernetes-плагин Jenkins под каждый билд поднимает отдельный pod, который живет ровно столько, сколько идет сборка, а потом уничтожается. Никаких "грязных" окружений от прошлых билдов, оплата только за фактическое время, автоматическое масштабирование вместе с кластером. podTemplate описывается прямо в Jenkinsfile:
Код: Выделить всё
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.9-eclipse-temurin-21
command: ["sleep"]
args: ["infinity"]
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
'''
}
}
stages {
stage('Build') {
steps {
container('maven') {
sh 'mvn -B clean package'
}
}
}
}
}
Без k8s тоже есть варианты эфемерности: docker-плагин (контейнер на билд на Docker-хосте) или облачные агенты на спотах. Идея та же - не держать парк машин в простое.
Мониторинг и здоровье контроллера
Масштабировать вслепую нельзя - нужны метрики. Базовый набор для jenkins администрирование в проде: длина очереди сборок, число занятых executor'ов, время в очереди, использование heap JVM, статус подключения агентов. Стандартный инструмент 2026 - плагин Prometheus metrics: он отдает эндпоинт /prometheus, Prometheus его скрейпит, а ты строишь дашборды и алерты в Grafana.
Код: Выделить всё
# prometheus.yml - scrape job для Jenkins
scrape_configs:
- job_name: 'jenkins'
metrics_path: '/prometheus'
scheme: http
static_configs:
- targets: ['jenkins.internal:8080']
Контроллер как код: JCasC + plugins.txt + Docker
Вот где сходятся все три темы урока. Если контроллер описан кодом, то бэкап упрощается (бэкапить надо в основном данные, а не конфигурацию), обновление становится предсказуемым (версии плагинов зафиксированы), а disaster recovery - это пересборка образа, а не ручное восстановление по памяти.
Рецепт воспроизводимого контроллера из трех файлов. Первый - plugins.txt с зафиксированными версиями:
Код: Выделить всё
configuration-as-code:1932.v17e874b_4a_a_99
kubernetes:4306.va_da_66c6e9a_29
git:5.7.0
workflow-aggregator:608.v67378e9d3db_1
prometheus:2.6.0
Код: Выделить всё
jenkins:
systemMessage: "Managed by JCasC - do not edit via UI"
numExecutors: 0
clouds:
- kubernetes:
name: "k8s"
serverUrl: "https://kubernetes.default:443"
namespace: "jenkins-agents"
jenkinsUrl: "http://jenkins.jenkins.svc:8080"
containerCapStr: "20"
unclassified:
location:
url: "https://jenkins.example.com/"
Третий - Dockerfile, который запекает плагины в образ. Никакого скачивания плагинов на старте, никакого дрейфа версий:
Код: Выделить всё
FROM jenkins/jenkins:2.555.1-lts-jdk21
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN jenkins-plugin-cli --plugin-file /usr/share/jenkins/ref/plugins.txt
COPY jenkins.yaml /var/jenkins_home/casc_configs/jenkins.yaml
ENV CASC_JENKINS_CONFIG=/var/jenkins_home/casc_configs
Типичные грабли
- Бэкап без папки secrets/ - креды после восстановления превращаются в нечитаемый мусор.
- Апгрейд сразу в проде "потому что окошко мигало". Стейдж не роскошь, а страховка.
- Сборка на контроллере. Один тяжелый билд - и UI у всей команды лагает.
- "Update all plugins" одной кнопкой без фиксации версий. Несовместимый плагин роняет старт.
- Прыжок на новую LTS без проверки Java. 2.555.x на Java 17 не запустится в принципе.
- Нет алерта на свободное место - JENKINS_HOME забивается логами билдов, и контроллер тихо умирает.
- Напиши bash-скрипт бэкапа JENKINS_HOME с исключением builds/ и workspace/ и ротацией. Проверь, что secrets/ и credentials.xml в архиве.
- Подними тестовый контроллер из Dockerfile с plugins.txt и jenkins.yaml. Убедись, что numExecutors там 0, заданный через JCasC.
- Опиши podTemplate в Jenkinsfile и прогони сборку на эфемерном агенте в k8s (или на docker-плагине, если нет кластера).
- Установи плагин Prometheus metrics, открой /prometheus, найди метрику длины очереди и метрику heap.
- Сэмулируй апгрейд: подними копию из бэкапа как стейдж, накати новую LTS, прогони smoke-Jenkinsfile.
- Какие каталоги внутри JENKINS_HOME критичны для восстановления, а какие можно безопасно исключить из бэкапа?
- Почему нельзя обновлять прод-Jenkins напрямую и из чего состоит безопасная процедура апгрейда?
- В чем преимущество эфемерных агентов в Kubernetes перед статическими и зачем контроллеру numExecutors: 0?
- Как связка plugins.txt + jenkins.yaml + Dockerfile упрощает disaster recovery по сравнению с ручной настройкой через UI?
Эксплуатация Jenkins в проде держится на трех вещах. Бэкап - снапшот JENKINS_HOME с обязательными secrets/ и кредами, без лишних билдов и workspace. Обновление - только через стейдж, с фиксацией версий плагинов и проверкой требований к Java (в 2026 это уже Java 21/25 на свежих LTS). Масштабирование - выноси сборки с контроллера на агентов, а лучше на эфемерные pod'ы в Kubernetes, и смотри за метриками через Prometheus. А связующее звено - контроллер как код: JCasC, plugins.txt и Docker превращают хрупкий сервер с кучей ручных настроек в систему, которую можно пересобрать с нуля за минуты. Это та зрелость, ради которой Jenkins вообще стоит держать в продакшене.