Kubernetes Jenkins插件-奴隶总是离线

jckbn6z7  于 2023-02-03  发布在  Jenkins
关注(0)|答案(8)|浏览(239)

我正在尝试使用Jenkins/Kubernetes插件与Jenkins一起编排 Docker 奴隶。
我正在使用这个插件:https://github.com/jenkinsci/kubernetes-plugin
我的问题是所有的从服务器都离线,所以作业无法执行:

我已经在我的本地机器上使用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是用来做什么的?

vc6uscn9

vc6uscn91#

我只是想为新手们在上面的答案中多加一点解释。
在公开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

3yhwsihp

3yhwsihp2#

在Kubernetes中运行jenkins时,jenkins主服务器和从服务器都可以解析服务名称。
最好的配置方法是使用内部DNS并将jenkins url设置为:

http://jenkins:8080

(假设您调用您的服务Jenkins,并且您在服务上的端口是8080)
不需要隧道。
这种方法的好处是,它可以在jenkins重新启动后继续运行,而无需重新配置。
第二个好处是您不必将Jenkins暴露给外界,从而限制了安全风险。

x8diyxa7

x8diyxa74#

多亏了@csanchez,我找到了解决办法。

问题是我在k8中运行jenkins服务器,我没有在k8中指定一个固定的端口(我让k8选择端口),所以改变jenkins隧道的配置解决了这个问题。
更好的解决方案是按照建议固定端口,然后进行更改。

wmtdaxz3

wmtdaxz35#

因为,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隧道(请参见下面的屏幕截图)

积分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
      # ....
ttisahbt

ttisahbt6#

我知道这是一个老职位,但没有一个以上的答案解决了我的问题与离线Jenkins代理无论如何,我已经设法解决这个问题,由我自己,我会离开这里的解决方案!

**注意1:**我的Kubernetes集群使用Hyper-V本地运行在3个虚拟机上,而我不使用Nginx!
**注2:**Jenkins主机正在Kubernetes pod上运行!
**Note 3:**你可以在这里 checkout 我的git仓库:https://github.com/RazvanSebastian/Kubernetes_Cluster/tree/master/3_jenkins_setup

1.为Jenkins创建命名空间
$ kubectl create namespace jenkins
1.创建service-account,因为Jenkins master需要权限才能创建/删除资源,例如Jenkins-Slave pod

---
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允许从Kubernetes群集外部访问Jenkins主服务器

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的发现服务一样工作。* 默认情况下,主服务器在端口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主机创建一个部署

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的脱机状态
**观察结果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作业时满足如下限制:

gev0vcfq

gev0vcfq7#

如果您的jenkins主Pod和代理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
avwztpqn

avwztpqn8#

请记住两件事:

为什么会发生这种情况?

这是因为k8创建了一个Jenkins从代理,无法通过jnlp端口连接到您的主Jenkins。

您可以通过以下链接了解Jenkins如何调用k8 How Does Jenkins Kubernetes Pod Agents Work?

如何解决?
  • 首先你应该确保你的jnlp端口被导出。在下面的例子service.yaml文件中,我配置了pordtarget pord

  • 其次,使用kubectl get service -n $namespace获取Jenkins群集IP并在Jenkins

    中对其进行配置

并且还在Jenkins配置页面中配置Jenkins URL。

相关问题