Статьи

Автоматизация настройки док-станции Jenkins

Дженкинс, безусловно, самый используемый инструмент CI / CD на рынке. Это неудивительно, так как он существует некоторое время, у него есть одно из крупнейших сообществ с открытым исходным кодом, у него есть корпоративная версия для тех, кто в ней нуждается, и его легко расширить, чтобы удовлетворить (почти) чьи-либо потребности.

Продукты, которые доминируют на рынке в течение многих лет, имеют тенденцию быть стабильными и очень многофункциональными. Дженкинс не исключение. Однако с возрастом появляются и недостатки. В случае с Jenkins, настройка автоматизации — это одна из тех вещей, которая может быть желательной. Если вам нужно, чтобы Jenkins выступил в качестве организатора вашей автоматизации и задач, вы обнаружите, что его легко использовать. Но если вам нужно автоматизировать сам Дженкинс, вы поймете, что это не так гладко, как вы ожидаете от современных инструментов. Тем не менее, установка Jenkins может быть автоматизирована, и мы рассмотрим одно из возможных решений.

Я не буду рассказывать обо всем, что мы можем сделать в рамках установки Дженкинса. На эту тему можно написать целую книгу. Вместо этого я попытаюсь показать вам, как выполнить два наиболее распространенных шага настройки. Мы автоматизируем установку плагинов Jenkins и настройку администратора. Если вам нужно добавить что-то еще, пожалуйста, напишите мне по электронной почте (вы найдете мою информацию на странице « О нас» ).

Давайте быстро пройдемся по целям, которые поставим перед нами.

Цели

Автоматизация — залог успеха любой софтверной компании. Поскольку я считаю, что каждая компания является компанией-разработчиком программного обеспечения (хотя некоторые до сих пор не знают об этом), мы можем сказать, что автоматизация является ключом для всех.

Я ожидаю, что вы используете Docker для запуска своих сервисов. Если нет, пожалуйста, пересмотрите свою стратегию. Он предоставляет так много преимуществ, что игнорирование его будет означать, что конкуренция захлестнет вас. Я не буду вдаваться в подробности, почему Докер великолепен. Вы, наверное, уже все это знаете.

Краткая версия целей, стоящих за автоматической установкой Jenkins, заключается в том, что мы не хотим ничего делать, кроме как запустить одну команду. Результатом должен быть полностью сконфигурированный мастер Jenkins, который мы можем умножить на столько экземпляров, сколько нам нужно. Докер через Swarm обеспечит отказоустойчивость, (вид) высокую доступность, а что нет.

Немного более длинная версия — мы хотим установить все необходимые плагины и создать хотя бы одного администратора. Это не значит, что вы не будете добавлять больше плагинов позже. Вы, вероятно, будете. Однако это не должно помешать нам предварительно установить те из них, которые чаще всего используются в вашей организации. Без хотя бы одного пользователя любой мог бы получить доступ к вашему мастеру Jenkins и, возможно, получить доступ ко всей вашей системе. Вероятно, нет необходимости обсуждать, почему мы должны этого избегать.

Прежде чем мы начнем работать над автоматизацией, мы запустим мастер Jenkins вручную и получим некоторую информацию, которая будет полезна позже.

Настройка Jenkins вручную

Мы начнем с создания службы Jenkins в кластере Swarm. Если у вас его нет, вы можете легко преобразовать Docker для Windows / Mac / Linux в кластер с одним узлом, выполнив docker swarm init .

W> Если вы пользователь Windows, пожалуйста, запустите все команды из Git Bash (установленного через Git ) или любого другого Bash, который у вас может быть.

1
2
docker service create --name jenkins \
    -p 8080:8080 jenkins

Через некоторое время образ jenkins будет извлечен, и служба будет запущена. Не стесняйтесь проверять статус, выполнив docker service ps jenkins .

Как только Jenkins запущен и работает, мы можем открыть его интерфейс в браузере.

Если вы не используете свой локальный движок Docker для Windows / Mac / Linux в качестве единственного узла в кластере, замените localhost на IP одного из ваших узлов Swarm.

Если вы пользователь Windows, Git Bash может не использовать команду open . Если это так, замените open на echo . В результате вы получите полный адрес, который должен быть открыт непосредственно в выбранном вами браузере.

Вы должны увидеть первый экран установки, где вы должны ввести пароль администратора . Он доступен в /var/jenkins_home/secrets/initialAdminPassword внутри контейнера, в котором размещается служба.

Если вы не используете свой локальный движок Docker для Windows / Mac / Linux в качестве единственного узла в кластере, пожалуйста, найдите узел, на котором работает служба, и SSH в нее, прежде чем выполнять следующие команды.

1
2
3
4
5
ID=$(docker container ls -q \
    -f "label=com.docker.swarm.service.name=jenkins")
 
docker container exec -it $ID \
    cat /var/jenkins_home/secrets/initialAdminPassword

Мы использовали команду docker container ls с фильтром, чтобы найти идентификатор контейнера, в котором размещается служба. Затем мы выполнили команду, которая отображала содержимое файла /var/jenkins_home/secrets/initialAdminPassword . Вывод будет варьироваться от одного исполнения к другому. В моем случае это так.

1
ecd46df9ec1b420dadacdb56de9492c8

Скопируйте пароль и вставьте его в поле « Пароль администратора» в пользовательском интерфейсе Jenkins и следуйте инструкциям по настройке мастера Jenkins. Выберите плагины, которые вам понадобятся. Когда вы дойдете до последнего экрана настройки, который называется Create First Admin User , пожалуйста, используйте admin как имя пользователя и пароль.

После завершения установки мы можем отправить запрос, который получит список всех установленных плагинов.

Прежде чем продолжить, пожалуйста, проверьте, установлен ли у вас jq . Если вы этого не сделаете, вы можете найти на его официальном сайте .

1
2
  | jq -r '.plugins[].shortName' | tee plugins.txt

Мы отправили запрос в API менеджера плагинов Jenkins и получили все плагины, которые мы установили во время ручной настройки. Мы передали результат в jq и отфильтровали его так, чтобы выводились только короткие имена. Результат сохраняется в файле plugins.txt .

Нам больше не нужен сервис Дженкинс. Он имеет только временную функцию, которая позволяет нам получить список плагинов, которые нам нужны. Давайте уничтожим это.

1
docker service rm jenkins

Создание образа Jenkins с автоматической настройкой

Прежде чем мы определим Dockerfile, который мы будем использовать для создания образа Jenkins с автоматической настройкой, нам нужно выяснить, как создать хотя бы одного административного пользователя. К сожалению, нет (достойного) API, который мы можем вызвать. Лучше всего выполнить Groovy-скрипт, который сделает эту работу. Сценарий заключается в следующем.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
#!groovy
 
import jenkins.model.*
import hudson.security.*
import jenkins.security.s2m.AdminWhitelistRule
 
def instance = Jenkins.getInstance()
 
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("admin", "admin")
instance.setSecurityRealm(hudsonRealm)
 
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
instance.save()
 
Jenkins.instance.getInjector().getInstance(AdminWhitelistRule.class).setMasterKillSwitch(false)

Ключ находится в hudsonRealm.createAccount("admin", "admin") . Он создает учетную запись с именем пользователя и паролем, установленными для admin .

Основная проблема этого сценария заключается в том, что в нем жестко прописаны учетные данные. Мы могли бы преобразовать их в переменные окружения, но это было бы очень небезопасно. Вместо этого мы будем использовать секреты Docker. При подключении к контейнеру секреты хранятся в каталоге /run/secrets в памяти.

Более безопасная (и гибкая) версия скрипта заключается в следующем.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
#!groovy
 
import jenkins.model.*
import hudson.security.*
import jenkins.security.s2m.AdminWhitelistRule
 
def instance = Jenkins.getInstance()
 
def user = new File("/run/secrets/jenkins-user").text.trim()
def pass = new File("/run/secrets/jenkins-pass").text.trim()
 
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount(user, pass)
instance.setSecurityRealm(hudsonRealm)
 
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
instance.save()
 
Jenkins.instance.getInjector().getInstance(AdminWhitelistRule.class).setMasterKillSwitch(false)

На этот раз мы поместили содержимое jenkins-user и jenkins-pass в переменные и использовали их для создания учетной записи.

Пожалуйста, сохраните скрипт как файл security.groovy .

Имея список плагинов, хранящихся в plugins.txt и скрипт, который создаст пользователя из секретов Docker, мы можем приступить к созданию Dockerfile.

Пожалуйста, создайте Dockerfile с содержанием, которое следует.

1
2
3
4
5
6
7
8
FROM jenkins:alpine
 
ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false"
 
COPY security.groovy /usr/share/jenkins/ref/init.groovy.d/security.groovy
 
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt

Изображение будет основано на alpine версии Jenkins, которая намного меньше и безопаснее других.

Мы использовали JAVA_OPTS чтобы отключить мастер настройки. Нам это не понадобится, поскольку наша установка будет полностью автоматизирована.

Затем мы копируем файл security.groovy в каталог /usr/share/jenkins/ref/init.groovy.d/ . При инициализации Jenkins выполнит все скрипты Groovy, расположенные в этом каталоге. Если вы создаете дополнительные сценарии установки, это место, где вы должны их разместить.

Наконец, мы plugins.txt файл plugins.txt , содержащий список всех необходимых нам плагинов, и передаем этот список в скрипт install-plugins.sh который является частью стандартного дистрибутива.

Dockerfile , мы можем создать наш образ и Dockerfile его в реестр Docker.

Пожалуйста, замените vfarcic вашим пользователем Docker Hub.

1
2
3
docker image build -t vfarcic/jenkins .
 
docker image push vfarcic/jenkins

Создав образ и отправив его в Реестр, мы, наконец, можем создать сервис Jenkins.

Создание службы Jenkins с автоматической настройкой

Мы должны создать Compose-файл, который будет содержать определение сервиса. Это так.

Пожалуйста, замените vfarcic вашим пользователем Docker Hub.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
version: '3.1'
 
services:
 
  main:
    image: vfarcic/jenkins
    ports:
      - 8080:8080
      - 50000:50000
    secrets:
      - jenkins-user
      - jenkins-pass
 
secrets:
  jenkins-user:
    external: true
  jenkins-pass:
    external: true

Сохраните определение как файл jenkins.yml .

Файл Compose очень прост. If определяет только один сервис ( main ) и использует вновь созданный образ. Он предоставляет порты 8080 для пользовательского интерфейса и 50000 для агентов. Наконец, он определяет jenkins-user и jenkins-pass .

Мы должны создать секреты перед развертыванием стека. Следующие команды будут использовать admin как имя пользователя и пароль. Не стесняйтесь изменить его на что-то менее очевидное.

1
2
3
echo "admin" | docker secret create jenkins-user -
 
echo "admin" | docker secret create jenkins-pass -

Теперь мы готовы развернуть стек.

1
docker stack deploy -c jenkins.yml jenkins

Через несколько секунд сервис будет запущен. Пожалуйста, подтвердите статус, выполнив docker stack ps jenkins .

Давайте подтвердим, что все работает как положено.

Вы заметите, что на этот раз нам не пришлось проходить через шаги мастера установки. Все автоматизировано и сервис готов к использованию. Не стесняйтесь войти и подтвердить, что указанный вами пользователь действительно создан.

Если вы создаете этот сервис в демонстрационной среде (например, на своем ноутбуке), сейчас самое время удалить его и освободить ресурсы для чего-то другого. Созданное вами изображение должно быть готово к производству.

1
2
3
4
5
docker stack rm jenkins
 
docker secret rm jenkins-user
 
docker secret rm jenkins-pass
Ссылка: Автоматизация настройки Jenkins Docker от нашего партнера JCG Виктора Фарсика в блоге технологических бесед .