【问题标题】:Kubernetes Jenkins plugin - slaves always offlineKubernetes Jenkins 插件 - slaves 总是离线
【发布时间】:2016-11-24 00:28:53
【问题描述】:

我正在尝试使用 Jenkins/Kubernetes 插件与 Jenkins 协调 docker slaves。

我正在使用这个插件:https://github.com/jenkinsci/kubernetes-plugin

我的问题是所有的slave都离线了,所以作业无法执行:

我已经在我的本地机器上使用 minikube 以及在我们的操作组托管的 K8 集群上进行了尝试。我已经尝试过 Jenkins 1.9 和 Jenkins 2。我总是得到相同的结果。截图来自 Jenkins 1.642.4, K8 v1.2.0

这是我的配置...请注意,当我单击“测试连接”时,我会成功。另请注意,我不需要任何凭据(这是我能看到的与记录示例的唯一区别)。

Jenkins 日志一遍又一遍地显示以下内容:

    Waiting for slave to connect (11/100): docker-6b55f1b7fafce
Jul 20, 2016 5:01:06 PM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud$ProvisioningCallback call
Waiting for slave to connect (12/100): docker-6b55f1b7fafce
Jul 20, 2016 5:01:07 PM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud$ProvisioningCallback call
Waiting for slave to connect (13/100): docker-6b55f1b7fafce
Jul 20, 2016 5:01:08 PM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud$ProvisioningCallback call

当我运行kubectl get events 时,我看到了这个:

24s         24s        1         docker-6b3c2ff27dad3   Pod                                Normal    Scheduled           {default-scheduler }      Successfully assigned docker-6b3c2ff27dad3 to 96.xxx.xx.159
24s         23s        2         docker-6b3c2ff27dad3   Pod                                Warning   MissingClusterDNS   {kubelet 96.xxx.xx.159}   kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
23s         23s        1         docker-6b3c2ff27dad3   Pod       spec.containers{slave}   Normal    Pulled              {kubelet 96.xxx.xx.159}   Container image "jenkinsci/jnlp-slave" already present on machine
23s         23s        1         docker-6b3c2ff27dad3   Pod       spec.containers{slave}   Normal    Created             {kubelet 96.xxx.xx.159}   Created container with docker id 82fcf1bd0328
23s         23s        1         docker-6b3c2ff27dad3   Pod       spec.containers{slave}   Normal    Started             {kubelet 96.xxx.xx.159}   Started container with docker id 82fcf1bd0328

有什么想法吗?

更新:csanchez 建议的更多日志信息

 ➜  docker git:(master) ✗ kubectl get pods --namespace default -o wide
NAME                   READY     STATUS    RESTARTS   AGE       NODE
docker-6bb647254a2a4   1/1       Running   0          1m        96.x.x.159

➜  docker git:(master) ✗ kubectl log docker-6bafbac10b392

    Jul 20, 2016 6:45:10 PM hudson.remoting.jnlp.Main$CuiListener status
INFO: Connecting to 96.x.x.159:50000 (retrying:10)
java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)

我得看看这个50000端口是干什么用的??

【问题讨论】:

  • 您需要检查您的 pod 连接失败的原因。 kubectl get pods 和检查失败 pod 的日志
  • 已更新日志信息,谢谢!
  • 知道了,@csanchez!所以问题是 jenkins 也在 k8 中运行,所以端口 50000 是动态的。将 jenkins 隧道更改为 k8 分配的端口解决了问题。

标签: jenkins docker kubernetes


【解决方案1】:

在 Kubernetes 中运行 jenkins 时,jenkins master 和 slave 都可以解析服务名。

最好的配置方法是使用内部 DNS 并将 jenkins url 设置为:

http://jenkins:8080

(假设你调用了你的服务 jenkins,并且你在服务上的端口是 8080)

不需要隧道。

这种方法的好处是它可以在 jenkins 重新启动后不重新配置。

第二个好处是您不必将 Jenkins 暴露给外界,从而限制了安全风险。

【讨论】:

    【解决方案2】:

    我只是想为以上新手的答案添加一点解释。

    在暴露jenkins UI的同时,还需要暴露内部端口50000 这是一个用于 jenkins 部署的简单服务:

    apiVersion: v1
    kind: Service
    metadata:
      name: jenkins
      namespace: jenkins
    spec:
      type: NodePort
      ports:
        - port: 8080
          name: "http"
          nodePort: 30000
          targetPort: 8080
        - port: 50000
          name: "slave"
          nodePort: 30010
          targetPort: 50000
      selector:
        app: jenkins
    

    对于 Jenkins UI 的外部访问,上述配置中使用了nodePort。我将端口 8080 暴露给 nodePort 30000(jenkins UI 现在将在 node_ip:30000 上可用)并将 pod 端口 50000 暴露给 nodeport 30010。

    创建 svc 后:

    $ kubectl get svc -n jenkins
    NAME      CLUSTER-IP    EXTERNAL-IP   PORT(S)                          AGE
    jenkins   10.233.5.94   <nodes>       8080:30000/TCP,50000:30010/TCP   23m
    

    现在将jenkins_ip:30010 添加为Jenkins Tunnel

    【讨论】:

    • 我正是这样做的 Junaid。但是我的奴隶仍然显示离线。还有其他我可能遗漏的东西吗?
    • @Daggerhunt,slave 真的被创建了吗?你用kubectl get po -n &lt;namespace&gt;命令确认了吗?
    【解决方案3】:

    您需要同时公开端口 8080 和 50000,如插件示例配置 https://github.com/jenkinsci/kubernetes-plugin/blob/master/src/main/kubernetes/jenkins.yml 中所述

    【讨论】:

    • 链接已损坏
    【解决方案4】:

    感谢@csanchez,我找到了解决方案。

    问题是我在 k8 中运行 jenkins 服务器,而我没有在 k8 中指定固定端口(我让 k8 选择端口)。所以更改詹金斯隧道的配置解决了它。

    更好的解决方案是按照建议修复端口,然后进行更改。

    【讨论】:

    • 我试过了。我还将 JNLP 从代理的 TCP 端口] 更改为随机。我还使用 NodePort 公开了 jnlp 和 UI 端口,我在配置中使用了这些端口,但我仍然无法让它工作。任何帮助将不胜感激。
    【解决方案5】:

    因为,kubectl -n jenkins-namespace get services 显示:

    NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
    cicd-jenkins         ClusterIP   172.20.120.227   <none>        8080/TCP    128d
    cicd-jenkins-agent   ClusterIP   172.20.105.189   <none>        50000/TCP   128d
    

    您必须转到 Jenkins > 管理 Jenkins > 配置系统 (http://jenkins:8080/configure)。 然后,相应地配置 Jenkins URLjenkins tunnel(见下面的截图)

    学分https://youtu.be/MkzCVvlpiaM

    如果您使用的是 Jenkins 配置即代码 (JCasC) 插件,则可以通过 jenkinsUrljenkinsTunnel 键配置:

    jenkins:
      clouds:
      - kubernetes:
          name: cluster
          serverUrl: https://kubernetes.default
          # ....
          jenkinsUrl: http://cicd-jenkins:8080/
          jenkinsTunnel:  cicd-jenkins-agent:50000
          # ....
    

    【讨论】:

      【解决方案6】:

      我知道这是一篇旧帖子,但以上答案都没有解决我与离线 Jenkins 代理的问题 无论如何,我已经设法自己解决了这个问题,我将把解决方案留在这里!

      注意 1:我的 Kubernetes 集群在 3 个本地虚拟机上运行,​​使用 Hyper-V,我不使用 Nginx!

      注意 2: Jenkins master 正在 Kubernetes pod 上运行!

      注意 3: 你可以在这里查看我的 git 存储库:https://github.com/RazvanSebastian/Kubernetes_Cluster/tree/master/3_jenkins_setup

      1. 为 Jenkins 创建命名空间

      $ kubectl create namespace jenkins

      1. 创建一个服务帐户,因为 Jenkins master 需要创建/删除资源的权限,例如 Jenkins-Slave pods
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: jenkins
        namespace: jenkins
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: Role
      metadata:
        name: jenkins
        namespace: jenkins
      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/v1
      kind: RoleBinding
      metadata:
        name: jenkins
        namespace: jenkins
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: Role
        name: jenkins
      subjects:
      - kind: ServiceAccount
        name: jenkins
      
      1. 我们必须创建两个服务;

      NodePort 将使 Jenkins 主节点可以从 Kubernetes 集群外部访问

      apiVersion: v1
      kind: Service
      metadata:
        name: jenkins
        namespace: jenkins
      spec:
        ports:
          - protocol: TCP
            port: 8080
            targetPort: 8080
            nodePort: 30123
            name: ui
        selector:
          app: master
        type: NodePort
      

      ClusterIp,它将像内部 Jenkins-Slaves 的发现服务一样工作。 默认情况下,master 在端口 5000 上监听入站代理!

      apiVersion: v1
      kind: Service
      metadata:
        name: jenkins-discovery
        namespace: jenkins
      spec:
        selector:
          app: master
        ports:
          - protocol: TCP
            port: 50000
            targetPort: 50000
            name: slaves
      
      1. 现在我们必须为 Jenkins master 创建一个部署
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: jenkins
        namespace: jenkins
      spec:
        replicas: 1
        selector:
          matchLabels:
             app: master
        template:
          metadata:
            labels:
              app: master
          spec:
            serviceAccountName: jenkins
            containers:
              - image: jenkins/jenkins:lts
                name: jenkins
                ports:
                  - containerPort: 8080
                    name: http-port
                  - containerPort: 50000
                    name: jnlp-port
                env:
                  - name: JAVA_OPTS
                    value: -Djenkins.install.runSetupWizard=false
      

      观察 1: Jenkins 主容器必须公开两个端口:8080(UI Jenkins 端口)和 50000(用于入站代理)。如果您不公开 5000 端口,您将收到来自 Jenkins-Slaves 的离线状态

      OBSERVATION 2 : Deployment 模板中的serviceAccountName: jenkins 行将绑定到 Jenkins 创建/删除 Kubernetes 资源的权限

      1. 检查创建到 jenkins 命名空间中的资源

      $ kubectl get all -o wide --namespace=jenkins

      注意 从 Jenkins pod 复制 IP;我们将需要它来设置 Jenkins

      1. 获取Kubernetes主节点地址

      $ kubectl cluster-info | grep master

      1. 现在我们必须从 UI 配置 Jenkins。我会附加图片,但你也可以查看 git repo :)

        7.1。安装包(管理 Jenkins -> 管理插件 -> 可用):KubernetesSSH 代理

        7.2。设置主节点(管理 Jenkins -> 管理节点和云 -> 工具图标):

        7.3。设置 Kubernetes 插件(管理 Jenkins -> 配置系统 -> 在页面底部单击云部分)

      7.4。确保在创建 Jenkins 作业时,限制如下:

      【讨论】:

        【解决方案7】:

        如果您的 jenkins master 和 agent pod 在同一个集群中,那么jenkinsUrl 就足够了。

        apiVersion: v1
        kind: Service
        metadata:
          name: jenkins-prod-service
          namespace: my-prod
        spec:
          selector:
            app: jenkins-prod
          ports:
            - port: 50000
              targetPort: 50000
              name: jnlp-port
            - port: 8080
              name: http-port
              targetPort: 8080
          type: ClusterIP
        

        然后是jcasc:

        jenkinsUrl: http://jenkins-prod-service:8080/
        

        jenkins 可以计算出jenkinsTunnel 的值。你也不需要定义serverUrl

        如果使用外部集群,则需要定义jenkinsTunnel

        使用外部集群时的服务示例

        apiVersion: v1
        kind: Service
        metadata:
          name: jenkins-prod-service
          namespace: my-ns
        spec:
          selector:
            app: jenkins-prod #jenkins-master
          ports:
            - port: 50000
              nodePort: 34321    
              targetPort: 50000
              name: jnlp-port
            - port: 8080
              nodePort: 31234    
              name: http-port
              targetPort: 8080
          type: NodePort
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 2018-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多