jenkins в docker in mesos in
TRANSCRIPT
Jenkins Cloud Jenkins in Docker in Mesos in...
@tolkv
2
@lavcraft
Jenkins Cloud
● Amazon EC2
Jenkins Cloud
● Amazon EC2● Eucalyptus
Jenkins Cloud
● Amazon EC2● Eucalyptus● Docker● Mesos
Jenkins Cloud
● Amazon EC2● Eucalyptus● Docker● Mesos
Jenkins Cloud
● Amazon EC2● Eucalyptus● Docker● Mesos
Что дает:
● Jenkins Master в каждый дом(проект)● Shared Slaves● = Jenkins as a Service
Предпосылки
● Jenkins Master – не самый стабильный
Предпосылки
● Jenkins Master – не самый стабильный● Каждый хочет установить свой плагин
Предпосылки
● Jenkins Master – не самый стабильный● Каждый хочет установить свой плагин● И настроить “правильно”
Предпосылки
● Jenkins Master – не самый стабильный● Каждый хочет установить свой плагин● И настроить “правильно”● И вообще сделать всео “по уму”
Хитрость
● Гды вы запускаете Jenkins?
Хитрость
● Гды вы запускаете Jenkins?● На каких серверах запускать jenkins slave?
Проект $
Ресурсы на проект
Prod
App1
App2
App3
Db1
Db2
Db3
Проект $
Ресурсы на проект
Prod
App1
App2
App3
Db1
Db2
Db3
Dev
App1
App2
Db1
Проект $
Ресурсы на проект
Prod
App1
App2
App3
Db1
Db2
Db3
Dev
App1
App2
Db1
Infra
Mon1
Mon2
Проект $
Ресурсы на проект
Prod Dev Infra
Mon1
Mon2
Проект $
Ресурсы на проект
Prod Dev Infra
Mon1
Mon2
Jenkins Resources
Проект $
Ресурсы на проект
Prod Dev Infra
Mon1
Mon2
Jenkins Resources
Хитрость
● Гды вы запускаете Jenkins?● На каких серверах запускать jenkins slave?● А почему бы не запускать билды на разработческих стендах?
С чего начать
* Что каждый может сделать придя домой
ПодходыРаш
ПодходыРациональный подход
Подходы
VS
Подходы
Подходы
Что имеется
● Docker
Что имеется
● Docker● Mesos
Что имеется
● Docker● Mesos● Maratrhon
Что имеется
● Docker● Mesos● Maratrhon● zookeeper … ● …
Jenkins
Jenkins
Jenkins Master
Jenkins
Jenkins Master Jenkins Slave
Запихаем в Docker
Запихаем в Docker
● Уже есть оффициальный на docker hubhttps://hub.docker.com/_/jenkins/
● Отлично! Запускаем!docker run -p 8080:8080 -it jenkins
Запихаем в Docker
● Уже есть оффициальный на docker hubhttps://hub.docker.com/_/jenkins/
● Отлично! Запускаем!docker run -p 8080:8080 -it jenkins
● А как же плагины? Давайте разбираться!
Начнем с Docker
https://github.com/jenkinsci/docker/blob/master/README.md#preinstalling-plugins
DockerfileFROM jenkins:2.32.1
COPY plugins.txt /usr/share/jenkins/ref/RUN /usr/local/bin/plugins.sh /usr/share/jenkins/ref/plugins.txt
DockerfileFROM jenkins:2.32.1
COPY plugins.txt /usr/share/jenkins/ref/RUN /usr/local/bin/plugins.sh /usr/share/jenkins/ref/plugins.txt
Начнем с Docker
$ docker build .
Начнем с Docker
$ cat plugins.txt
handlebars:1.1.1icon-shim:2.0.3ivy:1.27.1jackson2-api:2.7.3javadoc:1.4jquery-detached:1.2.1junit:1.19ldap:1.14mailer:1.18mapdb-api:1.0.9.0marathon:1.4.0matrix-auth:1.4matrix-project:1.8maven-plugin:2.14mesos:0.14.0metrics:3.1.2.9momentjs:1.1.1pam-auth:1.3pipeline-build-step:2.4pipeline-graph-analysis:1.3pipeline-input-step:2.5pipeline-milestone-step:1.3pipeline-rest-api:2.4pipeline-stage-step:2.2pipeline-stage-view:2.4plain-credentials:1.3resource-disposer:0.6scm-api:1.3script-security:1.25ssh-credentials:1.12ssh-slaves:1.13structs:1.5subversion:2.7.1timestamper:1.8.8token-macro:2.0windows-slaves:1.2workflow-aggregator:2.4workflow-api:2.8workflow-basic-steps:2.3workflow-cps-global-lib:2.5workflow-cps:2.24workflow-durable-task-step:2.8workflow-job:2.9workflow-multibranch:2.9.2workflow-scm-step:2.3workflow-step-api:2.7workflow-support:2.12ws-cleanup:0.32http_request:1.8.13
Где взять plugins.txt
$ cd $JENKINS_HOME/plugins
Где взять plugins.txt
$ cd $JENKINS_HOME/plugins$ tree├── <PLUGIN_NAME>│ ├── META-INF│ │ ├── MANIFEST.MF
Где взять plugins.txt
$ cd $JENKINS_HOME/plugins$ tree├── <PLUGIN_NAME>│ ├── META-INF│ │ ├── MANIFEST.MF
Где взять plugins.txt
$ cd $JENKINS_HOME/plugins$ tree├── <PLUGIN_NAME>│ ├── META-INF│ │ ├── MANIFEST.MF$ cat <PLUGIN_NAME>/META-INF/MANIFEST.MF
Где взять plugins.txt
$ cd $JENKINS_HOME/plugins$ tree├── <PLUGIN_NAME>│ ├── META-INF│ │ ├── MANIFEST.MF$ cat <PLUGIN_NAME>/META-INF/MANIFEST.MF
Manifest-Version: 1.0Archiver-Version: Plexus ArchiverUrl: https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+API+PluginPlugin-Version: 2.8…
Где взять plugins.txt
$ cd $JENKINS_HOME/plugins$ tree├── <PLUGIN_NAME>│ ├── META-INF│ │ ├── MANIFEST.MF$ cat <PLUGIN_NAME>/META-INF/MANIFEST.MF
Manifest-Version: 1.0Archiver-Version: Plexus ArchiverUrl: https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+API+PluginPlugin-Version: 2.8…
Где взять plugins.txt
for i in `MANIFEST.MF for all plugins`;do
done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do
done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do # Plugin-Version: 2.8 v=EXTRACT VERSION FROM FILE <plugin>/META-INF/MANIFEST.MFdone
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do # Plugin-Version: 2.8 v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' ');done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do # Plugin-Version: 2.8 v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' ');done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do # Plugin-Version: 2.8 v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' ');done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do # Plugin-Version: 2.8 v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' ');done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' '); # $i = ./workflow-api/META-INF/MANIFEST.MFdone
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' '); # ./workflow-api/META-INF/MANIFEST.MF mod=EXTRACT PLUGIN NAMEdone
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' '); # ./workflow-api/META-INF/MANIFEST.MF mod=$(echo $i | cut -d'/' -f2); done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' '); # ./workflow-api/META-INF/MANIFEST.MF mod=$(echo $i | cut -d'/' -f2); done
Где взять plugins.txt
for i in `find -d $JENKINS_HOME/plugins -name "MANIFEST.MF"̀ ;do v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' '); mod=$(echo $i | cut -d'/' -f2); done
Где взять plugins.txt
cd $JENKINS_HOME/plugins
for i in `find -d . -name "MANIFEST.MF"̀ ;do v=$(cat $i| grep Plugin-Ver | cut -d':' -f2 | tr -d ' '); mod=$(echo $i | cut -d'/' -f2); echo $mod:$v; # pluginname:versiondone
Инициализируем jenkins_home
● Запускаем Jenkins и монтируем JENKINS_HOMEdocker run \
$PWD/jenkins_home:/var/jenkins_home \-p 8080:8080 \
-it jenkins● Теперь у нас в jenkins_home все нужные плагины
Теперь у нас есть jenkins в Docker?
НЕТТеперь у нас есть jenkins в Docker?
Задеплоим Jenkins-Master
Mesos + Marathon + Marathon-LB
Деплоим Jenkins
Marathon Manifest [Json]
Jenkins Master
Деплоим Jenkins
Marathon Manifest [Json]
Jenkins Master
POST
Деплоим Jenkins
Marathon Manifest [Json]
Jenkins Master
POST EVENT
Reload
Деплоим Jenkins
Marathon Manifest [Json]
Jenkins Master
POST EVENT
Reload
ANNOUNCE
Деплоим Jenkins
Marathon Manifest [Json]
Jenkins Master
POST EVENT
Reload
ANNOUNCE
OPEN UI
Деплоим Jenkins
Marathon Manifest [Json]
Jenkins Master
{"id": "/my_project/jenkins", "cmd": "...", "cpus": 2, "mem": 2048, "instances": 1, "container": { "type": "DOCKER", "docker": { "image": "docker.moscow.alfaintra.net/jenkins:2.32.1-mesos", } }, "healthChecks": [ { "path": "/proxy/raw/jenkins/passport/login", "protocol": "HTTP", "portIndex": 0, ... } ], "portDefinitions": [ { "port": 11102, "protocol": "tcp", "name": "jenkinshttp", },{ "port": 11103, "protocol": "tcp", "name": "jenkinsjnlp", "labels": {} }, { "port": 11104, "protocol": "tcp", "name": "mesoslibprocess", "labels": {} } ] }
Публикуем по http
Marathon Manifest [Json]
Jenkins Master
{"id": "/my_project/jenkins", ... "labels": { "HAPROXY_DEPLOYMENT_GROUP": "cd_my_project_jenkins", "HAPROXY_GROUP": "cd_my_project_jenkins", "HAPROXY_0_PATH": "/proxy/raw/jenkins/my_project", "HAPROXY_0_VHOST": "my_project.jenkins.cd" },
…}
Marathon LB
Marathon Manifest [Json]
Jenkins Master
{"id": "/my_project/jenkins", ... "labels": { "HAPROXY_DEPLOYMENT_GROUP": "cd_my_project_jenkins", "HAPROXY_GROUP": "cd_my_project_jenkins", "HAPROXY_0_PATH": "/proxy/raw/jenkins/my_project", "HAPROXY_0_VHOST": "my_project.jenkins.cd" "HAPROXY_0_HTTP_FRONTEND_ACL_WITH_PATH": " acl host_{cleanedUpHostname} hdr(host) -i {hostname}\n acl path_{backend} path_beg {path}\n use_backend {backend} if path_{backend}\n", },
…}
Marathon
Marathon Manifest [Json]
Jenkins Master
Marathon
Marathon Manifest [Json]
Jenkins Master
Открываем
● VHOST + PATH если есть DNS
Открываем
● VHOST + PATH если есть DNS● Иначе кастомизируем Haproxy acl для варианта только с PATH
Открываем
● VHOST + PATH если есть DNS● Иначе кастомизируем Haproxy acl для варианта только с PATH● curl http://jenkins.my_project.mesosdev/● curl http://any_nodehostname/proxy/raw/jenkins/my_project
Открываем
● VHOST + PATH если есть DNS● Иначе кастомизируем Haproxy acl для варианта только с PATH● curl http://jenkins.my_project.mesosdev/● curl http://any_nodehostname/proxy/raw/jenkins/my_project
Открываем
● VHOST + PATH если есть DNS● Иначе кастомизируем Haproxy acl для варианта только с PATH● curl http://jenkins.my_project.mesosdev/● curl http://any_nodehostname/proxy/raw/jenkins/my_project● Jenkins не поддерживает X-Forwarded
ну или у меня не получилось завести...
Открываем
● VHOST + PATH если есть DNS● Иначе кастомизируем Haproxy acl для варианта только с PATH● curl http://jenkins.my_project.mesosdev/● curl http://any_nodehostname/proxy/raw/jenkins/my_project● Jenkins не поддерживает X-Forwarded
ну или у меня не получилось завести...● см --prefix=/proxy/raw/jenkins/my_project
Проверим jenkins-mesos плагин
Jenkins Mesos Plugin$JENKINS_URL/manage → $JENKINS_URL/configure
Jenkins Mesos Plugin$JENKINS_URL/manage → $JENKINS_URL/configure
→
Jenkins Mesos Plugin$JENKINS_URL/manage → $JENKINS_URL/configure
→
Mesos Hostname
Mesos native library path
APPLY
Не найден mesos.so
APPLY
Как это должно работать?
Jenkins Master
JenkinsSlaveJenkins
SlaveJenkinsSlaveJenkins
Slave
Как это должно работать?
MesosMaster
AgentAgent
AgentAgentJenkins
Master
JenkinsSlaveJenkins
SlaveJenkinsSlaveJenkins
Slave
Как это должно работать?
MesosMaster
AgentAgent
AgentAgentJenkins
Master
JenkinsSlaveJenkins
SlaveJenkinsSlaveJenkins
Slave
Как это должно работать?
Как это должно работать?
Jenkins Master
MesosMaster
MesosMasterMesos
Master
AgentAgent
AgentAgent
JenkinsSlave
Mesos Native
$ docker build .
DockerfileFROM jenkins:2.32.1
ARG MESOS_VERSIONARG MESOS_VERSION_DEBENV MESOS_VERSION ${MESOS_VERSION:-1.1.0}ENV MESOS_VERSION_DEB ${MESOS_VERSION_DEB:-2.0.107.debian81}ENV TMP_DIR=/tmp/mesos
USER rootRUN apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF && \ echo "deb http://repos.mesosphere.com/debian jessie main" > /etc/apt/sources.list.d/mesosphere.list && \ apt-get update && \ apt-get install -y --no-install-recommends mesos=$MESOS_VERSION-$MESOS_VERSION_DEB && \ rm -rf /var/lib/apt/lists/*USER jenkins
COPY plugins.txt /usr/share/jenkins/ref/RUN /usr/local/bin/plugins.sh /usr/share/jenkins/ref/plugins.txt
Mesos NativeDockerfileFROM jenkins:2.32.1
...
USER rootRUN apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF && \ echo "deb http://repos.mesosphere.com/debian jessie main" > /etc/apt/sources.list.d/mesosphere.list && \ apt-get update && \ apt-get install -y --no-install-recommends \ mesos=$MESOS_VERSION-$MESOS_VERSION_DEB && \ rm -rf /var/lib/apt/lists/*USER jenkins
COPY plugins.txt /usr/share/jenkins/ref/RUN /usr/local/bin/plugins.sh /usr/share/jenkins/ref/plugins.txt
$ docker build .
Что там в Mesos?
Что там в Mesos?
Что там в Mesos?
Что там в Mesos?
Mesos Hostname
Specifies the hostname:port of the Mesos master.
● node1:zk_port,node2:zk_port,node3:zk_port
Mesos Hostname
Specifies the hostname:port of the Mesos master.
● node1:zk_port,node2:zk_port,node3:zk_port● http://node1:2181/api/v1/scheduler
Mesos Hostname
Specifies the hostname:port of the Mesos master.
● node1:zk_port,node2:zk_port,node3:zk_port● http://node1:2181/api/v1/scheduler ● zk://node1:2181,node2:2181,node3:2181
Mesos Hostname
Specifies the hostname:port of the Mesos master.
● node1:zk_port,node2:zk_port,node3:zk_port● http://node1:2181/api/v1/scheduler ● zk://node1:2181,node2:2181,node3:2181● zk://node1:2181,node2:2181,node3:2181/mesos
Mesos Hostname
Specifies the hostname:port of the Mesos master.
● node1:zk_port,node2:zk_port,node3:zk_port● http://node1:2181/api/v1/scheduler ● zk://node1:2181,node2:2181,node3:2181● zk://node1:2181,node2:2181,node3:2181/mesos
А теперь что в Mesos?
А теперь что в Mesos?
А теперь что в Mesos?
Разберемся
Разберемся
CLI
JNLP
HTTP
MESOS
Jenkins in Docker
Разберемся
CLI_PORT
JNLP_PORT
HTTP_PORT
CLI_ADVERTIZED_PORT
MESOS_PORT
HTTP_ADVERTIZED_PORT
JNLP_ADVERTIZED_PORT
MESOS_ADVERTIZED_PORT
Внутри контейнера
Внутренние порты Внешние
порты
Jenkins in Docker
Во вне
Как лечим
● -Dhudson.TcpSlaveAgentListener.port=$PORT1
● JENKINS_SLAVE_AGENT_PORT=$PORT1
● --httpPort=$PORT0
Разберемся
CLI_ADVERTIZED_PORT
HTTP_ADVERTIZED_PORT
JNLP_ADVERTIZED_PORT
MESOS_ADVERTIZED_PORT
Внутренние порты Внешние
порты
Jenkins in Docker
MesosMaster
LIBPROCESS_ADVERTIZED_PORTLIBPROCESS_ADVERTIZED_IP
CL_PORT
JNLP_PORT
HTTP_PORT
CLI_ADVERTIZED_PORT
MESOS_PORT
HTTP_ADVERTIZED_PORT
JNLP_ADVERTIZED_PORT
MESOS_ADVERTIZED_PORT
Внутри контейнера
Во вне
Как лечим
● -Dhudson.TcpSlaveAgentListener.port=$PORT1
● JENKINS_SLAVE_AGENT_PORT=$PORT1
● --httpPort=$PORT0
● LIBPROCESS_PORT=$PORT2
Как лечим
● -Dhudson.TcpSlaveAgentListener.port=$PORT1
● JENKINS_SLAVE_AGENT_PORT=$PORT1
● --httpPort=$PORT0
● LIBPROCESS_PORT=$PORT2
Build Now
Что еще можно потюнить?
Соберём что нибудь
Набор инструментов
● Jenkins Tools○ M3○ Docker○ Gradle○ ...
Набор инструментов
● Jenkins Tools○ M3○ Docker○ Gradle○ …
● Docker image per task type
Jenkins Jobs. Pipeline
node('mesos-jendev'){...}
Jenkins Jobs. Pipeline
node('mesos-jendev'){...}
Название Jenkins Cloud
Jenkins Jobs. Pipeline. Custom image
node('mesos-jendev'){...}
node('mesos-jendev:jenkins-slave:java-with-curl'){...}
Название Jenkins Cloud в котором будет запущен таск
Название образа в котором будет запущен новый jenkins-slave
Jenkins Jobs. Pipeline. Dind Image
node('mesos-jendev:jenkins-slave:java-dind'){...}
Docker client конфликт версий
● Официальный dind образ для docker 1.12+
Docker client конфликт версий
● Официальный dind образ для docker 1.12+● Docker на сервере 1.10 – 1.12
Docker client конфликт версий
● Официальный dind образ для docker 1.12+● Docker на сервере 1.10 – 1.12● Клиент 1.12 не работает с сервером 1.10
Docker client конфликт версий
● Официальный dind образ для docker 1.12+● Docker на сервере 1.10 – 1.12● Клиент 1.12 не работает с сервером 1.10● Сделаем свой?
Docker client конфликт версий
● Официальный dind образ для docker 1.12+● Docker на сервере 1.10 – 1.12● Клиент 1.12 не работает с сервером 1.10● Сделаем свой?● Нет, обновим Docker
Jenkins Jobs. Pipeline. Custom image
node('mesos-jendev:jenkins-slave:java-with-curl'){ stage('fetch'){ checkout scm } stage('build'){
... }
}
node('mesos-jendev:jenkins-slave:java-with-curl'){ stage('fetch'){ checkout scm } stage('build'){ def server = Artifactory.server 'alfa-laboratory' def rtGradle = Artifactory.newGradleBuild() def buildInfo = Artifactory.newBuildInfo() rtGradle.run tasks: 'snapshot', buildInfo: buildInfo }}
Jenkins Jobs. Pipeline. Custom image
Jenkins Job in Mesos Cluster in Docker
Jenkins Slaves под нашим контролем
● jenkins home persistence – требует mesos 1.0.1 + (Incubating API)● работа с Network BRIDGE – боль
○ jenkins jnlp4 handshake○ advertized ports○ mesos LIBPROCESS
● build cache and incremental builds● gradle cache problems gradle/851● link to MESOS_SANDBOX from builds
Немного проблем
Резюме
● Jenkins`a стоит бояться● Jenkins Cloud для энтузиастов
Резюме
● Jenkins`a стоит бояться● Jenkins Cloud для энтузиастов● Подумайте 3 раза нужно ли вам это● Если не нужно не используйте
Резюме
● Jenkins`a стоит бояться● Jenkins Cloud для энтузиастов● Подумайте 3 раза нужно ли вам это● Если не нужно не используйте● Можно упороться и заставить работать Jenkins Cloud
node('mesos-jendev:jenkins-slave:java-with-httpie'){echo '1'deployTo()echo '5'
}@NonCpsdef deployTo() {
echo '2'isExistInCluster()echo '4'
}def isExistInCluster() {
echo '3'}
Pipeline прямиком из ада
Pipeline прямиком из ада> 1> 2> 3> 5> End Stage> End Pipline
node('mesos-jendev:jenkins-slave:java-with-httpie'){echo '1'deployTo()echo '5'
}@NonCpsdef deployTo() {
echo '2'isExistInCluster()echo '4' // < ---- SKIPED
}def isExistInCluster() {
echo '3'}
Pipeline прямиком из ада
Заходите на чайhttps://goo.gl/HjfOz5
QA