kubernetes上安裝 Jenkins 及常見問題
-
持續集成和部署是DevOps的重要組成部分,Jenkins是一款很是流行的持續集成和部署工具,最近試驗了一下Jenkins,發現它是我一段時間以來用過的工具中最複雜的。一個可能的緣由是它須要與各類其它工具集成才能完成任務,而集成的方法又各不相同。在這些工具中,Docker是最簡單的,真的很是好用。kubernetes比較複雜,開始要花些時間熟悉,但它的總體設計十分合理,一旦搞清核心概念,掌握脈絡以後,就很是順利。它的命令格式即規範又統一,使得有些命令本身都能猜出來,這就是好的設計帶來的福利。。但Jenkins給人的感受就是開始的時候沒有設計得很好,後面在不斷地打補丁,致使一件事情有好幾種不一樣的作法,對不熟悉的人來說無所適從。沒有統一的風格,到處都是意外,使得整個系統看起來既龐雜又沒有章法,固然這也跟它出來的時間比較長有關。雖然它可能不是最好的,但它是免費的,所以不能要求過高。html
-
因爲種種緣由,個人Jenkins安裝碰到了各類各樣的問題,爲此我查看了大量的資料。但遺憾的是每一個人安裝Jenkins的方法都有些不一樣,很難找到一篇文章能解決全部問題。在我看來,Jenkins的安裝有兩三個關鍵之處,很是容易出錯,必定要理解透徹才能成功。java
-
本文分紅兩部分,第一部分講正常安裝步驟,若是一切順利,就不須要看第二部分了。我只能說恭喜你,你的運氣太好了。第二部分是講各類問題及解決辦法,這應該是本文最有價值的部分。node
1、kubernetes上部署Jenkins
1. 安裝在什麼地方?
-
容器化是大勢所趨,它不但包括應用程序的容器化,還包括與之相關的工具的容器化。當把Jenkins部署在kubernetes上時,Jenkins的主節點會根據狀況自動生成子節點(新的容器)來完成任務,任務結束後會自動銷燬子節點。git
-
我先在Windows上部署了VirtulBox虛機,並用Vagrant來管理虛機,再在虛機上部署了kubernetes。並經過Vagrant設置虛機和宿主機之間的網絡共享,這樣就能夠在宿主機上用遊覽器直接訪問kubernetes上的Jenkins。另外還要把宿主機的硬盤掛載到Jenkins上,這樣Jenkins的物理存儲仍是在宿主機上,即便虛機出了問題,全部的配置和數據都不會丟失。github
2. 選擇鏡像文件
-
這個看起來不是問題,可是一不留神就容易出錯。我就是由於選錯了鏡像,致使安裝了不少遍,最後才成功,在本文的第二部分會詳細說明。我最終用的鏡像文件是「jenkinsci/jenkins:2.154-slim」,後來發現這個是比較舊的版本,新的鏡像 是「jenkins/jenkins:lts」, 但由於已經安裝成功了,就沒有再換。Jenkins真的很坑人,有三個鏡像「Jenkins」,「jenkinsci/jenkins」, 「jenkins/jenkins」, 其中正確的是"jenkins/jenkins"。web
-
選好鏡像以後,能夠先運行下面命令,下載Jenkins鏡像文件到本地(虛機上)。docker
[root@k8s-master01 ~]# docker pull jenkinsci/jenkins:2.154-slim
3. 安裝Jenkins鏡像:
-
在安裝以前,須要先把宿主機的Jenkins安裝目錄掛載到虛機上,這樣能夠在本地直接操做Jenkins。shell
-
下面是Vagrant的配置文件(Vagrantfile)中的設置,它把宿主機的app目錄掛載到虛機的"/home/vagrant/app"。Jenkins就安裝在app目錄下。api
config.vm.synced_folder "app/", "/home/vagrant/app", id: "app"
- 下面就是在宿主機上安裝好了的Jenkins目錄
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tiCuIjvR-1604022842619)(assets/1805487-20191104161510729-548698586.jpg)]bash
- 安裝Jenkins鏡像分紅四部分,建立服務帳戶,安裝持久卷,安裝部署和安裝服務,須要按順序進行。其中的關鍵是建立服務帳戶,這個是必須的,沒有它不會成功。不知爲何網上的有些文章沒有提到它。
一、服務帳戶配置文件(service-account.yaml):
kind: ClusterRole apiVersion: rbac.authorization.kubernetes.io/v1 metadata: namespace: default name: service-reader rules: - apiGroups: [""] # "" indicates the core API group resources: ["services"] verbs: ["get", "watch", "list"] - 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"]
這裏建立了一個名爲「service-reader」的「ClusterRole」,並把特定的權限(例如[「get」, 「watch」, 「list」])賦給特定的資源(例如[「services」])。
運行以下命令,建立一個名爲「service-reader-pod」的集羣角色綁定,它的「clusterrole」是「service-reader」,它的名字是「default:default」,其中第一個「default」是名空間(namespace),第二個「default」是服務帳戶名字,後面的部署配置文件會引用這個名字(default)。這裏因爲我沒有給Jenkins建立單獨的名空間,所以它用的默認名空間(「default」)。
[root@k8s-master01 ~]# kubectl create clusterrolebinding service-reader-pod --clusterrole=service-reader --serviceaccount=default:default
關於服務帳戶的權限定義,請參閱「Kubernetes plugin for Jenkins」 .
二、持久卷配置文件(jenkins-volumn.yaml)
apiVersion: v1 kind: PersistentVolume metadata: name: kubernetesdemo-jenkins-pv labels: app: kubernetesdemo-jenkins spec: capacity: storage: 1Gi # volumeMode field requires BlockVolume Alpha feature gate to be enabled. volumeMode: Filesystem accessModes: - ReadWriteOnce storageClassName: standard local: path: /home/vagrant/app/jenkins nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - minikube --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: kubernetesdemo-jenkins-pvclaim labels: app: kubernetesdemo-jenkins spec: accessModes: - ReadWriteOnce # storageClassName: local-storage resources: requests: storage: 1Gi #1 GB
三、部署配置文件(jenkins-deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubernetesdemo-jenkins-deployment
labels:
app: kubernetesdemo-jenkins
spec:
selector:
matchLabels:
app: kubernetesdemo-jenkins
strategy:
type: Recreate
template:
metadata:
labels:
app: kubernetesdemo-jenkins
spec:
serviceAccountName: default # 服務帳戶的名字是default
containers:
- image: jenkinsci/jenkins:2.154-slim
name: kubernetesdemo-jenkins-container
imagePullPolicy: Never
ports:
- containerPort: 8080
- containerPort: 50000
volumeMounts:
- name: kubernetesdemo-jenkins-persistentstorage
mountPath: /var/jenkins_home
volumes:
- name: kubernetesdemo-jenkins-persistentstorage
persistentVolumeClaim:
claimName: kubernetesdemo-jenkins-pvclaim
注意,這裏引用了服務帳戶「default」(serviceAccountName: default)。
四、服務配置文件(jenkins-service.yaml):
apiVersion: v1
kind: Service
metadata:
name: kubernetesdemo-jenkins-service
labels:
app: kubernetesdemo-jenkins
spec:
type: NodePort
selector:
app: kubernetesdemo-jenkins
ports:
- port: 8080
name: http
protocol : TCP
nodePort: 30080
targetPort: 8080
- port: 50000
name: agent
protocol: TCP
targetPort: 50000
-
這裏面的一個關鍵點是部署和服務都暴露了兩個容器端口,一個是8080,另外一個是50000. 「8080」是外部訪問Jenkins的端口,「50000」是Jenkins內部集羣之間的互相通訊端口。這裏的Jenkins集羣不須要你搭建,而是Jenkins根據須要自動生成的,所以這兩個端口是必須配置的。這裏的配置命令都是比較標準的kubernetes配置,所以沒有詳細解釋。
-
若是你想了解kubernetes命令詳情(包括Vagrant配置),請參閱「經過搭建MySQL掌握kubernetes(Kubernetes)重要概念(上):網絡與持久卷」.
-
運行下面命令建立Jenkins:
[root@k8s-master01 ~]# kubectl apply -f jenkins-volume.yaml [root@k8s-master01 ~]# kubectl apply -f jenkins-deployment.yaml [root@k8s-master01 ~]# kubectl apply -f jenkins-service.yaml
五、驗證安裝
一、得到Jenkins的Pod名
[root@k8s-master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE envar-demo 1/1 Running 15 27d kubernetesdemo-backend-deployment-6b99dc6b8c-tbl4v 1/1 Running 7 11d kubernetesdemo-database-deployment-578fc88c88-mm6x8 1/1 Running 9 16d kubernetesdemo-jenkins-deployment-675dd574cb-bt7rx 1/1 Running 2 24h
二、查看Jenkins日誌
[root@k8s-master01 ~]# kubectl logs kubernetesdemo-jenkins-deployment-675dd574cb-bt7rx Running from: /usr/share/jenkins/jenkins.war webroot: EnvVars.masterEnvVars.get("JENKINS_HOME") Nov 02, 2019 1:33:30 AM org.eclipse.jetty.util.log.Log initialized INFO: Logging initialized @3749ms to org.eclipse.jetty.util.log.JavaUtilLog 。。。 INFO: Invalidating Kubernetes client: kubernetes null Nov 02, 2019 1:35:50 AM hudson.WebAppMain$3 run INFO: Jenkins is fully up and running --> setting agent port for jnlp --> setting agent port for jnlp... done
- 當看到「INFO: Jenkins is fully up and running」,就說明Jenkins已經運行好了,Jenkins的第一次啓動須要必定時間,要耐心等待。
四、登陸
-
前面已經講過,你能夠在Vagrant裏設置宿主機和虛機之間的網絡互訪,個人虛機的地址是「192.168.50.4」,「30080」是Jenkins服務的NodePort的對外地址,所以能夠用「http://192.168.50.4:30080/」 訪問Jenkins。
-
登陸以前先要得到初始口令,你能夠在Jenkins的「secrets\initialAdminPassword」目錄裏得到管理員用戶初始口令,我掛載Jenkins的宿主機目錄是「E:\app2\kub\app\jenkins」, 所以口令文件是「E:\app2\kub\app\jenkins\secrets\initialAdminPassword」。口令是「072d7157c090479195e0acaa97bc1049」。第一次登陸以後,須要從新設置用戶和口令。
五、安裝推薦插件
- 登陸以後,先要安裝必要的插件才能完成整個安裝工程, 直接選「Install suggested plugins」就能夠了。
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-4t1zTsP4-1604022842623)(assets/1805487-20191104161511011-955506293.jpg)]
六、安裝Kubernetes Plugin
- 用管理員帳戶登陸 Jenkins主頁面後
- Manage Jenkins-》Manage Plugins-》Available, 勾選安裝「Kubernetes plugin」便可。
- 下圖是安裝以後的圖:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Ii29iaLB-1604022842625)(assets/1805487-20191104161511271-718333641.jpg)]
七、配置Kubernetes Plugin
- 用管理員帳戶登陸 Jenkins Master主頁面後,找到
- Manage Jenkins-》Configure System-》,而後配置Kubernetes Plugin。以下圖所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-18KcqQ3k-1604022842628)(assets/1805487-20191104161511519-994203382.jpg)]
-
這是最重要的一個配置,決定整個安裝的成敗。默認的「name」是「Kubernetes「,這個不須要修改,但之後配置Pipelines時要用到。「Kubernetes URL」用 「https://kubernetes.default」 就能夠了。設置以後點擊「Test Connection」,見到「Connection test successful」就成功了。
-
「Jenkins URL」是從外部(從虛擬機而不是宿主機)訪問Jenkins的地址。
你能夠用以下命令,找到Kubernetes的「Jenkins Url」:
[root@k8s-master01 ~]# sudo minikube service kubernetesdemo-jenkins-service --url http://10.0.2.15:30080 http://10.0.2.15:32289
-
另一個參數是「Jenkins tunnel」,這個參數是Jenkins Master和Jenkins Slave之間通訊必須配置的,但不知道爲何,網上的不少文章都沒提這個參數,也許是Jenkins的版本不一樣,有些版本可能不須要。
-
查看容器名
[root@k8s-master01 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d15e30169568 f793ea0abe00 "/sbin/tini -- /usr/…" 15 minutes ago Up 15 minutes kubernetes_kubernetesdemo-jenkins-container_kubernetesdemo-jenkins-deployment-675dd574cb-2thn2_default_fb10e438-0231-4fd2-8dbd-d9e2f0bb9d09_0
- 查看容器地址:
[root@k8s-master01 ~]# docker inspect d15e |grep _8080 "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP_ADDR=10.100.3.79", "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP=tcp://10.100.3.79:8080", "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP_PROTO=tcp", "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP_PORT=8080",
- 根據上面信息,Jenkins的地址是「tcp://10.100.3.79:8080」,把8080換成50000就能夠了。最終結果是「10.100.3.79:50000」,注意不要添加「http」。
八、測試Jenkins:
- 如今Jenkins已經所有安裝好了, 下面進行測試。在Jenkins主頁面點擊「New Item」建立新項目,以下圖所示,輸入項目名,而後選擇「Pipeline」。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cVgAH5QW-1604022842630)(assets/1805487-20191104161511847-490339661.jpg)]
- 進入項目配置頁面,以下圖所示,腳本文件是jenkinsfile-test:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xKIFaGVf-1604022842632)(assets/1805487-20191104161512122-866957011.jpg)]
-
這是最簡單的測試,它直接使用Jenkins主節點(主節點名是master),不須要啓動子節點,所以基本上都不會有什麼問題。
-
在Jenkins主頁面選項目「test」,而後選「Build Now」運行項目,再到「Console Output」中查看結果以下:
Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline[Pipeline] podTemplate[Pipeline] { [Pipeline] nodeRunning on Jenkins in /var/jenkins_home/workspace/test [Pipeline] { [Pipeline] stage[Pipeline] { (Run shell)[Pipeline] sh+ echo hello world. hello world. [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] } [Pipeline] // podTemplate [Pipeline] End of Pipeline Finished: SUCCESS
九、測試子節點
- 這是複雜一點的測試,須要啓動子節點,這個才能真正檢測出安裝的成敗。先建立一個新的項目「slave-test」。
def POD_LABEL = "testpod-${UUID.randomUUID().toString()}" podTemplate(label: POD_LABEL, cloud: 'kubernetes', containers: [ containerTemplate(name: 'build', image: 'jfeng45/kubernetesdemo-backend:1.0', ttyEnabled: true, command: 'cat'), containerTemplate(name: 'run', image: 'jfeng45/kubernetesdemo-backend:1.0', ttyEnabled: true, command: 'cat') ]) { node(POD_LABEL) { stage('build a go project') { container('build') { stage('Build a go project') { sh 'echo hello' } } } stage('Run a Golang project') { container('run') { stage('Run a Go project') { sh '/root/main.exe' } } } } }
-
上面是腳本(jenkins-salve-test)。其中「POD_LABEL」取任何名字均可以(在Kubernetes-plugin 1.17.0 版本以後,系統會自動命名,但之前須要本身取名),「cloud: ‘kubernetes’」要與前面定義的「Kubernetes Plugin」 相匹配。它有兩個stage,一個是「build」,另外一個是「run」。在「podTemplate」裏定義了每個stage的鏡像(這樣後面的stage腳本里就能夠引用),這裏爲了簡便把兩個鏡像設成是同樣的。由於是測試,第一個stage只是輸出「echo hello」, 第二個運行鏡像「jfeng45/kubernetesdemo-backend:1.0」裏的main.exe程序。
-
在Jenkins主頁面選項目「slave-test」,而後選「Build Now」運行項目,再到「Console Output」中查看結果以下:
Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline[Pipeline] podTemplate[Pipeline] { [Pipeline] node Still waiting to schedule task ‘testpod-f754a7a4-6883-4be0-ba4f-c693906041ae-fjwqs-kbb7l’ is offline Agent testpod-f754a7a4-6883-4be0-ba4f-c693906041ae-fjwqs-kbb7l is provisioned from template Kubernetes Pod Template Agent specification [Kubernetes Pod Template] (testpod-f754a7a4-6883-4be0-ba4f-c693906041ae): * [build] jfeng45/kubernetesdemo-backend:1.0 * [run] jfeng45/kubernetesdemo-backend:1.0 Running on testpod-f754a7a4-6883-4be0-ba4f-c693906041ae-fjwqs-kbb7l in /home/jenkins/workspace/slave-test [Pipeline] { [Pipeline] stage[Pipeline] { (build a go project) [Pipeline] container[Pipeline] { [Pipeline] stage [Pipeline] { (Build a go project)[Pipeline] sh + echo heollo heollo [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // container [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Run a Golang project)[Pipeline] container [Pipeline] { [Pipeline] stage[Pipeline] { (Run a Go project) [Pipeline] sh + /root/main.exe time="2019-11-03T01:56:59Z" level=debug msg="connect to database " time="2019-11-03T01:56:59Z" level=debug msg="dataSourceName::@tcp(:)/?charset=utf8" time="2019-11-03T01:56:59Z" level=debug msg="FindAll()" time="2019-11-03T01:56:59Z" level=debug msg="user registere failed:dial tcp :0: connect: connection refused" [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // container [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] } [Pipeline] // podTemplate [Pipeline] End of Pipeline Finished: SUCCESS
-
運行成功,測試階段就完成了。
-
用腳原本寫Pipeline有兩種方法,「Scripted Pipleline」和「Declarative Pipleline」,這裏用的是第一種方法。詳情請見「Using a Jenkinsfile」. 「Declarative Pipleline」是新的方法,我在之後的文章裏會講到。這裏由於是測試,只要經過了就行。
十、沒必要須的安裝步驟
- 還有些安裝步驟在某些文章中提到了,但它們只是錦上添花,不是必須的。若是你的配置出現了問題,不要懷疑是這些步驟沒執行形成的。
- 配置名空間(namespace):
有些安裝步驟爲Jenkins配置了單獨的名空間,這樣固然更好,但你即便沒有配置也不會出現問題。 - Kubernetes server certificate key:
有些安裝步驟提到要配置「Kubernetes server certificate key 」,但我並無設置它,也沒有影響運行。
2、常見問題
1.、Jenkins版本不對
- 最開始用的是jenkins:2.60.3-alpine(這個已是Jenkins鏡像的最高版本了),這個版本過低,在安裝插件時基本上都不成功,以下圖
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-NP9Coq7O-1604022842635)(assets/1805487-20191104161512328-863345067.jpg)]
-
後來換成jenkins:latest,這個應該是最新的吧,結果 版本仍是同樣的,只不過Linux不是Apline的。
-
後來終於明白了是鏡像錯了(而不是版本的問題),是要用Jenkinsci, 而不是Jenkins。我用了當時排在第一位的jenkinsci/jenkins:2.150.1-slim,安裝以後,上面的插件錯誤所有消失了,真不容易。
二、不支持Kubernetes Plugin
- 但當安裝Kubernetes Plugin插件時,提示須要 2.150.3(個人是2.150.1),這也太坑了。只好再次重裝,此次用的是jenkinsci/jenkins:2.154-slim,還好終於成功了。不過這個其實仍是之前的鏡像,最新的在「jenkins/jenkins」。
三、不能訪問 Kubernetes
- 錯誤信息以下
Forbidden!Configured service account doesn't have access. Service account may have been revoked. User "system:serviceaccount:default:default" cannot get services in the namespace "default"
-
詳情請參見Kubernetes log, User 「system:serviceaccount:default:default」 cannot get services in the namespace。
-
錯誤緣由是沒有創建service account。解決辦法是先建立「service-account.yaml」文件,而後運行以下命令:
[root@k8s-master01 ~]# kubectl create clusterrolebinding service-reader-pod --clusterrole=service-reader --serviceaccount=default:default
- 再次運行,錯誤消失。
四、Jenkins URL地址不對
- 在Jenkins主頁面,進入Manage Jenkins-》System Log-》All Jenkins Logs, 錯誤信息以下。
SEVERE: http://192.168.50.4:30080/ provided port:50000 is not reachable java.io.IOException: http://192.168.50.4:30080/ provided port:50000 is not reachable at org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver.resolve(JnlpAgentEndpointResolver.java:303) at hudson.remoting.Engine.innerRun(Engine.java:527) at hudson.remoting.Engine.run(Engine.java:488)
- 這個錯誤主要是和Kubernetes-plugin配置有關。在Jenkins主頁面,進入Manage Jenkins-》Configure System》,在「http://192.168.50.4:30080/configure」 裏有兩個「Jenkins URL」,不要弄混了。
- 第一個是「Jenkins Location」下的「Jenkins URL」, 它是宿主機訪問Jenkins的地址。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ue9K2Qus-1604022842636)(assets/1805487-20191104161512810-1538987155.jpg)]
- 第二個是「Cloud」下的「Jenkins URL」, 它是從虛擬機訪問Jenkins的地址。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iesQJCHX-1604022842638)(assets/1805487-20191104161513042-1391358615.jpg)]
-
在上圖中,我開始時用的是「http://192.168.50.4:30080/」 ,但這個是從宿主機訪問Jenkins的Url,不是從虛機內部訪問的Url。
-
你能夠用以下命令,找到Kubernetes的「Jenkins Url」
[root@k8s-master01 ~]# sudo minikube service kubernetesdemo-jenkins-service --url http://10.0.2.15:30080 http://10.0.2.15:32289
- 鍵入以下命令測試URL。
[root@k8s-master01 ~]# curl http://10.0.2.15:30080 <html><head><meta http-equiv='refresh' content='1;url=/login?from=%2F'/><script>window.location.replace('/login?from=%2F');</script></head><body style='background-color:white; color:white;'> Authentication required <!-- You are authenticated as: anonymous Groups that you are in: Permission you need to have (but didn't): hudson.model.Hudson.Read ... which is implied by: hudson.security.Permission.GenericRead ... which is implied by: hudson.model.Hudson.Administer --> </body></html>
- 這就說明URL是好的。
五、不能鏈接slave
- 「Jenkins Url」改了以後,地址是對的,但仍是不通。運行項目時,頁面顯示以下信息:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uVTdWHxm-1604022842640)(assets/1805487-20191104161513310-1214686907.jpg)]
- 「Console Output」(在Jenkins->salve-test->#13中,其中#13是build #)顯示以下信息:
Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline[Pipeline] podTemplate[Pipeline] { [Pipeline] node Still waiting to schedule task ‘testpod-d56038a0-45a2-41d1-922d-2879e3610900-0hr0m-sfv8s’ is offline
- 後來發現還有一個參數要填寫,就是「Jenkins tunnel」。以下圖所示。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-i8euYrDh-1604022842641)(assets/1805487-20191104161513536-336397202.jpg)]
-
填寫以後原來的信息沒有了,並且出現了「Agent discovery successful」,這個信息是原來沒有的。但又有新的錯誤。
-
可用以下方法查看系統日誌,在Jenkins主頁面,選擇Manage Jenkins-》System Log-》All Jenkins Logs, 信息是這樣的:
INFO: Agent discovery successful Agent address: http://10.0.2.15 Agent port: 50000 Identity: 3e:1b:5f:48:f7:5b:f8:6d:ea:49:1d:b9:44:9a:2f:6c Oct 30, 2019 12:18:51 AM hudson.remoting.jnlp.Main$CuiListener status INFO: Handshaking Oct 30, 2019 12:18:51 AM hudson.remoting.jnlp.Main$CuiListener status INFO: Connecting to http://10.0.2.15:50000 Oct 30, 2019 12:18:51 AM hudson.remoting.jnlp.Main$CuiListener error SEVERE: null java.nio.channels.UnresolvedAddressException at sun.nio.ch.Net.checkAddress(Net.java:101) at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:622) at java.nio.channels.SocketChannel.open(SocketChannel.java:189) at org.jenkinsci.remoting.engine.JnlpAgentEndpoint.open(JnlpAgentEndpoint.java:203) at hudson.remoting.Engine.connectTcp(Engine.java:678) at hudson.remoting.Engine.innerRun(Engine.java:556) at hudson.remoting.Engine.run(Engine.java:488)
- 它的緣由是「JenkinsTunnel」的地址仍是不對,可用以下方法找到「Jenkins tunnel」地址:
[root@k8s-master01 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d15e30169568 f793ea0abe00 "/sbin/tini -- /usr/…" 15 minutes ago Up 15 minutes kubernetes_kubernetesdemo-jenkins-container_kubernetesdemo-jenkins-deployment-675dd574cb-2thn2_default_fb10e438-0231-4fd2-8dbd-d9e2f0bb9d09_0 [root@k8s-master01 ~]# docker inspect d15e |grep _8080 "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP_ADDR=10.100.3.79", "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP=tcp://10.100.3.79:8080", "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP_PROTO=tcp", "kubernetesDEMO_JENKINS_SERVICE_PORT_8080_TCP_PORT=8080",
- 根據上面信息,Jenkins容器地址是「tcp://10.100.3.79:8080」,把8080換成50000就能夠了。最終結果是「10.100.3.79:50000」,注意不要添加「http」。
詳情請見 What setting to use for jenkins tunnel?
六、鏡像問題
- 當使用的鏡像文件是「kubernetesdemo-backend:latest」或「kubernetesdemo-backend:1.0」時,「Console Output」顯示錯誤以下:
Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline[Pipeline] podTemplate[Pipeline] { [Pipeline] nodeStill waiting to schedule task All nodes of label ‘testpod-2971e0ce-e023-475f-b0ec-6118c5699188’ are offline Aborted by admin[Pipeline] // node [Pipeline] } [Pipeline] // podTemplate [Pipeline] End of Pipeline Finished: ABORTED
- 查看Pod, 錯誤是「ImagePullBackOff」:
[root@k8s-master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE envar-demo 1/1 Running 15 28d kubernetesdemo-backend-deployment-6b99dc6b8c-tbl4v 1/1 Running 7 12d kubernetesdemo-database-deployment-578fc88c88-mm6x8 1/1 Running 9 17d kubernetesdemo-jenkins-deployment-675dd574cb-bt7rx 1/1 Running 2 2d testpod-2971e0ce-e023-475f-b0ec-6118c5699188-xwwqq-vv59p 2/3 ImagePullBackOff 0 38s
- 查看鏡像:
[root@k8s-master01 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE jfeng45/kubernetesdemo-backend 1.0 f48d362fdebf 11 days ago 14.4MB kubernetesdemo-backend 1.0 f48d362fdebf 11 days ago 14.4MB kubernetesdemo-backend latest f48d362fdebf 11 days ago 14.4MB
- 這裏一共有三個「kubernetesdemo-backend」鏡像,它們的「Image ID」都是同樣的,之因此有三個是由於我用以下命令建立了tag
[root@k8s-master01 ~]# docker tag kubernetesdemo-backend jfeng45/kubernetesdemo-backend:1.0
- 但建立了以後,就只有「jfeng45/kubernetesdemo-backend:1.0」(最晚建立的)可以用在Jenkins的Pipeline腳本里,其餘兩個都會報錯。修改了正確的鏡像文件以後就運行成功了。
七、pv和pvc刪除慢
- 當用如下命令刪除pv時,命令遲遲不能返回。
[root@k8s-master01 ~]# kubectl delete pv kubernetesdemo-jenkins-pv
- 當你查看時,狀態(status)顯示一直是「Terminating」,但老是不能結束退出。pvc也是同樣。
[root@k8s-master01 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE kubernetesdemo-backend-pv 1Gi RWO Retain Bound default/kubernetesdemo-backend-pvclaim standard 13d kubernetesdemo-database-pv 1Gi RWO Retain Bound default/kubernetesdemo-database-pvclaim standard 18d kubernetesdemo-jenkins-pv 1Gi RWO Retain Terminating default/kubernetesdemo-jenkins-pvclaim standard 6d8h
- 這個主要緣由是用到它們的服務和部署還在運行,先把服務和部署刪除以後,pv和pvc的刪除操做就立刻結束,順利返回了。
八、項目源碼
-
注意,本文的程序在0.1(tag)下,這個程序的主分支之後還會修改。
-
下面是程序的目錄結構,黃色部分是與本文有關的配置文件。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-R7gxAwUj-1604022842643)(assets/1805487-20191104161513752-1790909480.jpg)]
九、參考文檔
- Kubernetes plugin for Jenkins
- 經過搭建MySQL掌握kubernetes(Kubernetes)重要概念(上):網絡與持久卷
- Using a Jenkinsfile
- Kubernetes log, User 「system:serviceaccount:default:default」 cannot get services in the namespace
- Kubernetes Jenkins plugin - slaves always offline.
- What setting to use for jenkins tunnel?
plugin/blob/master/src/main/kubernetes/service-account.yml) - 經過搭建MySQL掌握kubernetes(Kubernetes)重要概念(上):網絡與持久卷
- Using a Jenkinsfile
- Kubernetes log, User 「system:serviceaccount:default:default」 cannot get services in the namespace
- Kubernetes Jenkins plugin - slaves always offline.
- What setting to use for jenkins tunnel?
- 初試 Jenkins 使用 Kubernetes Plugin 完成持續構建與發佈