TOC
kubernetes ci/cd 开源实现有很多,传统的有霸主jenkins、后起之秀drone、Spinnaker、gitlab-ci以及jenkins-kubernetes衍生版jenkins X等; 不可否认后起之秀们有性能优势、云原生,但论产品的功能性、成熟度、生态跟jenkins比都不是一个级别产品,ci/cd 是企业devops的关键一环, jenkins在Pipeline加持下依然是当前不二之选。
- 先说下我这里的后端部署有 jar包和 war包,前端都是一样,大家可以根据自己的实际情况进行适当修改即可。
- 在代码库中增加一个Jenkinsfile 结合BlueOcean插件,采用webhook触发打包发布,dev、test环境会直接部署,master会有一个确认步骤,同意后才能进行发布。
- 此次部署有持久化存储需求,请自行解决,或参考我之前的ceph文档。
部署jenkins
git clone https://github.com/li-sen/jenkins-cicd-on-kubernetes.git
cd jenkins-cicd-on-kubernetes
1. 创建namespace
kubectl create -f 01ns.yaml
2. 创建ceph-key
kubectl create secret generic ceph-storageclass-secret --type="kubernetes.io/rbd" --from-literal=key='xxxxxxxxxxxxxBzNNWJVcfyCrhWDA==' --namespace=kube-ops
3. 创建sa
kubectl create -f 02jenkins-rbac.yaml
4. 创建statefulset
kubectl create -f 03jenkins-statefulset.yaml
5. 创建svc
kubectl create -f 04jenkins-svc.yaml
6. 安装jenkins
# 获取初始密码
kubectl exec -it jenkins-0 /bin/bash -n kube-ops
jenkins@jenkins-0:/$ cat /var/jenkins_home/secrets/initialAdminPassword
# 后续步骤跟传统安装一样,按推荐下一步就行(插件安装也按默认推荐),这里省略了。
- Jenkins URL需要设置为: http://jenkins.kube-ops.svc.cluster.local:8080/ 不然slave pod 无法连接master
- 插件的需另外安装Blue Ocean、kubernetes Gitlab相关插件 这里我就不截图了。
目录说明
由于前后端,采用不同的打包方式,部署的方式也不一样,所以采用不同的slave进行打包部署
fe 表示前端
java 表示后端
build slave镜像
# fe 前端
# fe前端打包前需要打包一个自定义nginx镜像:增加自定义配置,详细看Dockerfile。
cd fe/
docker build -t harbor.xxx.com/pub/nginx:v1 .
docker push harbor.xxx.com/pub/nginx:v1
docker build -t harbor.xxx.com/pub/jnlp-slave:fe .
docker push harbor.xxx.com/pub/jnlp-slave:fe
# 基础镜像,改时区,deploy虽然已经挂载了宿主机的/etc/localtime,但java还是无法正确识别时区,只能打基础镜像。
cd java/jar/springboot
docker build -t harbor.xxx.com/pub/springboot .
docker push harbor.xxx.com/pub/springboot
cd java/war/tomcat
docker build -t harbor.xxx.com/pub/tomcat .
docker push harbor.xxx.com/pub/tomcat
# war 后端
cd java/war/jenkins-slave
docker build -t harbor.xxx.com/pub/jnlp-slave:java .
docker push harbor.xxx.com/pub/jnlp-slave:java
# jar 后端
cd java/jar/jenkins-slave
docker build -t harbor.xxx.com/pub/jnlp-slave:jar .
docker push harbor.xxx.com/pub/jnlp-slave:jar
根据实际情况选取前后端slave
集成k8s
安装完毕后,点击 Manage Jenkins —> Configure System —> (拖到最下方)Add a new cloud —> 选择 Kubernetes,然后填写 Kubernetes 和 Jenkins 配置信息。
新增kubernetes信息
# 相关参数我这里贴下:
https://kubernetes.default.svc.cluster.local
kube-ops
http://jenkins.kube-ops.svc.cluster.local:8080
点击连接测试
新增后端 pod 模板
# 相关参数我这里贴下:
jnlp-java
jnlp-java
kube-ops
jenkins-jnlp-java # 这个lable很重要,后面的Jenkinsfile 运行指定容器就用这个参数
harbor.xxx.com/pub/jnlp-slave:java
# 这个镜像,这个镜像是在官方的 jnlp 镜像基础上定制的,加入了 kubectl 等一些实用的工具,具体请看Dockerfile。
# 说明下最好是镜像拉取策略为 Always,因为有时候基础slave 镜像更新了 由于tag一样,如果策略为IfNotPresent,则会一直使用老的镜像。
jenkins中设置多个 pod 模板,譬如java、或者前端fe 不要改变container模板的名称,不然jenkins-slave无法连接master
说明:
# 相关参数我这里贴下: /var/run/docker.sock /var/run/docker.sock /root/.kube /home/jenkins/.kube # /var/run/docker.sock 让slave pod 共享宿主机的 Docker, docker in docker 的方式 # /root/.kube 让slave pod中能够使用 kubectl 工具来访问我们的 Kubernetes #代理的空闲存活时间 这个参数可以选择480分钟,这样会一直有slave在线,会加速打包编译以及发布速度。
说明:
# 相关参数我这里贴下: myregistrykey jenkins
新增前端 pod 模板
说明: 前端slave pod和后端 参数基本一样这里就不赘述了。
测试
创建harbor secrets
kubectl create secret docker-registry myregistrykey --docker-server=harbor.xxx.com --docker-username=admin --docker-password=xxxx --docker-email="xxx@xxx.com" -n kube-ops
创建一个自由风格项目
# 相关参数我这里贴下:
docker info
kubectl get pods
点击构建 查看结果
至此jenkins与kubernetes的集成完成!下面来进行gitlab中项目进行整合
Jenkinsfile
将对应的Jenkinsfile上传到 相应git项目的 根目录
# Jenkinsfile 流程
拉代码---> 替换配置文件、编译打包---> 拷贝相关文件、打包成docker镜像并上传--->替换k8s相关资源模板文件--->创建k8s资源发布
一定要看懂Jenkinsfile 的内容,因为每个公司技术栈不一样,打包方式也不一样,需求也不一样,基本上都要根据自己的情况进行修改的,pipeline语法还是挺简单的。
新建相关资源
k8s 新建 ns
kubectl create ns master
kubectl create ns test
kubectl create ns dev
# 新建ns 相关资源
kubectl create secret docker-registry myregistrykey --docker-server=harbor.xxx.com --docker-username=admin --docker-password=xxxx --docker-email="xxx@xxx.com" -n master
kubectl create secret docker-registry myregistrykey --docker-server=harbor.xxx.com --docker-username=admin --docker-password=xxxx --docker-email="xxx@xxx.com" -n test
kubectl create secret docker-registry myregistrykey --docker-server=harbor.xxx.com --docker-username=admin --docker-password=xxxx --docker-email="xxx@xxx.com" -n dev
kubectl create secret generic ceph-storageclass-secret --type="kubernetes.io/rbd" --from-literal=key='xxxxxxxxxxxxxxxxxxxx/SiECTd0WfQ==' --namespace=master
kubectl create secret generic ceph-storageclass-secret --type="kubernetes.io/rbd" --from-literal=key='xxxxxxxxxxxxxxxxxxxx/SiECTd0WfQ==' --namespace=test
kubectl create secret generic ceph-storageclass-secret --type="kubernetes.io/rbd" --from-literal=key='xxxxxxxxxxxxxxxxxxxx/SiECTd0WfQ==' --namespace=dev
jenkins 账号新增
# jenkins中新增 harbor账号密码
# 我这里将数据库的账号密码也放jenkins中了
# 目的是为了隐藏账号密码,Jenkinsfile直接通过jenkins变量引入
BlueOcean
打开BlueOcean,安装提示部署,默认会在有Jenkinsfile的项目分支中建立多分支项目。
Jenkinsfile中 对与master分支 也就是一般的生产环境所用的分支,在发布的时候会有一个 确认操作!否则会一直等待直到失效。
前端项目,nginx的配置文件我是通过configmap进行存储控制的,所以打包发布之前先确认对应的configmap建立好。
webhook
只要代码进行了修改,就自动触发cicd
在gitlab 设置webhook url
Settings——>Integrations
格式为:
http://xxxxx/project/[ProjectName]
示例:
http://88.88.88.88:40002/project/api-gateway
webhook触发多分支流水线会自动判断并触发对应的分支打包,比如项目master分支更新了,只会触发jenkins上项目对应的master,其他的分支不会 触发打包发布操作。
回滚
由于在 发布/更新 时候添加了 --record ,所以会有一个版本号的概念
kubectl apply -f deploy.yaml --record
kubectl set image deploy ${app_name} ${app_name}=${image_name} -n ${env.BRANCH_NAME} --record
# 查看master namespace deployment 记录
kubectl rollout history deployment -n master
# 回滚
kubectl rollout undo deployment xxxx --to-revision=2 -n master
后续有需求再来采用 helm方式进行发布 回滚,先满足功能需求再说。。。