Jenkins是一款广泛受到的欢迎的持续集成工具,有着丰富的插件以及扩展能力,基本上能够满足大多数团队的需求。本文将从工具使用的角度,来讲述如何在kubernetes集群中使用Jenkins作为持续集成工具。
权限控制
K8s采用RBAC进行权限管理,Jenkins流水线需要相关的权限才能正确运行。所以,我们先创建一个jenkins.yaml的文件,以便向集群申明Jenkins需要的权限,内容如下:
代码语言:javascript复制---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: ops
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
namespace: ops
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/portforward"]
verbs: ["*"]
- 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
namespace: ops
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: ops
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkinsClusterRole
namespace: ops
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: ClusterRoleBinding
metadata:
name: jenkinsClusterRuleBinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkinsClusterRole
subjects:
- kind: ServiceAccount
name: jenkins
namespace: ops
这段代码做了这么几件事情:首先是在ops命名空间下创建了一个名为jenkins的account;然后在同一个空间下创建了一个新的角色,并申明了这个角色具备的操作权限;接下来将这个角色和前面创建的账号绑定在一起;最后因为涉及到cluster级别的一些操作,因此创建了ClusterRole,并同样进行了绑定。
持久化
Jenkins中的任务状态、数据等需要持久化下来,因此有必要提前做好准备。创建了另外一个名为jenkins-pvc.yaml的文件,内容如下:
代码语言:javascript复制kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: jenkins-pvc
namespace: ops
spec:
storageClassName: "ceph-rbd"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1024Gi
这一部分需要根据大家的根据实际情况变通,我这里是继续在ops中创建了一个名为jenkins-pvc的PersistentVolumeClaim,底层是使用的ceph作为StorageClass,然后这个存储的大小我申请的是1024G。
部署运行
前面万事已具备,现在只差部署Jenkins了。创建了一个名为jenkins-deployment.yaml的文件,内容如下:
代码语言:javascript复制apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jenkins
namespace: ops
labels:
app-name: jenkins
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app-name: jenkins
spec:
serviceAccount: jenkins
containers:
- name: jenkins
image: jenkins/jenkins:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
readOnly: false
env:
- name: JAVA_OPTS
value: "-Duser.timezone=Asia/Shanghai -XX: UnlockExperimentalVMOptions -XX: UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85"
securityContext:
runAsUser: 0
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-pvc
这里在ops命名空间创建了一个叫做jenkins的Deployment资源,然后重点看看template中的主要内容,可以看到在spec中申明了要使用前面准备好的ServiceAccount。然后这个应用需要使用两个端口,一个是8080,用于提供web界面,另外一个是50000端口,Jenkins中的slave节点和master通信的时候会用到。最后在volumes中申明了要使用前面准备好的pvc做持久化存储。
此时,你可以通过执行kubectl apply -f *来应用这些yaml文件,成功之后你会看到在ops下会有名为jenkins的deploment、以及jenkins开头的pod的存在。
Service 和 Ingress
经过前面的步骤,Jenkins已经正常启动起来了。命令行里会输出初始的密码,接下来需要做的就是用这个初始密码登录Jenkins。 那么问题就来了,我们目前仅仅是把Jenkins运行了起来,并没有办法在集群外部很方便地访问到它,也没办法完成Jenkins的初始化工作。因此,接下来需要为应用创建Ingress。创建一个新的yaml文件,内容如下:
代码语言:javascript复制kind: Service
apiVersion: v1
metadata:
labels:
app-name: jenkins
name: jenkins
namespace: ops
spec:
ports:
- port: 8080
targetPort: 8080
name: web
- port: 50000
targetPort: 50000
name: agent
selector:
app-name: jenkins
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: jenkins-http-route
namespace: ops
spec:
entryPoints:
- web
routes:
- match: Host(`jenkins.your-domain.com`)
kind: Rule
services:
- name: jenkins
port: 8080
这里只提一点,就是集群中使用的是Traefik 2.0作为Ingress Controller,所以不能在直接创建Ingress,而是要创建IngressRoute的资源才能让服务变得可访问。(关于Traefik 2.0和Ingress Route的知识,可以查看之前的文章)
现在你应该可以在浏览器里通过你的域名访问到jenkins了,按照默认向导进行初始化就可以了,如果遇到插件安装失败可以直接跳过,后面可以更换下载源或者手动安装即可。在下一篇文章中,我们将在此基础上安装需要的插件然后创建一条流水线把Jenkins用起来。