Jenkins в docker in mesos in ...

Post on 20-Mar-2017

103 views 4 download

Transcript of Jenkins в docker in mesos in ...

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