1、概述
本文分享的是基於k8s
環境與jenkins
實現CI/CD
其中的一個配置具體實現
即:不同環境下jenkins與k8s集群連接的問題
為什么會有不同的環境?我總結的原因如下:
a、在實際生產環境中,由於某些歷史原因我們或許不能完美的實現所謂的一切皆“雲原生”,例如有傳統的jenkins
和執行專有任務的slave
節點
b、存在多集群共一個jenkins
服務端的情況,例如k8s
中集群A
用作基礎設施集群(包含日志、存儲、devops
平台),集群B
、C
、D
用作不同業務線集群
因此,我們可以將不同環境定義為如下兩種情況:
-
同集群:指
k8s
集群內部的jenkins
連接本集群 -
跨集群:指外部的
jenkins
連接k8s
集群,或者是jenkins
連接外部的k8s
集群
2、同集群
同集群下,k8s
集群內部的jenkins
連接所在的k8s
集群。這是原生的方式:我們的環境都是全新的,全新的機器、全新安裝的集群、全新的jenkins
,總之一切都是新的,沒有任何歷史問題
由於在k8s
集群內部部署jenkins
時,已經對jenkins
做了以下相關的角色授權綁定
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: kube-system
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
namespace: kube-system
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
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: kube-system
因此只需要在jenkins
中配置相應的連接地址就可以了
在jenkins
中安裝好k8s
插件后,打開jenkins
——>系統管理——>系統配置——>新增一個kubernetes
雲
配置名稱,即這個雲的別名
Kubernetes
地址,即在集群內部暴露的k8s service
名稱
Kubernetes
命名空間,這個配置就填寫jenkins
所屬的namespace
Jenkins
地址,填寫jenkins svc
的名稱
配置完成后點擊測試連接成功
后面配置pod template
這里不做介紹,這里配置的pod template
是默認情況下jenkins slave
的pod
模板,當然也可以在每個流水線中單獨指定
配置完成后的動態創建jenkins slave pod
測試在本文后面一並給出
3、跨集群
一個實際場景:jenkins
部署在A
集群或部署在傳統VM
的環境下,想通過jenkins
連接B
集群,動態創建pod
用以執行構建任務
3.1 端口有什么
既然是跨集群,那么首先需要考慮的就是網絡問題,網絡是否可達?需要開通哪些端口的安全組策略?
在這之前,就需要先了解一下jenkins
的運行機制及端口有哪些?
-
http端口:默認
8080
,如果在jenkins
前面做了反向代理並配置了域名,那么可能是常見的80/443
端口,我這里通過域名+https
的方式訪問jenkins
-
Agent Port:基於
JNLP
的Jenkins
代理通過TCP
默認端口50000
與Jenkins
進行通信 -
SSH port:
jenkins
作為ssh
服務器,這個一般不會使用,具體使用可參考我之前的文章Jenkins workflowLibs庫的使(妙)用
3.2 網絡策略打通
由上面知道了有哪些端口之后,因此需要打通的網絡策略包括
- B集群節點連接
jenkins
暴露的http port
和Agent port
- A集群節點(即
jenkins server
)連接B
集群kube-apiserver
暴露的端口
除網絡策略之外,如果jenkins UI
的地址,例如通過ingress
設置了白名單限制訪問,還需要將B
集群的相關源ip
設置為白名單
3.3 證書的生成和配置
3.3.1 kubeconfig文件
由於這里A
集群中的jenkins
並沒有對B
集群的操作權限,因此需要配置授權,即發起對B
集群的kube apiserver
的請求,和kubectl
一樣利用config
文件用作請求的鑒權,默認在~/.kube/config
下,當然我們也可以單獨嚴格指定權限細節,生成一個jenkins
專用的config
文件,這里就不再延伸了,kubeconfig
文件的組成如下
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: xxx
server: https://<master-ip>:6443
name: cluster1
contexts:
- context:
cluster: cluster1
user: admin
name: context-cluster1-admin
current-context: context-cluster1-admin
kind: Config
preferences: {}
users:
- name: admin
user:
client-certificate-data: xxx
client-key-data: xxx
其中包含了3
段證書相關的內容,也就是我們常見的證書組成格式:ca.crt
、client.crt
、client.key
3.3.2 生成證書
在jenkins
中能夠識別的證書文件為PKCS#12 certificate
,因此需要先將kubeconfig
文件中的證書轉換生成PKCS#12
格式的pfx
證書文件
首先,使用yq
命令行工具來解析yaml
並通過base 64
解碼生成各個證書文件
服務端證書:
certificate-authority-data
——>base 64
解碼——>ca.crt
yq e '.clusters[0].cluster.certificate-authority-data' .kube/config | base64 -d > ca.crt
客戶端證書
client-certificate-data
——>base 64
解碼——>client.crt
yq e '.users[0].user.client-certificate-data' .kube/config | base64 -d > client.crt
client-key-data
——>base 64
解碼——>client.key
yq e '.users[0].user.client-key-data' .kube/config | base64 -d > client.key
然后,通過openssl
進行證書格式的轉換,生成Client P12
認證文件cert.pfx
openssl pkcs12 -export -out cert.pfx -inkey client.key -in client.crt -certfile ca.crt
Enter Export Password: # 輸入密碼加密
Verifying - Enter Export Password:
通過踩坑證明,這里必須輸入密碼,不然在后面添加jenkins
相關配置后驗證會報錯
3.3.3 導入證書
生成文件后,打開jenkins
的web
界面
添加全局憑據,憑據的類型選擇Certificate
,選擇Upload PKCS#12 certificate
上傳剛才生成的cert.pfx
證書文件
輸入通過openssl
生成證書文件時輸入的密碼
檢查上傳的證書文件,此時可以查看到,jenkins
已經成功加載了證書文件並讀取了證書文件的相關信息
3.4 配置連接外部的k8s集群
在jenkins
中新增kubernetes
雲配置
同樣的,打開jenkins
——>系統管理——>系統配置——>新增一個kubernetes
雲
配置名稱,即這個雲的別名,為外部的k8s集群起一個別名
Kubernetes
地址,這里需要填寫的是外部集群的kube-apiserver
地址,即https://<master ip>:6443
Kubernetes
服務證書key
,填寫上面服務端證書base64
解碼后的內容
Kubernetes
命名空間,填寫jenkins
所屬的namespace
憑據選擇上面導入的證書文件作為憑據
Jenkins
地址,填寫A
集群現有jenkins UI
域名(訪問地址和端口)
配置完成后點擊測試連接成功,到這里跨集群的jenkins
連接k8s
就成功了
4、測試驗證
4.1 配置pod template
這里以跨集群的環境下進行測試驗證A
集群的jenkins
執行構建任務,在B
集群中動態創建slave
的預期結果
在jenkins
系統配置中,除了配置關聯外部集群外,這里再配置一下相應的pod template
,以便於在B
集群中創建默認的slave pod
,如圖
4.2 自由風格構建測試
在自由風格中限制項目的運行節點,標簽為上面配置的pod template
標簽即k8s-test-cluster
,執行shell
命令進行測試,查看控制台輸出
4.3 流水線構建測試
編寫測試的pipeline
流水線,同樣指定標簽為上面配置的pod template
標簽即k8s-test-cluster
pipeline{
agent{
node {
label 'k8s-test-cluster-jnlp-slave'
}
}
stages{
stage('Deploy to Kubernetes'){
steps{
script{
sh """
kubectl version
kubectl get cs
"""
}
}
}
}
}
構建后查看控制台輸出
到這里,基於不同基礎環境下jenkins
與k8s
連接配置的相關操作就分享完啦
See you ~