agent, environment и переменные в конвейере

Рейтинг: 61% · 6 голосов
Подробный курс по Jenkins и CI/CD: установка и настройка, плагины и Configuration as Code, конвейеры (pipeline) и Jenkinsfile, declarative и scripted, агенты, Docker и Kubernetes, общие библиотеки на Groovy, безопасность и credentials, интеграции (SonarQube, артефакты), траблшутинг. Актуально на 2026.
Ответить
Аватара пользователя
Andrey_CICD
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

agent, environment и переменные в конвейере

Сообщение Andrey_CICD »

Оглавление курса (47)
  1. Что такое Jenkins и зачем нужен CI/CD
  2. Jenkins в 2026: версии, экосистема и сравнение с GitLab CI и GitHub Actions
  3. Архитектура Jenkins: контроллер, агенты, узлы и исполнители
  4. Установка Jenkins: пакеты, Docker и Kubernetes
  5. Первичная настройка Jenkins: мастер, плагины, пользователи
  6. Плагины Jenkins: установка, обновление и ключевой набор
  7. Configuration as Code (JCasC): настройка Jenkins декларативно
  8. Конвейеры Jenkins и Jenkinsfile: pipeline as code
  9. Scripted против Declarative: два синтаксиса конвейера
  10. Структура конвейера: node, stage, steps и первый pipeline
  11. Генератор сниппетов, запуск конвейера и Replay
  12. Типы заданий Jenkins: Freestyle, Pipeline, Multibranch и Organization
  13. Декларативный конвейер: структура pipeline, agent, stages
  14. agent, environment и переменные в конвейере (вы здесь)
  15. tools, options, parameters и triggers в декларативном конвейере
  16. stages, parallel и matrix: организация этапов
  17. Условное выполнение when и блок post
  18. Триггеры сборки: webhook от GitHub, SCM polling и расписание
  19. Параметры сборки и пользовательский ввод
  20. Управление потоком: timeout, retry, sleep и waitUntil
  21. Параллелизм и блокировки: parallel, lock, milestone
  22. Постобработка и уведомления о результате сборки
  23. Groovy для Jenkins: основы скриптового конвейера
  24. Скриптовый конвейер: логика, циклы и функции
  25. Общие библиотеки Jenkins: Shared Libraries
  26. Подключение и загрузка общих библиотек
  27. Шаги оболочки: sh, bat, powershell и коды возврата
  28. Переменные среды, withEnv и рабочие пространства
  29. Работа с файлами, артефактами и отпечатками
  30. Сборка проектов в конвейере: Maven, Gradle, npm
  31. Качество кода: SonarQube и покрытие тестами
  32. Управление артефактами: публикация в Nexus и Artifactory
  33. Docker в Jenkins: образы как агенты сборки
  34. Сборка и публикация Docker-образов из конвейера
  35. Jenkins в Kubernetes: динамические pod-агенты
  36. Развёртывание в Kubernetes из конвейера
  37. Безопасность Jenkins: аутентификация и матрица прав
  38. Учётные данные Jenkins: credentials в конвейере
  39. Безопасность сценариев: Groovy sandbox и Vault
  40. Уведомления и отчёты: email, Slack, Telegram, HTML
  41. Blue Ocean и интерфейс Jenkins в 2026
  42. Автоматизация Jenkins: CLI, REST API и script console
  43. Поиск и устранение неисправностей: читаем логи конвейера
  44. Типичные ошибки конвейера: сериализация и неутверждённый код
  45. Эксплуатация Jenkins: бэкап, обновление, масштабирование
  46. Конвертация и миграция: от Freestyle к Jenkinsfile
  47. Итог: сквозной CI/CD конвейер и Jenkins против альтернатив в 2026
Представь: пайплайн собирается, но ты не понимаешь где именно. На каком узле? В каком окружении? Какая версия Node там стоит? А почему этот стейдж упал с "command not found", хотя локально все работает? Девять из десяти таких загадок упираются в две директивы declarative pipeline - agent и environment. Первая отвечает на вопрос "где выполняется код", вторая - "в каком окружении и с какими переменными". Разберемся в обеих так, чтобы ты больше никогда не гадал, куда уехал твой билд и откуда взялась переменная.

Для справки: на момент написания актуальная Jenkins LTS - 2.541.1 (январь 2026), а сам Jenkins требует уже Java 17 или новее, скоро минимум сместится на 21. Все примеры ниже - валидный declarative Jenkinsfile, это стандарт 2026 года.

Где выполняется конвейер: jenkins agent и его виды

Блок agent говорит контроллеру, на какой машине (или в каком контейнере) развернуть рабочую область и гонять шаги. Объявить его можно на двух уровнях: глобально для всего pipeline и локально внутри отдельного stage. Локальный перекрывает глобальный - это и есть главный рычаг управления.

Самые ходовые варианты jenkins agent:
  • agent any - бери любого свободного исполнителя. Годится для проб, но в проде так почти не пишут: непредсказуемо.
  • agent { label 'linux && docker' } - выбери агента по меткам. Метки навешиваются на узлы в настройках. Выражение поддерживает && и ||.
  • agent none на уровне pipeline - глобального агента нет, каждый stage объявляет свой. Удобно, когда стадии разнородные.
  • agent { docker { ... } } - подними контейнер и выполни шаги внутри него.
  • agent { kubernetes { ... } } - закажи эфемерный pod-агент в кластере (об этом ниже).
Вот скелет с разными агентами на разных уровнях:

Код: Выделить всё

pipeline {
    agent none
    stages {
        stage('Build') {
            agent { label 'linux && jdk17' }
            steps {
                sh 'mvn -B clean package'
            }
        }
        stage('Test') {
            agent { label 'linux && jdk17' }
            steps {
                sh 'mvn -B test'
            }
        }
    }
}
Тут agent none наверху значит "общего узла нет", и каждая стадия сама решает, где ей жить. Запомни ловушку: при agent none нельзя ставить steps прямо в pipeline и нельзя в глобальном post без агента дергать sh - выполнять оболочку негде.

Изображение

docker jenkins: запуск стейджа в контейнере

Связка docker jenkins - один из самых частых способов получить чистое, воспроизводимое окружение без зоопарка тулчейнов на самих узлах. Вместо того чтобы ставить Node, Python и Go на каждый агент, ты говоришь: "выполни эту стадию внутри образа node:22". Главное условие - на узле должен быть установлен Docker, а сам узел иметь метку, по которой Jenkins его найдет.

Код: Выделить всё

pipeline {
    agent {
        docker {
            image 'node:22-alpine'
            label 'docker'
            args '-v /tmp/npm-cache:/root/.npm'
        }
    }
    stages {
        stage('Install') {
            steps {
                sh 'node --version'
                sh 'npm ci'
            }
        }
        stage('Build') {
            steps {
                sh 'npm run build'
            }
        }
    }
}
Что тут важно. Поле image - образ из реестра. label - на каком узле запускать контейнер (там, где есть демон Docker). args - сырые аргументы docker run, сюда удобно прокинуть том для кэша, как выше. Jenkins сам монтирует рабочую область внутрь контейнера и запускает его под нужным uid, так что артефакты остаются в workspace после остановки контейнера.

Можно задать docker-агента и для одной стадии, оставив остальные на обычных узлах:

Код: Выделить всё

stage('Lint') {
    agent {
        docker { image 'python:3.13-slim'; label 'docker' }
    }
    steps {
        sh 'pip install ruff && ruff check .'
    }
}
Эфемерные агенты в Kubernetes

Если у тебя кластер, docker jenkins на статичных узлах часто заменяют на agent { kubernetes }. Тут под каждый билд kubernetes-плагин создает отдельный pod, гонит в нем шаги и удаляет его по завершении. Никаких "грязных" агентов с остатками прошлых сборок - каждый запуск с чистого листа.

Код: Выделить всё

pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.9-eclipse-temurin-21
    command: [sleep]
    args: ["infinity"]
'''
        }
    }
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn -B clean verify'
                }
            }
        }
    }
}
Шаг container('maven') переключает выполнение в нужный контейнер pod-а. Если его не указать, шаги уедут в служебный jnlp-контейнер, где нет твоих инструментов - типичная причина "mvn: not found". Эфемерные pod-агенты - это современный мейнстрим масштабирования Jenkins, в отличие от заброшенного Blue Ocean, на который сегодня уже ничего не строят.

Блок environment и jenkins переменные

Теперь про окружение. Блок environment задает переменные окружения - те самые jenkins env, которые видны в sh, bat и в шагах. Объявить его можно на уровне pipeline (видно всем стадиям) или внутри stage (видно только ей). Обращаться к значению можно двумя путями: внутри Groovy - через env.NAME, а внутри shell-команды - через обычную интерполяцию ${NAME}.

Код: Выделить всё

pipeline {
    agent any
    environment {
        APP_NAME  = 'cyberlake-api'
        BUILD_TAG = "${env.BUILD_NUMBER}-${env.GIT_COMMIT.take(7)}"
    }
    stages {
        stage('Info') {
            environment {
                STAGE_REGION = 'eu-central'
            }
            steps {
                echo "Сборка ${env.APP_NAME}, тег ${env.BUILD_TAG}"
                sh 'echo "Region: $STAGE_REGION, workspace: $WORKSPACE"'
            }
        }
    }
}
Обрати внимание на разницу синтаксиса. В echo "..." и в BUILD_TAG мы внутри Groovy, поэтому пишем ${env.APP_NAME}. А в одинарных кавычках sh '...' интерполяцию делает уже сам shell - там $STAGE_REGION и $WORKSPACE. Если завернуть sh в двойные кавычки, подстановку сделает Groovy еще до запуска оболочки - смешивать эти два механизма и есть источник половины багов с пустыми переменными.

Про встроенные jenkins переменные. Jenkins сам наполняет окружение кучей полезных значений, главные из них:
  • env.BUILD_NUMBER - порядковый номер сборки.
  • env.GIT_COMMIT - хеш коммита (появляется после checkout).
  • env.WORKSPACE - абсолютный путь к рабочей области на агенте.
  • env.JOB_NAME, env.BUILD_URL - имя задачи и ссылка на сборку.
Полный список всегда можно глянуть по адресу твой-сервер/env-vars.html.

Секреты в environment через credentials()

Хардкодить пароли в Jenkinsfile - грубейшая ошибка безопасности. Правильный путь - функция credentials() в блоке environment. Она достает секрет из хранилища Jenkins по ID и кладет его в переменную, маскируя значение в логах звездочками.

Код: Выделить всё

pipeline {
    agent any
    environment {
        REGISTRY      = 'registry.cyberlake.ru'
        DOCKER_CREDS  = credentials('docker-registry')
        SONAR_TOKEN   = credentials('sonar-token')
    }
    stages {
        stage('Push') {
            steps {
                sh '''
                    echo "$DOCKER_CREDS_PSW" | docker login "$REGISTRY" \
                        -u "$DOCKER_CREDS_USR" --password-stdin
                    docker push "$REGISTRY/app:${BUILD_NUMBER}"
                '''
            }
        }
    }
}
Тонкость, на которой спотыкаются все новички. Для credentials типа "username with password" функция создает не одну, а три переменные: DOCKER_CREDS (в формате user:password), DOCKER_CREDS_USR (логин) и DOCKER_CREDS_PSW (пароль). Для secret text - одну переменную с самим токеном, как SONAR_TOKEN выше. Не вздумай делать echo секрета в лог намеренно: маскировка спасает от случайной утечки, но не от прямого вывода через base64 или подобные трюки.

Типичные грабли
  • Перепутаны ${env.X} (Groovy) и $X (shell). В sql '...' с одинарными кавычками работает только $X, в двойных - подставляет Groovy.
  • agent none, а в pipeline остались steps или sh в глобальном post. Выполнять негде - падает на старте.
  • Образ для docker есть, а узла с Docker и нужной меткой нет. Билд висит в очереди "ожидает исполнителя".
  • В kubernetes-агенте забыт container('...') - шаги уходят в jnlp без инструментов, привет "not found".
  • Пытаешься менять env.X присваиванием в середине стадии - в declarative так нельзя. Для динамики используй блок script { env.X = '...' } или библиотечный шаг.
  • Ждешь env.GIT_COMMIT до шага checkout - переменная еще пустая.
Мини-лаба

Собери один Jenkinsfile и прогони его руками:
  • Сделай pipeline с agent none и двумя стадиями: первая на agent { docker { image 'node:22-alpine'; label 'docker' } }, вторая на любом label.
  • В глобальный environment положи APP_NAME и BUILD_TAG, собранный из ${env.BUILD_NUMBER}.
  • В одной стадии выведи env.WORKSPACE через echo (Groovy) и через sh с $WORKSPACE - убедись, что значения совпадают.
  • Заведи в Jenkins тестовый credential типа secret text и достань его через credentials(). Проверь, что в логе он замаскирован звездочками.
  • Бонус: перепиши docker-стадию на agent { kubernetes { yaml ... } }, если есть доступ к кластеру, и оберни шаг в container().
Контрольные вопросы
  • Чем отличается обращение к переменной как ${env.NAME} от ${NAME}, и в каком контексте работает каждое?
  • Сколько переменных и с какими суффиксами создаст credentials() для секрета типа "username with password"?
  • Что произойдет, если на уровне pipeline стоит agent none, а внутри pipeline остался блок steps?
  • Зачем в kubernetes-агенте нужен шаг container() и что будет, если его не указать?
Итог

agent отвечает за "где" (узел по метке, контейнер docker, эфемерный pod в Kubernetes), environment - за "с чем" (переменные, встроенные jenkins env и секреты через credentials). Держи в голове разницу между Groovy- и shell-интерполяцией, не хардкодь пароли и помни, что локальный agent перекрывает глобальный. Этих двух директив хватает, чтобы пайплайн стал предсказуемым и переносимым, а не магией, которая работает только на одной машине.
👍5 ❤️3 🔥3 😄 🤔
Аватара пользователя
rgcc
Сообщения: 1
Зарегистрирован: 18 май 2026, 22:43

Re: agent, environment и переменные в конвейере

Сообщение rgcc »

Спасибо, наконец дошло про одинарные и двойные кавычки в sh. У меня как раз ${env.TAG} в одинарных не подставлялся, переписал на $TAG - заработало.
👍1 ❤️1 🔥 😄 🤔
Аватара пользователя
fwdann
Сообщения: 1
Зарегистрирован: 17 май 2026, 17:43

Re: agent, environment и переменные в конвейере

Сообщение fwdann »

Вопрос по credentials: а если у меня secret file, а не текст или логин-пароль? Туда тоже три переменные кладет или путь к файлу прилетает?
👍 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Декларативный конвейер: структура pipeline, agent, stages
Следующая глава →
tools, options, parameters и triggers в декларативном конвейере

Все главы курса «Jenkins: конвейеры CI/CD от основ до продакшена»

Поделиться темой: ✈ Telegram VK
Похожие запросы: что такое jenkins простыми словамиjenkinsfile declarative или scripted что выбратьgroovy в jenkins scripted pipeline как написатьjenkins shared library как создать и подключитьпараметры и параллельные стейджи в jenkins pipelineструктура declarative pipeline в jenkins: stages, agent, steps

Вернуться в «Jenkins: конвейеры CI/CD от основ до продакшена»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость