美文网首页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