kubernetes上安装 Jenkins 及常见问题

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”是新的方法,我在之后的文章里会讲到。这里由于是测试,只要经过了就行。

十、没必要须的安装步骤

  • 还有些安装步骤在某些文章中提到了,但它们只是锦上添花,不是必须的。若是你的配置出现了问题,不要怀疑是这些步骤没执行形成的。
  1. 配置名空间(namespace):
    有些安装步骤为Jenkins配置了单独的名空间,这样固然更好,但你即便没有配置也不会出现问题。
  2. 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"
[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)]

  • 详情请见 Kubernetes Jenkins plugin - slaves always offline.

  • 填写以后原来的信息没有了,并且出现了“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的删除操做就立刻结束,顺利返回了。

八、项目源码

  • 完整源码的github连接

  • 注意,本文的程序在0.1(tag)下,这个程序的主分支之后还会修改。

  • 下面是程序的目录结构,黄色部分是与本文有关的配置文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7gxAwUj-1604022842643)(assets/1805487-20191104161513752-1790909480.jpg)]

九、参考文档

  1. Kubernetes plugin for Jenkins
  2. 经过搭建MySQL掌握kubernetes(Kubernetes)重要概念(上):网络与持久卷
  3. Using a Jenkinsfile
  4. Kubernetes log, User “system:serviceaccount:default:default” cannot get services in the namespace
  5. Kubernetes Jenkins plugin - slaves always offline.
  6. What setting to use for jenkins tunnel?
    plugin/blob/master/src/main/kubernetes/service-account.yml)
  7. 经过搭建MySQL掌握kubernetes(Kubernetes)重要概念(上):网络与持久卷
  8. Using a Jenkinsfile
  9. Kubernetes log, User “system:serviceaccount:default:default” cannot get services in the namespace
  10. Kubernetes Jenkins plugin - slaves always offline.
  11. What setting to use for jenkins tunnel?
  12. 初试 Jenkins 使用 Kubernetes Plugin 完成持续构建与发布
相关文章
相关标签/搜索