前置工作:已部署5節(jié)點k8s集群,并搭建了代碼倉庫和鏡像倉庫(GitLab + Harbor)。
主機名 | IP | 角色 |
---|---|---|
k8s-master1 | 192.168.124.a | k8s控制平面 |
k8s-master2 | 192.168.124.b | k8s控制平面 |
k8s-master3 | 192.168.124.c | k8s控制平面 |
k8s-worker1 | 192.168.124.d | k8s工作節(jié)點 |
k8s-worker2 | 192.168.124.e | k8s工作節(jié)點 |
harborgit | 192.168.124.f | 代碼倉庫 & 鏡像倉庫 |
Jenkins容器化部署
Jenkins是一款開源的、用于自動化構(gòu)建、測試和部署的CI-CD工具。
部署NFS PV存儲
??配置參考:https://blog.csdn.net/Sebastien23/article/details/126276294
在工作節(jié)點k8s-worker1上部署NFS服務(wù)器:
[root@k8s-worker1 ~]# mkdir -p /ifs/kubernetes
[root@k8s-worker1 ~]# yum install nfs-utils -y
[root@k8s-worker1 ~]# vi /etc/exports
/ifs/kubernetes *(rw,sync,no_root_squash)
[root@k8s-worker1 ~]# systemctl start nfs
[root@k8s-worker1 ~]# systemctl enable nfs
在其他工作節(jié)點掛載NFS共享目錄:
[root@k8s-worker2 ~]# mkdir -p /ifs/kubernetes
[root@k8s-worker2 ~]# yum install nfs-utils -y
[root@k8s-worker2 ~]# echo '192.168.124.d:/ifs/kubernetes /ifs/kubernetes nfs4 defaults 0 0' >> /etc/fstab
[root@k8s-worker2 ~]# mount -a
修改目錄權(quán)限:
[root@k8s-worker1 ~]# mkdir /ifs/kubernetes/jenkins
[root@k8s-worker1 ~]# chmod -R 777 /ifs/kubernetes
定義一個nfs類型的PV資源:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-jenkins
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
path: /ifs/kubernetes/jenkins
server: 192.168.124.d
創(chuàng)建PV資源:
[root@k8s-master1 jenkins]# kubectl apply -f pv-nfs-jenkins.yml
persistentvolume/pv-nfs-jenkins created
[root@k8s-master1 jenkins]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-jenkins 5Gi RWX Retain Available 6s
Jenkins部署
通過Deployment控制器來部署Jenkins官方鏡像,會對外暴露8080(Web訪問端口)和50000(Slave通信端口)兩個端口。Jenkins容器的數(shù)據(jù)存儲默認在/var/jenkins_home
目錄下,需要對該目錄進行PV持久化。
??官方鏡像地址:https://hub.docker.com/r/jenkins/jenkins
??部署配置:https://www.jenkins.io/doc/book/installing/kubernetes/
我們使用jenkins.yml
來部署Jenkins容器,通過PVC來請求PV資源,同時定義好Service訪問和RBAC服務(wù)賬號權(quán)限。
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
spec:
replicas: 1
selector:
matchLabels:
name: jenkins
template:
metadata:
name: jenkins
labels:
name: jenkins
spec:
serviceAccountName: jenkins
containers:
- name: jenkins
image: jenkins/jenkins:lts
ports:
- containerPort: 8080
- containerPort: 50000
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
securityContext:
fsGroup: 1000
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
spec:
selector:
name: jenkins
type: NodePort
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
nodePort: 30008
- name: agent
port: 50000
protocol: TCP
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: default
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: jenkins
namespace: default
rules:
- apiGroups: [""]
resources: ["pods","events"]
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","events"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: default
部署Jenkins容器:
[root@k8s-master1 jenkins]# kubectl apply -f jenkins.yml
deployment.apps/jenkins created
persistentvolumeclaim/jenkins created
service/jenkins created
serviceaccount/jenkins created
role.rbac.authorization.k8s.io/jenkins created
rolebinding.rbac.authorization.k8s.io/jenkins created
部署完成后,通過查看Pod日志來獲取Jenkins初始化的管理員口令:
kubectl get pods
kubectl logs <jenkins-pod-name>
# 也可以在宿主機的以下路徑找到
cat /ifs/kubernetes/jenkins/secrets/initialAdminPassword
Jenkins初始化
通過暴露的NodePort訪問Jenkins首頁,我這里是http://192.168.124.a:30008
。
[root@k8s-master1 jenkins]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins NodePort 10.106.152.176 <none> 80:30008/TCP,50000:30282/TCP 22m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d
在自定義Jenkins界面,選擇插件來安裝(不要安裝推薦的插件),選擇“無”來取消自動勾選的所有插件。
定義好管理員用戶和實例信息后,來到Jenkins首頁。
安裝Jenkins插件
在Manage Jenkins → \rightarrow →System Configuration → \rightarrow →Manage Plugins → \rightarrow →Available plugins中分別搜索安裝以下插件(install without restart):
- Git:用于拉取代碼。
- Git Parameter:Git參數(shù)化構(gòu)建。
- Pipeline:流水線。
- kubernetes:連接k8s動態(tài)創(chuàng)建Slave代理。
- Config File Provider:存儲配置文件。
- Extended Choice Parameter:擴展選擇框參數(shù)。
Jenkins下載插件默認服務(wù)器在國外,如果下載速度很慢,可以修改為國內(nèi)源:
cd /ifs/kubernetes/jenkins/updates
sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json
然后通過瀏覽器重啟Jenkins:
http://NodeIP:30008/restart
如果重啟Jenkins Pod所在服務(wù)器后,Jenkins容器狀態(tài)一直為Unknown,可以直接刪除Pod,Deployment控制器會重新再創(chuàng)建一個新的Pod。而且由于/var/jenkins_home
被掛載在NFS存儲中,也不用擔心丟失Jenkins數(shù)據(jù)。
[root@k8s-master1 jenkins]# kubectl get pods,deploy
NAME READY STATUS RESTARTS AGE
pod/jenkins-5bddd99684-w9glp 0/1 Unknown 5 11h
pod/jenkins-slave-nhfbm-0xd6f 0/1 ContainerCreating 0 58m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/jenkins 0/1 1 0 11h
[root@k8s-master1 jenkins]# kubectl delete pod/jenkins-5bddd99684-w9glp
pod "jenkins-5bddd99684-w9glp" deleted
Jenkins主從架構(gòu)配置
Master(Jenkins本身)提供Web頁面來讓用戶管理項目和Slave(從節(jié)點)。項目任務(wù)可以運行在Master本機,也可以分配到從節(jié)點運行。一個Master可以關(guān)聯(lián)多個Slave。Slave節(jié)點起到了分擔工作任務(wù)和隔離構(gòu)建環(huán)境的作用。
當觸發(fā)Jenkins任務(wù)時,Jenkins會調(diào)用Kubernetes API創(chuàng)建Slave Pod。Slave Pod啟動后會連接Jenkins,接受任務(wù)處理。
Kubernetes插件配置
Kubernetes插件用于Jenkins在k8s集群中運行動態(tài)代理。
??插件介紹:https://github.com/jenkinsci/kubernetes-plugin
配置插件:Manage Jenkins → \rightarrow →Manage Nodes and Clouds → \rightarrow →Configure Clouds中添加Kubernetes。
點擊打開Kubernetes Cloud Details,輸入Kubernetes地址:
https://kubernetes.default
表示default命名空間中的kubernetes服務(wù),并點擊“連接測試”,出現(xiàn)Connected to Kubernetes v1.x.x
即表示連接成功。
最后輸入Jenkins地址并保存。
http://jenkins.default
安裝nerdctl工具
Jenkins Slave工作需要用到OpenJDK、Maven、git命令、kubectl命令、以及docker build和docker push命令。由于我們的k8s集群使用的容器運行時為containerd,自帶的crictl工具不支持build和push操作,因此需要安裝nerdctl工具。
??Nerdctl官方下載地址:https://github.com/containerd/nerdctl/releases
查看containerd版本:
kubectl get nodes -o wide
#CONTAINER-RUNTIME中的版本信息為containerd://1.6.18
下載兼容的nerdctl版本,并解壓到/usr/local
目錄下:
tar Cxzvvf /usr/local nerdctl-full-1.2.1-linux-amd64.tar.gz
啟動nerdctl和buildkit服務(wù):
nerdctl run -d --name nginx -p 80:80 nginx:alpine
# nerdctl使用buildkit服務(wù)來build鏡像
systemctl enable buildkit.service --now
自定義Jenkins Slave鏡像
用于構(gòu)建Jenkins Slave鏡像的Dockerfile如下:
FROM centos:7
LABEL maintainer kratos
RUN yum install -y java-1.8.0-openjdk maven git libtool-ltdl-devel && \
yum clean all && \
rm -rf /var/cache/yum/* && \
mkdir -p /usr/share/jenkins
COPY slave.jar /usr/share/jenkins/slave.jar
COPY jenkins-slave /usr/bin/jenkins-slave
COPY settings.xml /etc/maven/settings.xml
RUN chmod +x /usr/bin/jenkins-slave
COPY kubectl /usr/bin/
ENTRYPOINT ["jenkins-slave"]
其中:
-
slave.jar
為agent程序,用于接收master下發(fā)的任務(wù)。 -
jenkins-slave
是用于啟動slave.jar
的Shell腳本。 -
settings.xml
配置中需要將Maven官方源修改為阿里云源。 - 另外還需要
kubectl
客戶端工具。
在Dockerfile同級目錄下準備好要打包進鏡像的文件。
[root@k8s-master1 jenkins]# ls
Dockerfile jenkins-slave kubectl settings.xml slave.jar
構(gòu)建鏡像并推送到Harbor鏡像倉庫:
# 注意命令最后面的'.'
nerdctl build -t 192.168.124.f/library/jenkins-slave-jdk:1.8 .
nerdctl push 192.168.124.f/library/jenkins-slave-jdk:1.8
推送成功后在Harbor倉庫中可以看到上傳的鏡像。
如果推送失敗,報錯類似如下:
ERRO[0000] server "192.168.124.f" does not seem to support HTTPS error="failed to do request: ...
... dial tcp 192.168.124.f:443: connect: connection refused
... unexpected status from GET request to https://auth.docker.io/token?offline_token=true&service=registry.docker.io: 401 Unauthorized
則需要配置容器運行時的HTTP傳輸。如果是docker,只需要在/etc/docker/daemon.json
中增加insecure-registries
并配置Harbor地址,然后重啟docker服務(wù)即可。Containerd則需要修改/etc/containerd/config.toml
中的多項配置。
# 備份containerd配置文件
[root@k8s-master1 jenkins]# cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
# 修改containerd配置文件
[root@k8s-master1 jenkins]# vi /etc/containerd/config.toml
...
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.124.f".tls]
insecure_skip_verify = true # 跳過TLS認證
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.124.f".auth]
username = "admin" # 配置Harbor登陸用戶和密碼
password = "XXXXXX"
[plugins."io.containerd.grpc.v1.cri".registry.headers]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.124.f"]
endpoint = ["http://192.168.124.f"] # 配置Harbor訪問地址
...
# 重啟containerd
[root@k8s-master1 jenkins]# systemctl restart containerd
登錄后重新推送即可(要加--insecure-registry
):
[root@k8s-master1 jenkins]# nerdctl login http://192.168.124.f --insecure-registry
[root@k8s-master1 jenkins]# nerdctl push 192.168.124.f/library/jenkins-slave-jdk:1.8 --insecure-registry
??參考:https://goharbor.io/docs/2.0.0/install-config/run-installer-script/#connect-http
測試主從架構(gòu)是否正常
點擊New Item輸入名稱java-demo
,選中Pipeline再點擊OK確認。
創(chuàng)建完成后,在java-demo → \rightarrow →Configure → \rightarrow →Advanced Project Options → \rightarrow →Pipeline中選擇“Pipeline Script”。
將下面的測試腳本粘貼進去并保存。
pipeline {
agent {
kubernetes {
label "jenkins-slave"
yaml '''
apiVersion: v1
kind: Pod
metadata:
name: jenkins-slave
spec:
containers:
- name: jnlp
image: "192.168.124.f/library/jenkins-slave-jdk:1.8"
'''
}
}
stages {
stage('Main'){
steps {
sh 'hostname'
}
}
}
}
保存Pipeline腳本后,在新建項目中點擊Build Now,然后在Build History中查看Console Output日志,直到輸出Build成功的信息。文章來源:http://www.zghlxwxcb.cn/news/detail-435061.html
可以通過kubectl get pods
命令檢查k8s集群中是否會自動創(chuàng)建和銷毀jenkins-slave Pod。文章來源地址http://www.zghlxwxcb.cn/news/detail-435061.html
到了這里,關(guān)于K8S + GitLab + Jenkins自動化發(fā)布項目實踐(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!