Jenkins定制Agent

上一节,我们实现了最简单的打包任务,在这一节,我们将定制所需的打包环境,为CD流水线做准备。

手动连接Agent

在上一节,我们使用了Kubernetes集群启动新的Slave节点,你可以沿着这条路,继续集成所需的环境,不再展开。

在本节,我们将切换另一种思路,使用手动启动&连接的方式。

首先,在Jenkins中添加一个Agent,路径是:Manage Jenkins -> Manage Nodes and Clouds -> New Node。

关键参数如下:

name:自选,这里e1

Number of executors:在这台机器上的并发执行任务数,这里选默认的2

Remote root directory:默认执行目录,这里选/home/jenkins/ateng

Labels:自选,这里executor,可以用它对Executor分组(如测试、线上等)

Launch method:Launch agent by connecting it to the master,即我们手动连接

保存后,点击进去后,能看到如下提示:

Run from agent command line:

java -jar agent.jar -jnlpUrl http://127.0.0.1:8080/computer/e1/jenkins-agent.jnlp -secret b057970bf978f53a8f945d470ac644e44c945e4b7259b216f703dedb95d0cac9 -workDir "/home/jenkins/agent"
Run from agent command line, with the secret stored in a file:

echo b057970bf978f53a8f945d470ac644e44c945e4b7259b216f703dedb95d0cac9 > secret-file
java -jar agent.jar -jnlpUrl http://127.0.0.1:8080/computer/e1/jenkins-agent.jnlp -secret @secret-file -workDir "/home/jenkins/agent"

如上所示,我们需要用上述的Secret来连接Controller(主控)节点。

我们通过Docker启动Executor节点,如下:

#!/bin/bash

NAME="jenkins_e1"
PUID="1000"
PGID="1000"

docker ps -q -a --filter "name=$NAME" | xargs -I {} docker rm -f {}
docker run \
    --name $NAME \
    --env PUID=$PUID \
    --env PGID=$PGID \
    --detach \
    --init jenkins/inbound-agent \
    -workDir=/home/jenkins/agent \
    -url http://10.1.172.136:8080 \
    b057970bf978f53a8f945d470ac644e44c945e4b7259b216f703dedb95d0cac9 \
    e1

温馨提示:上述的workDir需要与Jenkins中的配置保持一致。

当启动成功后,能看到节点上线了,如下图所示:

f

为了不调度到Controller节点,我们可以将其上的执行数量设置为0。

随后,我们尝试修改任务,如下所示:

pipeline {
    agent any 
    stages {
        stage('Test') { 
            steps {
                sh 'echo hello world'
            }
        }
    }
}

如果一起顺利,其会成功地在e1完成执行!

定制Executor的环境

从上述例子中,不难理解:真正的打包任务,是在Executor中执行的。

如果我们的打包流程需要用到git、Java、Gradle、Kubernetes的话,我们也需要将这些集成到Executor中。

我们基于Jenkins的官方基础镜像进行定制,Dockerfile如下:

FROM jenkins/inbound-agent:latest-jdk8

ENV GRADLE_VERSION=7.2
ENV K8S_VERSION=v1.22.3

# tool
USER root
RUN apt-get update && \
    apt-get install -y curl unzip docker-ce docker-ce-cli && \
    apt-get clean

# gradle
RUN curl -skL -o /tmp/gradle-bin.zip https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip && \
    mkdir -p /opt/gradle && \
    unzip -q /tmp/gradle-bin.zip -d /opt/gradle && \
    ln -sf /opt/gradle/gradle-$GRADLE_VERSION/bin/gradle /usr/local/bin/gradle

RUN chown -R 1001:0 /opt/gradle && \
    chmod -R g+rw /opt/gradle

# kubectl
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$K8S_VERSION/bin/linux/amd64/kubectl
RUN chmod +x ./kubectl
RUN mv ./kubectl /usr/local/bin

USER jenkins

如上所示:

  • 我们基于inbound-agent进行定制,这是官方的默认的Agent基础镜像
  • 随后,我们使用apt安装curl、unzip等基础工具
  • 接着,我们安装gradle、kubectl等二进制文件
  • 最后恢复默认的运行环境

制作镜像

docker build -t "coder4/jenkins-my-agent" .

制作时间会比较长

再次打包

pipeline {
    agent {label 'executor'} 
    stages {
        stage('git') {
            steps {
                sh "echo todo"
            }
        }

        stage('gradle') {
            steps {
                sh "gradle -v"
            }    
        }

        stage('k8s') { 
            steps {
                withKubeConfig([credentialsId: "60a8e9d2-0212-4ff4-aa98-f46fced97121",serverUrl: "https://kubernetes:6443"]) {
                    sh "kubectl get nodes"
                }
            }
        }
    }
}

需要指出的是:上述'k8s'阶段,使用的凭据,是我们在 Jenkins搭建入门一节中生成的证书+凭据。

运行结果

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on e1 in /home/jenkins/agent/workspace/test
[Pipeline] {
[Pipeline] stage
[Pipeline] { (git)
[Pipeline] sh
+ git version
git version 2.30.2
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (gradle)
[Pipeline] sh
+ gradle -v

Welcome to Gradle 7.2!

Here are the highlights of this release:
 - Toolchain support for Scala
 - More cache hits when Java source files have platform-specific line endings
 - More resilient remote HTTP build cache behavior

For more details see https://docs.gradle.org/7.2/release-notes.html


------------------------------------------------------------
Gradle 7.2
------------------------------------------------------------

Build time:   2021-08-17 09:59:03 UTC
Revision:     a773786b58bb28710e3dc96c4d1a7063628952ad

Kotlin:       1.5.21
Groovy:       3.0.8
Ant:          Apache Ant(TM) version 1.10.9 compiled on September 27 2020
JVM:          1.8.0_302 (Temurin 25.302-b08)
OS:           Linux 5.10.47-linuxkit amd64

[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (k8s)
[Pipeline] withKubeConfig
[Pipeline] {
[Pipeline] sh
+ kubectl get nodes
NAME       STATUS   ROLES                  AGE     VERSION
minikube   Ready    control-plane,master   6h58m   v1.21.2
[Pipeline] }
[kubernetes-cli] kubectl configuration cleaned up
[Pipeline] // withKubeConfig
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS