基于Kubernetes的Jenkins实现动态slave
前言
一般情况下都是在物理机或者虚拟机上部署Jenkins,但是这种部署方式会存在一些缺点,比如:
- master节点故障,整体不可用
- 每个slave都需要维护,较为繁琐
- 资源分配不均衡,且资源利用率低
因此需要更可靠和高效的方式来完成CI/CD流程。
如图所示,master和slave以Pod的形式运行在kubernetes集群中,并且将配置数据存储到PV中。但是其中slave运行在多个节点,但是不是一直运行的状态,会根据需求动态创建并自动删除。
工作流程:
- master接收到build请求,会根据配置的label动态创建一个slave的Pod并注册到master
- slave运行完job,该Pod自动注销并且删除
- 恢复到最初的状态
架构优点:
- 高可用。当master故障时,kubernetes 会自动创建一个新的Pod,并且将之前的PV分配给新的Pod,保证数据的完整
- 动态伸缩。根据job来动态创建slave的Pod,并且完成后自动释放资源,提供资源利用率
- 可扩展。当资源不足时,可以通过增加node的方式快速增加slave
部署
编排文件
- PV/PVC 提供数据持久化
1 | --- |
- 角色授权
1 | apiVersion: v1 |
- 创建deployment
1 | --- |
依次执行上述编排文件即可。需要注意PV的文件目录权限是否需要单独修改。
配置
初始化
Jenkins启动后先进行初步配置,此处不在详细描述。需要注意的是:
- 访问的地址是使用的nodePort:30002端口
- 初始化的密码文件可以从nfs目录上获取
- 必要插件Pipline和kubernetes
配置kubernetes
节点管理-》Configure Clouds -》kubernetes
Kubernetes Cloud details
- 注意此处填写的是kubernetes 集群6443的地址。
- 由于之前创建了account,因此此处无需填写凭据
- 命名空间可以独立
- 信息填写完成后注意测试一下。如果测试失败,很可能是权限问题,需要把ServiceAccount的凭证jenkins-sa添加进来。
注意此处的Jenkins地址,要填写 http://jenkins.devops.svc.cluster.local:8080 。因为之后slave的Pod是需要访问master节点的,只有这种域名的形式才能更灵活的满足需求。如果想不明白为什么是这样的域名,可以思考一下域名解析的过程。
这两部分是配置slave的Pod的,重点部分在于镜像。jnlp是Jenkins的slave访问master的一种方式。
验证
1 | ~ kubectl get pods -n devops |
此时slave的Pod已经运行完成,自动终止了,之后会自动释放。
调试
使用podTemplate
根据标签,调度到其他节点,且使用Jenkins-slave的label
1 | podTemplate(cloud: 'kubernetes', inheritFrom: 'jenkins-slave', label: 'jenkins-slave', name: 'test-label', namespace: 'devops') { |
调度后的Pod
1 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES |
使用变量
总结
纠结了好几天,总算调试出一些结果。
- 事实证明,label的作用是决定是否使用模板,和kubernetes中的label毫无关系;
- 脚本式的pipeline和声明式的pipeline存在很大的不同,至少语法上就有很大差别;
- 解决了maven项目重复下载依赖的问题,挂载.m2目录即可;
目前仍存在的问题:
- 如何决定让slave不运行在某些机器上?
- 哪种pipeline才是主流呢?