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

本次实践主要介绍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这个名字即可

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341