美文网首页K8s
基于Docker, Kubernets动态创建Jenkins-A

基于Docker, Kubernets动态创建Jenkins-A

作者: 阿当运维 | 来源:发表于2023-02-09 15:11 被阅读0次

    本次实践主要介绍Docker与Kubernerts动态创建agent

    一.前言

    Jenkins的分布式架构,分为server节点和agent节点。 server节点也是可以运行构建任务的,但我们一般使其来调度任务分配给agent去做。agent在一定程度上也会减轻server节点的压力,并且可以基于容器环境随着任务的构建来动态创建agent节点,有任务时agent就会被创建出来,执行完空闲时销毁不占用资源。

    二.Jenkins-agent实现方式

    方式目前主要有三种: VM,Docker,Kubernets

    1.VM方式简单来说就是我们传统添加agent客户机的方式,添加一个静态节点。 (本次不做介绍)

    2.Docker方式是找一台有Docker环境的机器开放端口,jenkins去链接docker地址,之后的agent都是以容器的方式创建出来(这台docker主机上)

    3.Kubernets方式与docker类似,通过连接apiserver的api 来实现k8s集群内动态创建agent pod ;
    此方式有两种情况:
    a. jenkins安装在k8s集群内(直接写svc地址能访问到即可)
    b. jenkins安装在k8s集群外(需要配置创建一个连接k8s集群的凭据来连接)

    三.Docker动态创建Jenkins-Agent

    我们上面说了这种方式需Jenkins调用Docker的接口完成的,所以需要开启Docker远程访问将Docker的API暴露出去。

    1.暴露Docker的api

    vim /lib/systemd/system/docker.service
    (-H tcp://0.0.0.0:2375)为新增内容

    ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
    

    重启docker服务

    2.Jenkins安装Docker插件(略)

    3.Jenkins配置Cloud

    点击管理-管理节点

    a.节点设置

    1-jenkins-docker配置.png

    参数解读:
    Connection Timeout 连接超时时间
    Read Timeout 读操作超时时间
    Enabled 功能是否开启
    Error Duration 错误的持续时间 默认5分钟
    Container Cap 容器数量 (默认值100;负值或零代表无限制)

    b.pod模板设置

    2-jenkins-agent配置.png

    Connect method连接方式;默认的Attach Docker container
    其他设置均默认,可根据需求修改;保存退出。

    4. 测试流水线

    新增一个流水线项目(docker-slave为配置模板中的标签)

    pipeline {
        agent {
            label 'docker-slave'
        }
    
        stages {
            stage('Hello') {
                steps {
                    echo 'Hello World'
                    sh 'pwd'
                    sh 'sleep 20'
                    echo 'Finish'
                }
            }
        }
    }
    
    3-jenkins-agent结果.png

    在docker主机中创建了一个agent,执行完并销毁。

    4-jenkins_docker结果.png
    至此docker动态创建agent完成

    —————————————————————————————————————————————

    四. Kubernets动态创建Agent

    我这里的jenkins为k8s集群外搭建的,连接k8s集群需要创建一个凭据。(证书)

    1. Jenkins安装Kubernets插件(略)

    2. 创建k8s服务证书

    Kubernetes服务证书key是用来与Kubernetes API server建立连接的,生成方法是,从Kubernetes API server的/root/.kube/config文件中,获取/root/.kube/config中certificate-authority-data的内容,并转化成base64编码的文件

    2.1- 安装yaml解析工具yq

    wget -O /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v4.15.1/yq_linux_amd64
    chmod +x /usr/local/bin/yq
    

    2.2-服务端证书

    yq e '.clusters[0].cluster.certificate-authority-data' .kube/config | base64 -d > ca.crt
    

    2.3-客户端证书

    yq e '.users[0].user.client-certificate-data' .kube/config | base64 -d > client.crt
    

    2.4-key:

    yq e '.users[0].user.client-key-data' .kube/config | base64 -d > client.key
    

    2.5-生成Clinet P12认证文件:

    openssl pkcs12 -export -out cert.pfx -inkey client.key -in client.crt -certfile ca.crt
    Enter Export Password:
    Verifying - Enter Export Password:
    

    这里必须要输入密码。并且记住,这个后面jenkins配置凭据的时候要用到~

    3. 创建凭据

    创建一个jenkins用于连接k8s集群api的凭据
    进入 Jenkins 的系统管理,点击Manage Credentials; 点击Stores scoped to Jenkins列表下全局中的添加凭据


    A-jenkins-k8s-凭据.png

    4. 创建cloud

    在系统管理的节点管理点击 Add a new cloud,添加k8s集群


    B-jenkins-k8s-集群配置.png
    C-jenkins-k8s-集群配置2.png

    4.1 设置pod模板

    D-jenkins-k8s-pod模板.png

    容器运行的命令及命令参数均为默认,只有容器名和镜像是我自定义的
    注意:(容器名不要叫jnlp,不然会出现一直重启的情况或者不执行任务也一直不退出的情况)


    E-jenkins-k8s-pod模板2.png

    5.创建流水线任务进行测试

    介绍2种方式创建pod模板的方式:
    1.以上过程中直接在界面中配置保存pod模板信息,在流水线中指定配置的label来运行。
    2.直接将pod模板写在pipeline里来直接创建引用。

    5.1 方式1的形式,写一个demo流水线测试

    注意:以上在界面中配置的pod模板中label为jenkins-agent这里来指定他

    pipeline {
        agent {
             label 'jenkins-agent' 
        }
        options {
            skipDefaultCheckout()
        }
        stages {
            stage('Hello') {
                steps {
                    script{
                        sh 'whoami'
                        sh 'sleep 15'
                    }    
                }
            }
        }
    }
    
    结果:

    可以看到是2/2,两个容器,因为其中有一个是agent默认启动的jnlp的容器用来agent和master链接的容器,所以上面咱们自己定义的容器名字的时候不能叫jnlp,不然就覆盖了默认的配置,只会启动一个咱们自己的jnlp,缺少链接容器,没人干活了就。会一直不停重启。


    F-jenkins-k8s-流水线结果1.png
    G-jenkins-k8s-流水线结果2.png

    5.2 方式2的形式,写一个demo流水线测试

    这次尝试pod模板创建不在界面上进行了,来pipleine里来直接创建。

    pipeline {
        agent {
            kubernetes{
                label "javapod"
                cloud "kubernetes"
                yaml '''
    ---
    kind: Pod
    apiVersion: v1
    metadata:
      labels:
        k8s-app: k8s-slave-agent
      name: jenkinsagent
      namespace: nacos
    spec:
    containers:
      name: jenkinsagent
      image: jenkins/inbound-agent:4.10-3-jdk8
      imagePullPolicy: IfNotPresent
    '''
           }
        }
    
        options {
            skipDefaultCheckout()
        }
        stages {
            stage('Hello') {
                steps {
                    script{
                        sh 'sleep 15'                           
                    }    
                }
            }
        }
    }
    
    H-jenkins-k8s-流水线结果3.png
    至此Jenkins基于Kubernets动态创建agent环境已经基本完成。 上面一些基本配置没有配置存储,只是跑了一个demo,后续也将更新最佳实践。

    遇到的问题:

    Q1: k8s动态创建agent,配置完运行demo流水线进行测试时报错:

    
    INFO: Connecting to [http://192.168.1.28:50000](http://192.168.1.28:50000/)
    Feb 10, 2023 1:36:30 AM hudson.remoting.jnlp.Main$CuiListener error
    SEVERE: null
    java.nio.channels.UnresolvedAddressException
        at sun.nio.ch.Net.checkAddress(Net.java:104)
        at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:621)
        at java.nio.channels.SocketChannel.open(SocketChannel.java:189)
        at org.jenkinsci.remoting.engine.JnlpAgentEndpoint.open(JnlpAgentEndpoint.java:206)
        at hudson.remoting.Engine.connectTcp(Engine.java:880)
        at hudson.remoting.Engine.innerRun(Engine.java:757)
        at hudson.remoting.Engine.run(Engine.java:540)
    
    nacos/javapod-2hl99-6klw2 Pod just failed (Reason: null, Message: null) </pre>
    

    原因:可以看到是链接master的50000端口时报错了。分析:
    1.远程50000端口无法访问,如果docker或者k8s为jenkins-master检查端口是否暴露出来了。没问题
    2.防火墙原因或者安全组检查,远程telnet ip 50000。没问题
    3.Jenkins Cloud上配置jenkins地址的时候一个是8080端口,地址http://jenkins_url:8080没错,另一个应该为50000端口,地址jenkins_url:50000(应该为tcp协议去访问,如果是http协议会有这个问题)并且这个50000端口需要控制端也要开启,*系统管理 -> 全局安全设置 ** ->代理-固定端口50000

    解决:将http://jenkins_url:50000改成jenkins_url:50000 (jenkins_url替换为你的jenkins-master地址)

    Q2: 最终测试流水线的时候,agent容器可以被正常创建出来,但是没有执行我的任务,并且一直自动重启;如果尝试用sleep等类似语句hold住容器 那么它是可以一直保持不退出 ,但是任务也不执行。

    原因: Jenkins默认会启动一个用于agent和master链接的一个容器,叫jnlp。那么在Jenkins Cloud 上配置容器部分的时候,那个容器名也写成了jnlp ,这样就会冲突,导致最终创建的时候只创建一个jnlp这个容器,没有"干活"的容器了,所以会发生这个情况。

    解决: 自定义容器名的话 ,避开jnlp这个名字即可

    相关文章

      网友评论

        本文标题:基于Docker, Kubernets动态创建Jenkins-A

        本文链接:https://www.haomeiwen.com/subject/xawckdtx.html