Kubernetes安装Jenkins

IT
IT
IT
401
文章
1
评论
2020年12月3日20:47:42 评论 5,536 7327字阅读24分25秒

简述

持续构建与发布是我们日常工作中必不可少的一个步骤,目前大多公司都采用 Jenkins 集群来搭建符合需求的 CI/CD 流程,然而传统的 Jenkins Slave 一主多从方式会存在一些痛点,比如:

  • 主 Master 发生单点故障时,整个流程都不可用了
  • 每个 Slave 的配置环境不一样,来完成不同语言的编译打包等操作,但是这些差异化的配置导致管理起来非常不方便,维护起来也是比较费劲
  • 资源分配不均衡,有的 Slave 要运行的 job 出现排队等待,而有的 Slave 处于空闲状态
  • 资源有浪费,每台 Slave 可能是物理机或者虚拟机,当 Slave 处于空闲状态时,也不会完全释放掉资源。

正因为上面的这些种种痛点,我们渴望一种更高效更可靠的方式来完成这个 CI/CD 流程,而 Docker 虚拟化容器技术能很好的解决这个痛点,又特别是在 Kubernetes 集群环境下面能够更好来解决上面的问题,下图是基于 Kubernetes 搭建 Jenkins 集群的简单示意图:

Kubernetes安装Jenkins

从图上可以看到 Jenkins Master 和 Jenkins Slave 以 Pod 形式运行在 Kubernetes 集群的 Node 上,Master 运行在其中一个节点,并且将其配置数据存储到一个 Volume 上去,Slave 运行在各个节点上,并且它不是一直处于运行状态,它会按照需求动态的创建并自动删除。

这种方式的工作流程大致为:当 Jenkins Master 接受到 Build 请求时,会根据配置的 Label 动态创建一个运行在 Pod 中的 Jenkins Slave 并注册到 Master 上,当运行完 Job 后,这个 Slave 会被注销并且这个 Pod 也会自动删除,恢复到最初状态。

使用jenkins动态slave的优势:

  • 服务高可用,当 Jenkins Master 出现故障时,Kubernetes 会自动创建一个新的 Jenkins Master 容器,并且将 Volume 分配给新创建的容器,保证数据不丢失,从而达到集群服务高可用。
  • 动态伸缩,合理使用资源,每次运行 Job 时,会自动创建一个 Jenkins Slave,Job 完成后,Slave 自动注销并删除容器,资源自动释放,而且 Kubernetes 会根据每个资源的使用情况,动态分配 Slave 到空闲的节点上创建,降低出现因某节点资源利用率高,还排队等待在该节点的情况。
  • 扩展性好,当 Kubernetes 集群的资源严重不足而导致 Job 排队等待时,可以很容易的添加一个 Kubernetes Node 到集群中,从而实现扩展。

创建命名空间

[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl create namespace kube-ops
namespace/kube-ops created
[root@iZ0jl4dahgopda92qitm77Z ~]# 
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl get namespace
NAME STATUS AGE
default Active 79m
ingress-nginx Active 76m
kube-node-lease Active 79m
kube-ops Active 15s
kube-public Active 79m
kube-system Active 79m
kubernetes-dashboard Active 76m

部署

  • 创建PV、PVC,为Jenkins提供数据持久化
[root@iZ0jl4dahgopda92qitm77Z ~]# vim pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: opspv
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
server: 172.21.212.155
path: /home/www.centoscn.vip

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: opspvc
namespace: kube-ops
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs
resources:
requests:
storage: 3Gi
  • 创建需要用到的 PVC 对象:
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl create -f pvc.yaml
persistentvolume/opspv created
persistentvolumeclaim/opspvc created

 

  • 创建RBAC,授权
[root@iZ0jl4dahgopda92qitm77Z ~]# vim rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: kube-ops

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- 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: jenkins
namespace: kube-ops
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: kube-ops
  • 创建 rbac 相关的资源对象
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl create -f rbac.yaml
serviceaccount/jenkins created
clusterrole.rbac.authorization.k8s.io/jenkins created
clusterrolebinding.rbac.authorization.k8s.io/jenkins created

创建jenkins master

  • 新建一个 Deployment:(jenkins.yaml)
[root@iZ0jl4dahgopda92qitm77Z ~]# vim jenkins.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: kube-ops
spec:
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccount: jenkins
containers:
- name: jenkins
image: jenkins/jenkins:lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
volumeMounts:
- name: jenkinshome
subPath: jenkins
mountPath: /var/jenkins_home
env:
- name: LIMITS_MEMORY
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Mi
- name: JAVA_OPTS
value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Duser.timezone=Asia/Shanghai
securityContext:
fsGroup: 1000
volumes:
- name: jenkinshome
persistentVolumeClaim:
claimName: opspvc

---
apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: kube-ops
labels:
app: jenkins
spec:
selector:
app: jenkins
type: NodePort
ports:
- name: web
port: 8080
targetPort: web
nodePort: 30002
- name: agent
port: 50000
targetPort: agent

这里为了方便,通过 NodePort 的形式来暴露 Jenkins 的 web 服务,固定为30002端口,另外还需要暴露一个 agent 的端口,这个端口主要是用于 Jenkins 的 master 和 slave 之间通信使用的。

  • 创建 Jenkins 服务
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl create -f jenkins.yaml
deployment.apps/jenkins created
service/jenkins created

排错

  • 创建完成后,要去拉取镜像可能需要等待一会儿,查看下 Pod 的状态:
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl get pods -n kube-ops
NAME READY STATUS RESTARTS AGE
jenkins-85f6b6c6db-mkpc8 0/1 CrashLoopBackOff 1 65s
  • 查看pod
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl describe pod jenkins-85f6b6c6db-mkpc8 -n kube-ops
Name: jenkins-85f6b6c6db-mkpc8
Namespace: kube-ops
Priority: 0
Node: k8s-node2/172.21.212.157
Start Time: Tue, 08 Dec 2020 23:46:18 +0800
Labels: app=jenkins
pod-template-hash=85f6b6c6db
Annotations: <none>
Status: Running
IP: 10.244.1.2
IPs:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned kube-ops/jenkins-85f6b6c6db-227ct to k8s-node1
Normal Pulling 58s kubelet, k8s-node1 Pulling image "jenkins/jenkins:lts"
Normal Pulled 22s kubelet, k8s-node1 Successfully pulled image "jenkins/jenkins:lts"
Normal Created 20s (x2 over 20s) kubelet, k8s-node1 Created container jenkins
Normal Pulled 20s kubelet, k8s-node1 Container image "jenkins/jenkins:lts" already present on machine
Normal Started 19s (x2 over 20s) kubelet, k8s-node1 Started container jenkins
Warning BackOff 10s (x4 over 19s) kubelet, k8s-node1 Back-off restarting failed container

可以看到上面的 Warning 信息,健康检查没有通过,具体原因是什么引起的呢?可以通过查看日志进一步了解

[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl logs -f jenkins-85f6b6c6db-227ct -n kube-ops
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

很明显可以看到上面的错误信息,意思就是我们没有权限在 jenkins 的 home 目录下面创建文件,这是因为默认的镜像使用的是 jenkins 这个用户,而我们通过 PVC 挂载到 nfs 服务器的共享数据目录下面却是 root 用户的,所以没有权限访问该目录,要解决该问题,也很简单,我只需要在 nfs 共享数据目录下面把我们的目录权限重新分配下即可:

[root@iZ0jl4dahgopda92qitm76Z ~]# chown -R 1000 /data1/k8s
  • 重新创建
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl delete -f jenkins.yaml
deployment.apps "jenkins" deleted
service "jenkins" deleted
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl create -f jenkins.yaml
deployment.apps/jenkins created
service/jenkins created
[root@iZ0jl4dahgopda92qitm77Z ~]# kubectl get pods -n kube-ops
NAME READY STATUS RESTARTS AGE
jenkins-85f6b6c6db-l4x86 0/1 Running 0 6s

访问

  • 等到服务启动成功后,可以根据Node节点的 IP:30002 端口就可以访问 jenkins 服务了,可以根据提示信息进行安装配置即可:

Kubernetes安装Jenkins

  • 从Dashboard上查看

Kubernetes安装Jenkins

  • 初始化的密码可以在 jenkins 的容器的日志中进行查看,也可以直接在 nfs 的共享数据目录中查看:
[root@iZ0jl4dahgopda92qitm75Z ~]# cat /data1/k8s/jenkins/secrets/initialAdminPassword
0c7fd352ce294e10acc4559e9ed305e6
  • 然后选择安装推荐的插件即可。

Kubernetes安装Jenkins

  • 安装完成后添加管理员帐号即可进入到 jenkins 主界面

Kubernetes安装Jenkins Kubernetes安装Jenkins

  • 安装kubernetes 插件

Kubernetes安装JenkinsKubernetes安装Jenkins

  • 更新源地址为清华源https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

Kubernetes安装Jenkins

  • 安装插件

Kubernetes安装JenkinsKubernetes安装Jenkins

插件配置

点击 Manage Jenkins —> 系统配置 —> (拖到最下方)Add a new cloud —> 选择 Kubernetes,然后填写 Kubernetes 和 Jenkins 配置信息。

Kubernetes安装Jenkins Kubernetes安装Jenkins

Kubernetes安装Jenkins

另外需要注意,如果这里 Test Connection 失败的话,很有可能是权限问题,这里就需要把 jenkins 的 serviceAccount 对应的 secret 添加到这里的 Credentials 里面。

 

 

此处为隐藏的内容!
登录后方可查看!
继续阅读
  • 我的QQ
  • QQ扫一扫
  • weinxin
  • 我的头条
  • 头条扫一扫
  • weinxin
IT
  • 本文由 发表于 2020年12月3日20:47:42
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
Ingress Kubernetes

Ingress

Ingress 是什么? Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。 下面是一个将所有流量都发送到同一 Ser...
jenkinsfile集成阿里云镜像仓库 jenkins-ci/cd

jenkinsfile集成阿里云镜像仓库

创建Jenkins认证授权 ID也配置成aliyun-registry-admin 阿里云镜像库有个问题,在设置固定密码后,使用的是本账号名字。本账号的密码和镜像的密码也就不一样了。所以要么单独创建一...

您必须才能发表评论!