Введение
Jenkins считается инструментом с открытым исходным кодом и сервером автоматизации конвейеров непрерывной интеграции и развертывания. Jenkins – написан на Java, и его можно установить на Ubuntu/Debian/CentOS и на разные дистрибутивы с помощью пакетного менеджера, который установлен на сервере или же из исходных файлов репозитория проекта.
Jenkins можно настроить вручную, как рассмотрено в нашей инструкции, либо можно установить в контейнере Docker, чтобы процесс работы в Jenkins не был медленным и был без ошибок. Если устанавливать Jenkins вручную, то некоторые конфигурации не отследить в системе контроля версий (VCS), такой как Git.
В этой инструкции мы рассмотрим установку и настройку Jenkins в контейнере Docker и рассмотрим метод «Конфигурация Jenkins как код» (JCasC).
Мы рассмотрим запуск своего экземпляра Jenkins с помощью Docker и воспользуемся преимуществами, в виде кроссплатформенности и согласованности.
В этой инструкции начнём с настройки JCasC и поэтапно будем добавлять в файл конфигурации JCasC настройку пользователей, аутентификацию и защиту нашего экземпляра Jenkins. После этой инструкции у нас будет собственный образ Docker, который настроен на использование подключаемого плагина JCasC для автоматической настройки и защиты экземпляра Jenkins.
Подготовка к работе
Для выполнения всех шагов в данной инструкции, необходимо развернуть собственный сервер на базе Debian/Ubuntu/CentOS, выбрать оперативную память минимально 2 GB. Установить Docker согласно нашей инструкции.
Отключение мастера установки
Использование JCasC избавляет от необходимости показывать мастер настройки, поэтому на первом этапе мы создадим модифицированную версию официального образа jenkins/jenkins, в которой мастер настройки будет отключен. Для этого нужно создать Dockerfile и собрать из него пользовательский образ Jenkins.
Образ jenkins/jenkins позволяет включить или отключить мастер установки, передав системное свойство jenkins.install.runSetupWizard через переменную окружения JAVA_OPTS. Пользователи образа могут передать переменную окружения JAVA_OPTS во время выполнения с помощью флага –env в docker run. Однако такой подход возлагает бремя отключения мастера установки на пользователя образа. Вместо этого следует отключать мастер установки во время сборки, чтобы он был отключен по умолчанию. Этого можно добиться, создав Dockerfile и используя инструкцию ENV для установки переменной окружения JAVA_OPTS.
Сначала создадим новый каталог внутри нашего сервера для хранения файлов, которые мы будем создавать в этом руководстве:
mkdir -p jenproject/jcasc
Перейдём в созданную директорию:
cd jenproject/jcasc
Создадим Docerfile с помощью nano/vim и добавим следующую конфигурацию:
FROM jenkins/jenkins:latest
ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false
FROM – указываем наш образ и версию
ENV (environment) – указываем среду JAVA_OPTS и в опции jenkins.install.runSetupWizard указываем параметр ЛОЖЬ (false) и отключаем мастер настройки. Сохраним файл и выполним выход. Необходимо находится в каталоге, где находится Dockerfile и запустить команду:
docker build -t jenkins:jcasc .
После запуска получим следующий результат:

Также можно посмотреть образ сборки с помощью:
docker images

Запустим наш образ в контейнере с помощью docker run и в конце указыважем ID образа:
docker run --name jenkins --rm -p 8080:8080 IMAGE_ID

Далее переходим в браузер и указываем IP-адрес сервера и порт 8080:
http://ip-address:8080

Мы только что убедились, что мастер настройки был отключен. Чтобы остановить контейнер, нажмите CTRL+C. Если вы ранее указали флаг –rm, остановленный контейнер будет автоматически удален.
В этом шаге мы создали пользовательский образ Jenkins, в котором отключен мастер настройки. Однако в правом верхнем углу веб-интерфейса теперь отображается красный значок уведомления, указывающий на наличие проблем с настройкой. Нажмите на значок, чтобы увидеть подробности:

Первое предупреждение информирует нас о том, что выполнение сборки на встроенном узле может быть небезопасно и ссылается на документацию. Ранее мастер настройки подсказывал нам, как решить эти проблемы. Теперь, когда мы отключили его, нам нужно воспроизвести те же функции с помощью JCasC. Остальная часть этого руководства включает в себя изменение вашего Dockerfile и конфигурации JCasC до тех пор, пока не останется никаких проблем (то есть пока не исчезнет красный значок уведомления).
На следующем этапе мы начнем этот процесс с предварительной установки ряда плагинов Jenkins, включая плагин Configuration as Code, в наш пользовательский образ Jenkins.
Установка плагинов Jenkins
Чтобы использовать JCasC, необходимо установить плагин Configuration as Code. В настоящее время плагины не установлены. Мы можем убедиться в этом, перейдя по адресу http://ip_address:8080/pluginManager/installed:

В этом шаге мы изменим свой Dockerfile для предварительной установки ряда плагинов, включая плагин Configuration as Code.
Чтобы автоматизировать процесс установки плагина, мы можем воспользоваться сценарием установки, который поставляется вместе с Docker-образом jenkins/jenkins. Мы можем найти его внутри контейнера по адресу /usr/local/bin/install-plugins.sh. Чтобы использовать его, мам нужно:
- создать текстовый файл, содержащий список плагинов для установки;
- скопировать его в образ Docker;
- запустить скрипт install-plugins.sh для установки плагинов.
Сначала с помощью редактора vim/nano создадим новый файл с именем plugins.txt:
vim jenproject/jcasc/plugins.txt
Затем добавим следующий список имен и версий плагинов, разделенных новой строкой (используя формат <id>:<version>):
ant:latest
antisamy-markup-formatter:latest
build-timeout:latest
cloudbees-folder:latest
configuration-as-code:latest
credentials-binding:latest
email-ext:latest
git:latest
github-branch-source:latest
gradle:latest
ldap:latest
mailer:latest
matrix-auth:latest
pam-auth:latest
pipeline-github-lib:latest
pipeline-stage-view:latest
ssh-slaves:latest
timestamper:latest
workflow-aggregator:latest
ws-cleanup:latest
Сохраним файл и выполним выход из редактора.
Список содержит плагин Configuration as Code, а также все плагины, предложенные мастером настройки. Например, у нас есть плагин Git, который позволяет Jenkins работать с репозиториями Git; у нас также есть плагин Pipeline, который на самом деле представляет собой набор плагинов, позволяющих определять задания Jenkins в виде кода.
Откроем наш Dockerfile и добавим изменения. В нем добавим конструкцию COPY, чтобы скопировать файл plugins.txt в каталог /usr/share/jenkins/ref/ внутри образа; именно там Jenkins обычно ищет плагины. Затем включим дополнительную конструкцию RUN для запуска сценария install-plugins.sh:
FROM jenkins/jenkins:latest
ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false
COPY --chown=jenkins:jenkins plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN jenkins-plugin-cli -f /usr/share/jenkins/ref/plugins.txt
Сохраним файл и выполним выход. Начнём сборку нашего образа с помощью команды:
docker build -t jenkins:jcasc .

Далее необходимо скопировать ID образа и запустить в контейнере.
docker images -a
docker run --name jenkins --rm -p 8080:8080 IMAGE_ID

Далее переходим по ссылке http://ip_address:8080/pluginManager/installed и увидим результат с установленными плагинами:

Убедившись, что плагин Configuration As Code установлен, завершим процесс контейнера, нажав CTRL+C.
В этом шаге мы установили все предложенные плагины Jenkins и плагин Configuration as Code. Теперь мы готовы использовать JCasC для решения проблем, перечисленных в окне уведомления. В следующем шаге мы устраним первую проблему, которая предупреждает нас о том, что корневой URL Jenkins пуст:

Настройка URL-адреса для Jenkins
URL-адрес Jenkins – это URL-адрес экземпляра Jenkins, который можно маршрутизировать с устройств, которым необходим доступ к нему. Например, если мы развертываем Jenkins как узел внутри частной сети, URL Jenkins может быть частным IP-адресом или DNS-именем, которое можно разрешить с помощью частного DNS-сервера. В данном руководстве для формирования URL Jenkins достаточно использовать IP-адрес сервера (или 127.0.0.1 для локальных узлов).
Мы можем задать URL Jenkins в веб-интерфейсе, перейдя по адресу ip_address:8080/configure и введя значение в поле Jenkins URL под заголовком Jenkins Location. Добиться того же самого с помощью плагина Configuration as Code:
- Определим желаемую конфигурацию нашего экземпляра Jenkins в декларативном конфигурационном файле (который мы назовем casc.yaml).
- Скопируем файл конфигурации в образ Docker (так же, как мы сделали это для файла plugins.txt).
- Установим переменную окружения CASC_JENKINS_CONFIG на путь к файлу конфигурации, чтобы указать плагину Configuration as Code прочитать его.
Для начала создадим файл casc.yml:
vim jenproject/jcasc/casc.yml
Добавим следующий кусок кода вместе с IP-адресом нашего сервера.
unclassified:
location:
url: http://ip_address:8080/
unclassified.location.url – это путь для установки URL-адреса Jenkins. Это лишь одно из огромного количества свойств, которые можно задать с помощью JCasC. Валидные свойства определяются установленными плагинами.
Например, свойство jenkins.authorizationStrategy.globalMatrix.permissions будет действительным, только если установлен плагин Matrix Authorization Strategy. Чтобы узнать, какие свойства доступны, перейдите по адресу ip_address:8080/configuration-as-code/reference, и вы найдете страницу документации, настроенной на вашу конкретную установку Jenkins.
Сохраним код и откроем Dockerfile. Добавим конструкцию COPY в конец, которая копирует файл casc.yaml в образ по адресу /var/jenkins_home/casc.yaml. Мы выбрали /var/jenkins_home/, потому что это каталог по умолчанию, в котором Jenkins хранит все свои данные. Затем добавим еще одну конструкцию ENV, которая устанавливает переменную окружения CASC_JENKINS_CONFIG:
FROM jenkins/jenkins:latest
ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false
ENV CASC_JENKINS_CONFIG /var/jenkins_home/casc.yaml
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
COPY casc.yaml /var/jenkins_home/casc.yaml
Сохраним файл и запустим сборку образа:
ocker build -t jenkins:jcasc .
Запустим наш образ в контейнере:
docker images
docker run --name jenkins --rm -p 8080:8080 IMAGE_ID
Перейдем на ip_address:8080, чтобы просмотреть панель инструментов. На этот раз мы, заметили, что количество уведомлений уменьшилось на единицу, а предупреждение об URL-адресе Jenkins исчезло:

Теперь перейдем по адресу ip_address:8080/configure и прокрутим вниз до поля Jenkins URL. Убедимся, что URL Jenkins был установлен на то же значение, которое указано в файле casc.yaml:

Наконец, остановим процесс контейнера, нажав CTRL+C.
В этом шаге мы использовали плагин Configuration as Code для установки URL Jenkins. В следующем шаге мы решим второе предупреждение из списка уведомлений (Незащищенный Jenkins позволяет каждому, у кого есть доступ к сети).
Настройка авторизации
Первая проблема в списке уведомлений связана с аутентификацией сборки. По умолчанию все задания запускаются от имени системного пользователя, который имеет много системных привилегий. Поэтому пользователь Jenkins может выполнить повышение привилегий, просто определив и запустив вредоносное задание или конвейер, это небезопасно.
Вместо этого задания должны запускаться тем же пользователем Jenkins, который их сконфигурировал или запустил. Для этого необходимо установить дополнительный плагин Authorize Project.
Откройте файл plugins.txt и внесите следующую строку:
authorize-project:latest
Плагин предоставляет новую стратегию авторизации сборки, которую нам нужно будет указать в конфигурации JCasC. Выполним выход из файла plugins.txt и откроем файл casc.yaml и добавим следующую конфигурацию:
jenkins:
securityRealm:
local:
allowsSignup: false
users:
- id: ${JENKINS_ADMIN_ID}
password: ${JENKINS_ADMIN_PASSWORD}
authorizationStrategy:
globalMatrix:
permissions:
- "Overall/Administer:admin"
- "Overall/Read:authenticated"
remotingSecurity:
enabled: true
security:
queueItemAuthenticator:
authenticators:
- global:
strategy: triggeringUsersAuthorizationStrategy
unclassified:
Сохраним файл и запустим сборку образа:
docker build -t jenkins:jcasc .
Запустим образ в контейнере:
docker images
docker run --name jenkins --rm -p 8080:8080 --env JENKINS_ADMIN_ID=admin --env JENKINS_ADMIN_PASSWORD=serverspace IMAGE_ID
Дождемся появления строки журнала «Jenkins is fully up and running», затем перейдем по адресу ip_address:8080/login, укажем логин и пароль и будем перенаправлены на главную панелей инструментов. Откроем уведомления, и увидим, что проблемы отсутствуют из-за строк в файле casc.yml:
remotingSecurity:
enabled: true

Рисунок 14 – Отсутствие предупреждений
Выводы
Теперь мы успешно настроили простой сервер Jenkins с помощью JCasC. Подобно тому, как плагин Pipeline позволяет разработчикам определять свои задания внутри Jenkinsfile, плагин Configuration as Code позволяет администраторам определять конфигурацию Jenkins внутри YAML-файла. Оба этих плагина приближают Jenkins к парадигме Everything as Code (EaC).
Однако правильное понимание синтаксиса JCasC может быть затруднено, а документацию трудно расшифровать. Если вы застряли и вам нужна помощь, вы можете найти ее в чате Gitter для этого плагина.
Хотя мы настроили основные параметры Jenkins с помощью JCasC, новый экземпляр не содержит никаких проектов или заданий. Чтобы пойти еще дальше, изучите плагин Job DSL, который позволяет вам определять проекты и задания в виде кода. Более того, вы можете включить код Job DSL в конфигурационный файл JCasC, и проекты и задания будут созданы в процессе конфигурирования.