针对Kubernetes和Docker Workflow Plugin的Jenkins配置

简介: 本文讲的是针对Kubernetes和Docker Workflow Plugin的Jenkins配置,【编者的话】Jenkins作为一款开源的持续集成工具,在很多平台上被使用,本文主要介绍了在Kubernetes和Docker Workflow Plugin中的一些配置,可以帮助读者了解到其中的一些细节和方法。
本文讲的是针对Kubernetes和Docker Workflow Plugin的Jenkins配置 【编者的话】Jenkins作为一款开源的持续集成工具,在很多平台上被使用,本文主要介绍了在Kubernetes和Docker Workflow Plugin中的一些配置,可以帮助读者了解到其中的一些细节和方法。

最近我开始尝试在 Kubernetes 中使用 Jenkins ,其实我也是想看看如何可以更好地运行  Docker Workflow插件

我的思路是有一个可以运行Jenkins的Pod,并用它来运行通过 Docker Workflow插件 定义的构建。经过大量阅读和多次反复的实验,我发现有很多种方法来实现这一想法,当然这些方法各有不同的利弊。

这篇文章讨论了所有可用的方法,具体来讲:
  1. 直接在Master上运行构建
  2. 使用Docker插件启动Slaves
  3. 使用Docker插件以及Docker in Docker
  4. 使用Swarm客户端
  5. 使用Docker in DockerSwarm

在我阐述所有可能的配置之前,我觉得先来描述一下所有的这些插件是什么会对大家很有帮助。

Docker Plugin

一个使用了 Docker Jenkins 插件,用以创建和使用slaves,它使用HTTP协议来与 Docker 通信并生成新的容器。这些容器只需支持Java并且可以运行SSHD,以便master可以通过SSH连接到容器内并施展它的魔力。网络上有许多slave容器的镜像,在我重新连接时最流行的镜像是 evarga jenkins slave

这个插件很不错但是让人感觉有点不可靠,虽然它可以创建Docker容器,但是有时候它却无法连接到slave并且会重试(往往会重试两三次),它会以相似的方法,使用很多不同的身份验证方法(密码、密钥验证等)尝试连接很多不同的slave镜像。

Swarm

生成slaves的一种方法是使用插件。另外一种方法是“建立自己的slaves”,这几乎就是Swarm的思想所在。这种思想指的是Jenkins master来运行Swarm插件,用户负责启动 Swarm 客户端(它仅仅是个Java进程)。
java -jar /path/to/swarm-client.jar http://jenkins.master:8080

客户端连接到master机器并且让master知道客户端已经启动并且运行。然后master就能够在客户端开始构建。

Docker Workflow插件

这个插件允许你在工作流脚本中使用Docker镜像和容器,或者换句话说,此插件允许你在Docker容器中执行工作流步骤并且可以从工作流脚本中生成Docker。

为了概括一下在Docker镜像中你的构建的所有需求并且让你无须担心如何安装和配置它们,下面给出一个Docker Workflow脚本的例子:
node('docker') {
docker.image('maven').inside {
  git 'https://github.com/fabric8io/example-camel-cdi'
  sh 'mvn clean install'
 }
} 

注意 :你无需在 Docker Workflow Plugin 中使用 Docker Plugin

另外 :Docker Workflow Plugin使用的是Docker二进制,这就意味着无论你在何处想要使用Docker Workflow插件,你都必须安装Docker客户端。

差点忘了 :构建的“执行器”和参与工作流的容器需要共享项目工作空间,这里我就不赘述了。只需记住,在Docker主机(或是一些缺少共享文件系统的主机)中,通常需要访问Docker host上的特定路径。无法满足这个需求会导致一些“难以监测”的问题比如构建永久悬挂等。

现在我们已经准备好了,让我们来一探究竟这些可能的设置是什么。

不涉及slaves

这是最简单的方法,它不会涉及 Jenkins  slaves,通过配置一系列固定的执行器,构建就可以直接运行在master上。

因为没有slaves,所以运行Jenkins的容器自身需要安装和配置Docker二进制文件来指向真正的Docker host。

如何在Kubernetes中使用Docker Host?

这里给出两种方法:
  1. 使用Kubernetes API
  2. 通过挂载 /var/run/docker.sock

你可以(1)通过使用一个简单的shell脚本,如下:
#!/bin/bash
KUBERNETES=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
TOKEN=`cat /var/run/secrets/kubernetes.io/serviceaccount/token`
POD=`hostname`
curl -s -k -H "Authorization: Bearer $TOKEN" $KUBERNETES/api/v1/namespaces/$KUBERNETES_NAMESPACE/pods/$POD | grep -i hostIp | cut -d "\"" -f 4 

(2)通过指定一个挂载到Jenkins POD上的hostDir卷
{
"volumeMounts": [
{
"name": "docker-socket",
"mountPath": "/var/run/docker.sock",
"readOnly": false
}
],


"volumes": [
{
"name": "docker-socket",
"hostPath": {
  "path": "/var/run/docker.sock"
}
}
]
} 

一个像这样设置的实例可以在 这里 找到。

优点:
  1. 简单可行
  2. 插件数量最少

缺点:
  1. 不具规模性
  2. 直接连接了Docker Daemon
  3. 需要获取主机上的具体路径(参见Docker Workflow Plugin

Docker Plugin管理Slaves

由于显而易见的原因,先前的方法都不具规模性。因为Docker和Kubernetes早已准备就绪,所以将它们当做丰富的资源来使用似乎是一个非常好的主意。

所以,我们可以为每一个我们想要运行的构建增加Docker Plugin并用它生成一个slave容器。这就意味着我们需要一个Docker容器,这个容器有权访问Docker二进制文件(需要docker workflow支持)并且也可以从master上挂载项目的工作空间。

正如上文所述,master需要通过SSH连接到slave。为了使得连接成功,需要配置证书或是正确的SSH密钥。在这两种情况中,docker plugin的xml配置文件都需要更新以适用于Jenkins证书配置的编号(例子参见 config.xml )。

那么,确切的说,这个编号是什么呢?

Jenkins使用Credential Plugin来存储和检索证书。每一套证书都有唯一的编号,其他插件可以根据这个编号找到一套适用的证书。考虑到安全因素,密码、口令等并不是以纯文本的方式存储,而是通过SHA256加密后存储。用来加密的密钥同样也被加密以确保更加安全。关于这个主题的更多详细的资料,你可以在这篇优秀的文章 “Credential storage in Jenkins” 中找到。

我希望您注意的是,鉴于证书在Jenkins的存储方式,建立一个在没有人为干扰下可以相互通信的master镜像和slave镜像是十分重要的。可以尝试使用像这样的脚本:
#Generate master.key and secret
MAGIC="::::MAGIC::::"
mkdir -p /var/jenkins_home/secrets
openssl rand -hex 128 > /var/jenkins_home/secrets/master.key
openssl dgst -sha256 -binary /var/jenkins_home/secrets/master.key > /tmp/master.hashed
HEX_MASTER_KEY=`head -c 16 /tmp/master.hashed | xxd -l 16 -p`
openssl rand 259 > /tmp/base
echo $MAGIC >> /tmp/base
openssl enc -aes-128-ecb -in /tmp/base -K $HEX_MASTER_KEY -out /var/jenkins_home/secrets/hudson.util.Secret

为了生成密钥和master key,并用他们来加密密码,你可以使用像下面这样的脚本:
#!/bin/bash
IN=`echo $1 | base64`
SUFFIX="::::MAGIC::::"
MASTER_KEY=`cat /var/jenkins_home/secrets/master.key`
HASHED_MASTER_KEY=`echo -n $MASTER_KEY | sha256sum | cut -d " " -f 1`
HASHED_MASTER_KEY_16=${HASHED_MASTER_KEY:0:16}
openssl enc -d -aes-128-ecb -in /var/jenkins_home/secrets/hudson.util.Secret -K $HASHED_MASTER_KEY -out /tmp/hudson.key
HUDSON_KEY=`cat /tmp/hudson.key`
HUDSON_KEY_TRIMMED=${HUDSON_KEY:0:-16}
HUDSON_KEY_16=${HUDSON_KEY_TRIMMED:0:16}
echo $HUDSON_KEY_16 > /tmp/hudson16.key
echo "$IN$SUFFIX" > /tmp/jenkins.password
openssl enc -aes-128-ecb -in /tmp/hudson16.key -out /tmp/jenkins.password.enc -K $IN 

若要真正地加密密码,我不会向任何人推荐这种做法,我展示上述脚本仅仅是为了强调这种加密是多么的复杂。当然了,像这样的脚本也会充分利用Credential Plugin内部的一些细节并且给人感觉很hack。我发现在配置证书时一个更加优雅的方法是将下面的groovy脚本写进Jenkins中的init.groovy.d文件:
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.common.*
import com.cloudbees.plugins.credentials.domains.*
import com.cloudbees.plugins.credentials.impl.*
import com.cloudbees.jenkins.plugins.sshcredentials.impl.*
import hudson.plugins.sshslaves.*;

domain = Domain.global()
store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()

priveteKey = new BasicSSHUserPrivateKey(
CredentialsScope.GLOBAL,
"jenkins-slave-key",
"root",
new BasicSSHUserPrivateKey.UsersPrivateKeySource(),
"",
""
)

usernameAndPassword = new UsernamePasswordCredentialsImpl(
CredentialsScope.GLOBAL,
"jenkins-slave-password", "Jenkis Slave with Password Configuration",
"root",
"jenkins"
)

store.addCredentials(domain, priveteKey)
store.addCredentials(domain, usernameAndPassword) 

上面的片段展示了如何使用一个空的口令来生成用户名/密码证书以及SSH私钥。

优点:
  1. 足够简单

缺点:
  1. Docker Plugin现阶段还未发展到这个地步
  2. 直接连接到Docker daemon
  3. 需要访问主机的特定路径(参见Docker Workflow Plugin

即使我们抛开与Docker Plugin相关的问题不谈,我仍然对于不与Docker daemon通信而是基于Kubernetes运行的方法非常感兴趣。

Docker Plugin使用D.I.N.D管理Slaves

对于我们而言, 为了避免落后于Kubernetes。

可能的情况数量有所增加,既可以在Kubernetes master上直接使用DIND,也可以结合Docker Plugin ,从而使得每一个salve都能够运行自己的demon并且实现100%隔离。

无论哪种方式,构建过程中发生的事情与环境之外完全隔离,另一方面它确实需要使用特权模式,这可能是一个问题,因为该模式可能无法在某些环境中使用(比如我上次检查时,它就无法在Google容器引擎中使用)。

注:通过在slave中托管docker daemon,我们可以从在外部docker中挂载卷的需求中解脱出来(请记住,只有执行程序和工作流步骤中需要共享工作空间)。
优点:
  1. 100%隔离
  2. 无需访问外部Docker的特定路径

缺点:
  1. 复杂性
  2. 需要特权模式
  3. Docker 镜像不能被缓存

D.I.N.D.或者说还没未出现的方法仍需要给出一个用于缩放的解决方案。到目前为止,Docke Plugin似乎并不是一个理想的解决方案。此外,在Kubernetes中等同于Docker Plugin的插件(Kubernetes Plugin)似乎需要多一点的关注。所以,现在让我们来谈谈Swarm。
使用Swarm似乎是一个不错的选择,因为我们使用的是Kubernetes,它可以非常容易的开启N多个运行Swarm客户端的容器。我们可以使用带有合适容器的replication controller。

优点:
  1. 迅速
  2. 可扩展性
  3. 健壮性

缺点:
  1. Slaves需要在外部管理
  2. 需要访问主机的特定路径(参见Docker Workflow Plugin

使用Swarm客户端和D.I.N.D

在这种使用情况下,关于D.I.N.D的主要问题是,事实上,在Docker中的Docker,里面的镜像无法被缓存。可以去尝试做一个分享Docker Registry的实验,不过我不确定有没有可能实现。

另一方面,对于大多数其他方法,我们需要使用hostPath挂载,在一些环境中这可能无法奏效。

解决上述问题的方案是将Swarm与D.I.N.D结合。

保留Swarm客户端(而不是在每次构建之后都消除它),这样就解决了镜像缓存问题。

另外,对于D.I.N.D,我们也不再需要通过Kubernetes来使用hostPath挂载。

因此,对于我们来说,这是个两全之计。

优点:
  1. 迅速
  2. 可扩展性
  3. 健壮性
  4. 100%隔离
  5. 镜像可以被缓存

缺点:
  1. Slave需要在外部管理

结语

我尝试了上述所有的设置,并把它作为我正在做的poc的一部分:" Jenkins for Docker Workflow on Kubernetes "。

我觉得我应该分享出来。我还想要尝试的一些东西比如:
  • 对slaves使用secrets认证
  • 去除 clutter
  • 等等

欢迎在评论中回复您的经验、建议或是指正。我希望这篇文章对您有用。

原文链接:Jenkins setups for Kubernetes and Docker Workflow(翻译:李加庆)

原文发布时间为:2015-09-10 
本文作者:YiGagyeong 
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:针对Kubernetes和Docker Workflow Plugin的Jenkins配置
相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
1月前
|
缓存 Kubernetes Docker
容器服务ACK常见问题之容器服务ACK ingress websocket配置失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
1月前
|
运维 Kubernetes 监控
构建高效自动化运维体系:基于Docker和Kubernetes的实践指南
【2月更文挑战第30天】 在当今快速发展的云计算时代,传统的IT运维模式已难以满足业务的敏捷性和稳定性需求。本文深入探讨了如何通过Docker容器化技术和Kubernetes集群管理工具构建一个高效、可靠的自动化运维体系。文章首先概述了容器化技术和微服务架构的基本概念,随后详细阐述了基于Docker的应用打包、部署流程,以及Kubernetes在自动化部署、扩展和管理容器化应用中的关键作用。最后,文中通过案例分析,展示了如何在实际场景中利用这些技术优化运维流程,提高系统的整体效率和可靠性。
|
1月前
|
开发者 Docker Python
深入浅出:使用Docker容器化部署Python Web应用
在当今快速发展的软件开发领域,Docker作为一个开放平台,为开发者提供了将应用打包在轻量级、可移植的容器中的能力,从而简化了部署和管理应用程序的复杂性。本文将通过一个简单的Python Web应用示例,引导读者理解Docker的基本概念、容器化的优势以及如何使用Docker来容器化部署Python Web应用。我们将从零开始,逐步探索创建Dockerfile、构建镜像、运行容器等关键步骤,旨在为读者提供一个清晰、易于理解的指南,帮助他们掌握使用Docker容器化部署应用的技能。
|
15天前
|
jenkins Java 持续交付
配置 Jenkins 构建工具
配置 Jenkins 构建工具
31 2
配置 Jenkins 构建工具
|
18天前
|
jenkins 测试技术 持续交付
软件测试|docker搭建Jenkins+Python+allure自动化测试环境
通过以上步骤,你可以在Docker中搭建起Jenkins自动化测试环境,实现Python测试的自动化执行和Allure报告生成。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
38 6
|
24天前
|
运维 Kubernetes 持续交付
构建高效自动化运维体系:基于Docker和Kubernetes的最佳实践
在现代云计算环境中,自动化运维成为保障系统稳定性与提升效率的关键。本文深入探讨了如何利用Docker容器化技术和Kubernetes容器编排工具构建一个高效、可靠的自动化运维体系。文中不仅介绍了相关的技术原理,还结合具体案例分析了实施过程中的常见问题及解决方案,为读者提供了一套行之有效的最佳实践指南。
|
28天前
|
jenkins Java 持续交付
Docker搭建持续集成平台Jenkins最简教程
Jenkins 是一个广泛使用的开源持续集成工具,它能够自动化构建、测试和部署软件项目。在本文中,我们将使用 Docker 搭建一个基于 Jenkins 的持续集成平台。
113 2
|
1月前
|
Kubernetes 开发者 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【2月更文挑战第29天】在当今快速发展的软件开发领域,微服务架构已成为提高系统可维护性、扩展性和敏捷性的关键解决方案。本文将深入探讨如何利用Docker容器化技术和Kubernetes集群管理工具,共同构建一个既高效又可靠的微服务环境。我们将分析Docker和Kubernetes的核心功能,并展示它们如何协同工作以简化部署流程、增强服务发现机制以及实现无缝的服务伸缩。通过实际案例分析,本文旨在为开发者提供一套实用的微服务架构设计和实施指南。
|
1月前
|
JavaScript Java jenkins
如何利用CentOS7+docker+jenkins+gitee部署springboot+vue前后端项目(保姆教程)
如何利用CentOS7+docker+jenkins+gitee部署springboot+vue前后端项目(保姆教程)
84 0
|
1月前
|
jenkins Java 持续交付
Docker Swarm总结+Jenkins安装配置与集成(5/5)
Docker Swarm总结+Jenkins安装配置与集成(5/5)
49 0