上一篇中,我们演示了如何配置并运行一条简单的流水线,可能有些读者对于上篇文章中的配置还有些疑问:
- 为何构建任务运行时会有一个slave节点加入
- pipeline的写法似乎和Jenkins文档中的例子有点不一样
今天这篇文章就来解答上面两个问题,并解释下构建中的几个stage跟传统环境中的差异
哪里来的slave?
这些slave节点都是kubernetes-plugin
这个插件动态创建的,实际上是在kubernetes运行的一个pod
大家应该还记得,我们在第一篇文章中,检查Jenkins安装结果的时候,查看了cloud
的kubernetes配置,这些配置就是给kubernetes-plugin
用的
这个插件会扩展pipeline的写法,允许我们自定义执行构建的环境,这也是为什么我们的pipeline会跟常见的有些差异的原因
slave节点配置
参数 | 作用 |
---|---|
名称 | kubernetes集群的标识,pipeline中以此选择在哪个集群中做构建 |
Kubernetes 地址 | kubernetes api入口,如果要连接Jenkins master所在的集群,写成https://kubernetes.default 即可 |
凭据 | 连接kubernetes api的凭据,如果Jenkins master在集群内且安装了rbac权限,可以留空 |
Jenkins 地址 | slave节点连接Jenkins master的地址 |
Jenkins 通道 | Jenkins master节点连接slave的地址 |
Pod 模板 | slave节点的定义,可以定义调度规则,包含那些容器,挂载哪些配置等 |
在我们这个环境中,pod模板的定义放在了pipeline里,可以提供更好的可回溯性
这里面还有几个点要注意:
- Jenkins会在slave pod启动的时候自动注入一个jnlp container,用来和Jenkins master通信
- 一般来讲,pod中的container都会有至少一个stage与其相对应,且stage一般都是串行执行,所以,container的主进程要配置成阻塞在stdin
- container之间一般都会有数据传递,默认会给pod上加一个emptydir的volume,mount到每一个container的/home/jenkins/agent目录,并且这个目录作为各个container的workspace
容器中的CI/CD
既然slave节点是Jenkins在kubernetes中动态创建的pod,那么自然我们所有的CI/CD流程都是在容器中进行的,如果说容器中做代码构建和传统环境区别还不算大,那么在后面的docker镜像构建、发布到kubernetes等过程就有了比较大的变化了,也是常常会困扰我们的问题,这里我们要推荐一些新东西出来:
无docker daemon的image build
在容器中做image build并不是新鲜事,常见的有这么几种做法:
- dind方式,需要privilege权限
- 挂载/var/run/docker.sock文件到容器里,完全操作主机的docker daemon
这两种方式都对主机有要求,并且在serverless的virtual node上无法使用,我们在示例的pipeline中使用的是kaniko,完全不依赖docker daemon即可完成image build
kubernetes-cli插件
在将应用发布到kubernetes的时候,需要用到kubectl,这里有两种方式:
- 将目标集群的.kube/config文件保存在configmap里,通过volume的方式挂载到容器里,在容器内使用kubectl
- 将目标集群的任意凭证保存在Jenkins里,通过kubernetes-cli插件来使用kubectl
在我们的例子中使用的是第二种方式
小结
前面两篇文章介绍了如果快速搭建Jenkins环境、演示了一条简单的流水线,本片着重介绍这种构建方式要注意的点以及因这种构建方式而引入的新的工具
后面我们会介绍在这套基于容器的Jenkins环境中的发布实践