基於K8s的動態Jenkins Slave構建實踐
前言
環境
這裡Jenkins Master的安裝沒有采用容器映象的方式,直接就是rpm包安裝。
版本資訊:
Jenkins 2.107.1
Kubernetes plugin 1.4
kubernetes叢集 1.5.2
這裡就不詳細說明安裝過程了。
配置
環境都安裝好後,配置Jenkins,進入系統管理—>系統設定—>雲
新增一個雲Kubernetes,配置如下:
配置比較簡單,這裡也沒有采用自定義的slave模板,預設Jenkins使用的是jenkins/jnlp-slave:alpine
映象作為動態的執行的slave。
其中Kubernetes URL也可以通過命令檢視:
# kubectl cluster-info
Kubernetes master 所在的地址即可,比如:
Kubernetes master is running at https://10.1.241.82:8080/r/projects/1a7/kubernetes:6443
這裡的URL就填
https://10.1.241.82:8080/r/projects/1a7/kubernetes:6443
測試
這裡測試全部使用pipeline進行構建。
新建一個Pipeline流水線專案,配置Pipeline執行指令碼:
指令碼內容:
podTemplate(label: 'mypod', cloud: 'kubernetes')
{
node ('mypod' ) {
stage('test') {
echo "hello, world"
sleep 60
}
}
}
label:Jenkins執行的節點標籤,可以隨意起;
cloud:就是我們上面配置雲的名字標識;
node:執行構建任務的slave節點,需要跟上面的label一致
非常簡單的一個測試用例,讓我們來跑一下看看。
首先看一下構建執行狀態:
可以看到Jenkins自動建立了一個Slave節點在執行我們的構建任務,
我們再通過k8s看下執行的pod情況:
# kubectl get pod
NAME READY STATUS RESTARTS AGE
jenkins-slave-5 d8m2-jzxk7 1/1 Running 0 38s
# kubectl describe pod jenkins-slave-5d8m2-jzxk7
。。。
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
46s 46s 1 {default-scheduler } Normal Scheduled Successfully assigned jenkins-slave-5d8m2-jzxk7 to master
44s 44s 1 {kubelet master} spec.containers{jnlp} Normal Pulled Container image "jenkins/jnlp-slave:alpine" already present on machine
44s 44s 1 {kubelet master} spec.containers{jnlp} Normal Created Created container with docker id 7cbdbd4ea859; Security:[seccomp=unconfined]
44s 44s 1 {kubelet master} spec.containers{jnlp} Normal Started Started container with docker id 7cbdbd4ea859
通過上面的k8s的pod資訊我們可以看到,pod名字就是Jenkins slave節點的名字。通過READY欄位,我們也能發現pod中只有一個容器在跑,最後看下詳細資訊,發現k8s確實是去拉取jenkins/jnlp-slave:alpine 映象了。
這裡再貼一下Jenkins的控制檯列印資訊:
專案實踐
真正的專案中實踐肯定不是這麼簡單的,我們這裡就以一個簡單maven構建專案為例。
步驟如下:
- 製作maven映象,設定maven倉庫私服mirror,新增ssh-key方便無密碼拉取倉庫程式碼
- 編寫Jenkinsfile,配置構建流程
- 執行構建
製作maven映象
FROM maven:latest
ADD settings.xml /root/.m2/
RUN mkdir /root/.ssh/
ADD .ssh /root/.ssh/
RUN chmod 600 /root/.ssh/id_rsa
其中settings.xml包含了maven倉庫私服mirror、sonarqube等等一些maven相關的配置,
這裡需要注意的是ssh的私鑰許可權必須是600的,這個是配置無密碼從gitlab倉庫拉取原始碼的。
通過Dockerfile來製作我們自己的maven映象:
docker build . -t e5:8889/maven:1.0
上傳到我們私服倉庫:
docker push e5:8889/maven:1.0
編寫Jenkinsfile
Jenkinsfile是jenkins pipeline構建的一種指令碼,其中定義了構建流程。
podTemplate(label: 'mypod', cloud: 'kubernetes', containers: [
containerTemplate(
name: 'maven',
image: 'e5:8889/maven:1.0',
ttyEnabled: true,
command: 'cat'
)
])
{
node ('mypod') {
container('maven') {
git url: '[email protected]:maven/springboot-archetype.git',
credentialsId: '6033483b-5125-4ce1-941d-83b23ae64ba6'
stage('create-archetype') {
sh 'mvn archetype:create-from-project'
}
stage('update-local-catalog') {
sh 'cd target/generated-sources/archetype'
sh 'mvn clean install'
sh 'mvn archetype:update-local-catalog'
}
stage('deploy') {
sh 'mvn deploy'
}
stage('build-tag') {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
echo build_tag
}
}
}
}
我們通過containers.containerTemplate
指定了我們程式碼是在哪個容器內進行構建的,其他的就都是一些簡單的構建流程,這裡就不細說了。
執行構建
我們最後再執行一次構建,看下Jenkins和k8s一些執行情況。
Jenkins Console控制檯列印:
K8s的pod資訊:
# kubectl get pod
NAME READY STATUS RESTARTS AGE
jenkins-slave-wm980-2v01l 2/2 Running 0 5s
通過READY欄位,發現這時pod執行的就有2個容器了,我們可以猜測一個是slave容器,一個是我們自定義的maven容器。
再來看下pod建立的詳細資訊:
# kubectl describe pod jenkins-slave-wm980-2v01l
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
17s 17s 1 {default-scheduler } Normal Scheduled Successfully assigned jenkins-slave-wm980-2v01l to master
15s 15s 1 {kubelet master} spec.containers{maven} Normal Pulled Container image "e5:8889/maven:1.0" already present on machine
15s 15s 1 {kubelet master} spec.containers{maven} Normal Created Created container with docker id 85c8547aa047; Security:[seccomp=unconfined]
15s 15s 1 {kubelet master} spec.containers{maven} Normal Started Started container with docker id 85c8547aa047
15s 15s 1 {kubelet master} spec.containers{jnlp} Normal Pulled Container image "jenkins/jnlp-slave:alpine" already present on machine
15s 15s 1 {kubelet master} spec.containers{jnlp} Normal Created Created container with docker id c10cc2694b05; Security:[seccomp=unconfined]
14s 14s 1 {kubelet master} spec.containers{jnlp} Normal Started Started container with docker id c10cc2694b05
通過這行資訊:"e5:8889/maven:1.0" already present on machine
我們發現果然有使用到自己的maven映象了。
結語
其實真正實踐起來還是會發現很多坑的,之前網上搜到很多教程都還需要自定義slave映象亦或者將Jenkins Master節點也作為容器放入k8s中,但是感覺一來麻煩,二來也沒太大必要就沒弄了。其實後面更關鍵是在應用的部署上面,這裡只是將構建工具鏈都準備好,提供一個應用乾淨的構建環境。
寫完之後還發現有許多可以優化的地方,比如maven本地快取倉庫的掛載等等。。