Jenkins: JNLP-slave из Docker-образа

Автор: | 21/01/2019
 

Имеется у нас зоопарк билд-агентов (macOS, Ubuntu), работающих в офисе.

Сам Jenkins при этом запущен в AWS, на ЕС2, и обращается к агентам через проброс SSH-портов на офисном роутере.

Задача – перенастроить схему, что бы агенты сами обращались к Jenkins, и, таким образом, отказаться от пробоса портов. Сесурити и вот это вот всё.

Простой пример запуска через JNLP (Java Network Launch Protocol) можно посмотреть в посте Jenkins: macOS slave агент через Java Web Start, а сегодня мы запустим аналогичный агент, но из Docker Compose, используя Jenkins JNLP Agent Docker image.

Создаём новый агент. Можно скопировать из существующего (android-агент – это нынешний, запущенный через SSH):

Добавление агента

В Launch method переключаем Launch agent agents via SSH на Launch agent via Java Web Start:

Агент готов, но ещё не запущен:

Jenkins slave Docker

На билд-агенте устанавливаем Docker и Docker Compose:

[simterm]

root@projectname-ci:~# curl -L http://get.docker.com | bash
root@projectname-ci:~# curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
root@projectname-ci:~# chmod +x /usr/local/bin/docker-compose

[/simterm]

Создаём каталог для билдов:

[simterm]

root@projectname-ci:~# mkdir /home/projectname/android_jnlp

[/simterm]

Создаём Compose-файл, например jenkins-slave.yml:

version: '3.3'

services:

  jenkins-slave:
    image: jenkins/jnlp-slave
    environment:
      - JENKINS_URL=https://ci.projectname.world
      - JENKINS_SECRET=550***aca
      - JENKINS_AGENT_NAME=android_jnlp
      - JENKINS_AGENT_WORKDIR=/home/projectname-ci/
    volumes:
      - /home/projectname/android_jnlp:/home/projectname/
    restart: unless-stopped

Проверяем доступность порта 50000 на мастере:

[simterm]

root@projectname-ci:~# telnet ci.projectname.world 50000
Trying 34.***.***.92...
Connected to ci.projectname.world.
Escape character is '^]'.

[/simterm]

Запускаем новый слейв:

[simterm]

root@projectname-ci:~# docker-compose -f jenkins-slave.yml up
projectname_jenkins-slave_1 is up-to-date
Attaching to projectname_jenkins-slave_1
...
jenkins-slave_1  | INFO: Agent discovery successful
jenkins-slave_1  |   Agent address: ci.projectname.world
jenkins-slave_1  |   Agent port:    50000
jenkins-slave_1  |   Identity:      e2:ab:7f:f5:45:53:30:04:b0:1e:fe:d1:59:7e:49:f3
jenkins-slave_1  | Jan 21, 2019 10:54:57 AM hudson.remoting.jnlp.Main$CuiListener status
jenkins-slave_1  | INFO: Handshaking
jenkins-slave_1  | Jan 21, 2019 10:54:57 AM hudson.remoting.jnlp.Main$CuiListener status
jenkins-slave_1  | INFO: Connecting to ci.projectname.world:50000
jenkins-slave_1  | Jan 21, 2019 10:54:57 AM hudson.remoting.jnlp.Main$CuiListener status
jenkins-slave_1  | INFO: Trying protocol: JNLP4-connect
jenkins-slave_1  | Jan 21, 2019 10:54:58 AM hudson.remoting.jnlp.Main$CuiListener status
jenkins-slave_1  | INFO: Remote identity confirmed: e2:ab:7f:f5:45:53:30:04:b0:1e:fe:d1:59:7e:49:f3
jenkins-slave_1  | Jan 21, 2019 10:54:58 AM hudson.remoting.jnlp.Main$CuiListener status
jenkins-slave_1  | INFO: Connected

[/simterm]

Проверяем на мастере:

systemd

И последний шаг – добавить systemd-файл для управления агентом.

Создаём файл /etc/systemd/system/jenkins-slave.service:

[Unit]
Description=Jenkins CI slave agent
Requires=docker.service
After=docker.service

[Service]
Restart=always
WorkingDirectory=/home/projectname-ci/

# Compose up
ExecStart=/usr/local/bin/docker-compose -f jenkins-slave.yml up

# Compose down, remove containers and volumes
ExecStop=/usr/local/bin/docker-compose -f jenkins-slave.yml down -v

[Install]
WantedBy=multi-user.target

Запускаем:

[simterm]

root@projectname-ci:~# systemctl start jenkins-slave

[/simterm]

Проверяем:

[simterm]

root@projectname-ci:~# systemctl status jenkins-slave
● jenkins-slave.service - Jenkins CI slave agent
   Loaded: loaded (/etc/systemd/system/jenkins-slave.service; disabled; vendor preset: enabled)
   Active: active (running) since пн 2019-01-21 13:01:02 EET; 4s ago
 Main PID: 4047 (docker-compose)
    Tasks: 4
   Memory: 47.4M
      CPU: 293ms
   CGroup: /system.slice/jenkins-slave.service
           ├─4047 /usr/local/bin/docker-compose -f jenkins-slave.yml up
           └─4055 /usr/local/bin/docker-compose -f jenkins-slave.yml up

січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:04 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Handshaking
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:04 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Connecting to ci.projectname.world:50000
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:04 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Trying protocol: JNLP4-connect
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:05 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Remote identity confirmed: e2:ab:7f:f5:45:53:30:04:b0:1e:fe:d1:59:7e:49:f3
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:05 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Connected

[/simterm]

Логи можно смотреть с помощью journalctl:

[simterm]

root@projectname-ci:~# journalctl -u jenkins-slave -f
-- Logs begin at ср 2019-01-09 15:13:52 EET. --
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:04 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Handshaking
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:04 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Connecting to ci.projectname.world:50000
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:04 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:04 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Trying protocol: JNLP4-connect
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:05 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Remote identity confirmed: e2:ab:7f:f5:45:53:30:04:b0:1e:fe:d1:59:7e:49:f3
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | Jan 21, 2019 11:01:05 AM hudson.remoting.jnlp.Main$CuiListener status
січ 21 13:01:05 projectname-ci docker-compose[4047]: jenkins-slave_1  | INFO: Connected

[/simterm]

Готово.