随着Kubernetes的普遍应用,基于Kubernetes的jenkins发布模式也需要随之做出一些改变,本博客基于之前搭建的Kubernetes 1.16.0高可用集群搭建一套企业级别Jenkins CI/CD发布流程。
Jenkins采用Pipline发布,容器化部署,主从结构,Jenkins master负责调度slave,而slave进行拉代码,打包,构建镜像发布等操作,待发布完成后slave自动消亡,不占用服务器资源。代码存储这里为了方便采用的Git仓库,镜像存储采用最新的1.9.0 Harbor。
服务器资源:
172.30.0.109 k8smaster1 Harbor
172.30.0.81 k8smaster2
172.30.0.89 k8snode1 Git仓库
注意:master节点设置为可调度,也可作为node,运行业务容器,K8S部署方案,请参考上一篇博客,在这里不过多描述。
本博客中相关配置文件,后面会上传到百度网盘中
一、部署Harbor
1、安装docker-compose
harbor需要基于docker-compose插件进行安装,管理
# curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
2、安装docker
Harbor 1.9版本的docker驱动需要至少18.03以上,请自行安装
3、下载Harbor安装包
Github上面搜索Harbor
4、修改harbor配置
修改haribor.yml,
若使用IP登录,需要修改成IP地址,域名登录,需要修改成域名,这里Harbor使用的是http模式,若要修改成https访问,则要修改密钥配置
Harbor使用非安全认证,docker需要修改安全配置,设置为新人非安全,否则无法上传镜像包
docker.service配置如下
5、Harbor效果,正常上传镜像
二、Git仓库
生产建议使用Gitlab图形化工具,方便管理
1、初始化Git服务器
下载git
# yum install git -y
# useradd git
# groupadd git
# su - git 切换到git用户,创建仓库
# mkdir tomcat-java-demo
# cd tomcat-java-demo
# git init --bare 初始化git
# git服务器初始化完成
2、上传代码到Git仓库
解压java demo代码
# unzip tomcat-java-demo.zip
# cd tomcat-java-demo
# git init 初始化客户端git,准备上传代码至远程服务端
# git add . 添加代码至本地git仓库
# git commit -m 'test'
# git remote add origin [email protected]:/home/git/tomcat-java-demo 设置git仓库为远程客户端
# git push origin master 上传代码至远程客户端master分支
验证代码是否正常上传:
重新创建一个目录,初始化git,拉取代码
# mkdir test && cd test
# git init && git remote add origin [email protected]:/home/git/tomcat-java-demo
# git pull origin master
代码拉取成功,上传代码无误
上传代码至指定分支,如1.0.0
本地创建1.0.0的分支,切换到1.0.0分支,因为默认是在master分支,然后上传代码到远程1.0.0分支
# git branch 1.0.0 创建1.0.0分支
# git checkout 1.0.0 切换到1.0.0分支
# git push origin 1.0.0 代码上传到远程1.0.0
会在远程git服务器上看到多了一个1.0.0分支
三、Jenkins部署
1、部署Jenkins master
[root@k8s-master1 jenkins]# cat jenkins.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: jenkins
labels:
name: jenkins
spec:
serviceName: jenkins
replicas: 1
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
name: jenkins
template:
metadata:
name: jenkins
labels:
name: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccountName: jenkins
#imagePullSecrets:
# - name: registry-pull-secret
nodeName: k8s-master1
containers:
- name: jenkins
image: jenkins/jenkins:lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
- containerPort: 50000
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 0.5
memory: 500Mi
env:
- name: LIMITS_MEMORY
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Mi
- name: JAVA_OPTS
# value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
volumeMounts:
- name: data
mountPath: /var/jenkins_home
securityContext:
fsGroup: 1000
volumes:
- name: data
hostPath:
path: /app/jenkins
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
spec:
type: NodePort
selector:
name: jenkins
ports:
-
name: http
port: 80
targetPort: 8080
protocol: TCP
nodePort: 30009
-
name: agent
port: 50000
protocol: TCP
对jenkins容器进行授权
[root@k8s-master1 jenkins]# cat rbac.yaml
# In GKE need to get RBAC permissions first with
# kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin [--user=
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
# kubectl apply -f rbac.yaml
# kubectl apply -f jenkins.yaml
访问http://172.30.0.109:30009 打开Jenkins web页面,插件安装默认就好,之后再到插件管理页面自行安装需要的插件
2、Jenkins系统配置
①集成Kubernetes到Jenkins中
在系统管理的系统设置中,修改配置
修改后可以进行连接测试,在右下角
②下载Jenkins与Kubernetes集成的插件
在系统管理的插件管理中
Kubernetes
Kubernetes Continuous Deploy
Extended Choice Parameter
③配置Git仓库访问密钥以及Jenkins容器访问Kubernetes使用的kubeconfig配置
在凭据中
访问Git服务器的密钥,只需要做Jenkins服务器到Git无密登录,并复制Jenkins所在服务器的私钥到以上位置,即可实现代码拉取过程的无密登录
将K8S集群/root/.kube/config文件复制到以上地区,使Jenkins可以访问K8S集群,部署pod
3、Jenkins slave
构建Jenkins Slave,再Jenkins上通过Pipline流水线调用JnekinsFile进行发布操作
Jenkins Slave Dockerfile:
构建镜像
# docker build -t 172.30.0.109/wujqc/jenkins-slave:lts -f dockerfile-jenkins-slave .
上传到Harbor上
# docker login 172.30.0.109
输入harbor管理员账号密码,进行登录
# docker push 172.30.0.109/wujqc/jenkins-slave:lts
4、创建Pipline发布Java项目到K8S环境
①创建流水线项目
②设置参数化构建
可以通过标签,字符参数指定代码分支,Branch等多种方式去拉取Git,Gitlab指定位置的代码,进行编译,这里采用的是字符参数指定代码分支的方式
③配置Pipline流水线
设置git地址,配置能够拉取git的免登录密钥(前面配置的)
通过字符参数Tag,获取到想要编译的代码分支,如1.0.0,载入变量origin/1.0.0拉取代码,在拉取的代码中读取JenkinsFile进行下一步Jenkins Slave的maven构建,镜像构建,K8S deploy操作
可以说整个Jenkins项目中,是通过${Tag}版本去拉取指定分支的JenkinsFile以及代码,在此基础上进行的流水线式部署,JenkinsFile中封装的就是整个打包编译,拉取指定服务的dockerfile,deploy.yaml,构建镜像,上传镜像,部署K8S deploy.yaml的流水线操作。
注意:JenkinsFile需要在git代码路径中,要不然Jenkins识别不到,会报NotFoundFile
JenkinsFile文件如下:
注意:这两处ID,需要替换成Jenkins上面的git,kubeconfig密钥ID
因为Jenkins Slave需要要到Docker进行镜像构建,上传操作,于是将docker以挂载的方式放入Jenkins Slave中,让其能够使用
Download Deploy File操作,是为了区分各个系统服务,微服务模块,因为不同的服务模块,其deploy.yaml以及Dockerfile可能都不一样,所以需要有一个统一管理的路径去获取到这两个文件,方便管理,只需要将目录挂载到Jenkins Slave中即可,这个路径,可以采用NFS,在这里为了方便使用的hostpath,生产不建议这么使用
5、启动Pipline项目,输入分支号1.0.0
构建成功!