容器化Agent #

容器化Agent是现代Jenkins部署的重要方式,提供动态、隔离、可扩展的构建环境。

为什么使用容器化Agent? #

传统Agent的问题 #

  • 环境配置复杂
  • 资源利用率低
  • 扩展困难
  • 环境不一致

容器化Agent优势 #

  • 环境标准化
  • 动态扩展
  • 资源隔离
  • 快速启动

Docker Agent #

基本使用 #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

配置选项 #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            label 'docker'
            args '-v $HOME/.m2:/root/.m2 -e MAVEN_OPTS="-Xmx1024m"'
            registryUrl 'https://registry.example.com'
            registryCredentialsId 'docker-registry'
            alwaysPull true
            customWorkspace '/tmp/custom'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Docker参数 #

参数 说明
image Docker镜像
label 节点标签
args Docker运行参数
registryUrl 镜像仓库URL
registryCredentialsId 仓库凭据
alwaysPull 总是拉取最新镜像
customWorkspace 自定义工作空间

挂载卷 #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            args '-v $HOME/.m2:/root/.m2 -v $HOME/.gradle:/root/.gradle'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

环境变量 #

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            args '-e MAVEN_OPTS="-Xmx2048m" -e JAVA_OPTS="-Xms512m"'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Dockerfile Agent #

groovy
pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile.build'
            dir 'docker'
            additionalBuildArgs '--build-arg VERSION=1.0'
            label 'docker'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Dockerfile示例:

dockerfile
FROM maven:3.8-openjdk-11

ARG VERSION

RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

ENV VERSION=${VERSION}

WORKDIR /app

Kubernetes Agent #

基本配置 #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command:
    - cat
    tty: true
'''
        }
    }
    
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn clean package'
                }
            }
        }
    }
}

多容器Pod #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command:
    - cat
    tty: true
    resources:
      requests:
        memory: "1Gi"
        cpu: "500m"
      limits:
        memory: "2Gi"
        cpu: "1"
  - name: docker
    image: docker:latest
    command:
    - cat
    tty: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  - name: kubectl
    image: bitnami/kubectl:latest
    command:
    - cat
    tty: true
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
'''
        }
    }
    
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn clean package'
                }
            }
        }
        
        stage('Docker') {
            steps {
                container('docker') {
                    sh 'docker build -t myapp .'
                }
            }
        }
        
        stage('Deploy') {
            steps {
                container('kubectl') {
                    sh 'kubectl apply -f k8s/'
                }
            }
        }
    }
}

使用YAML文件 #

groovy
pipeline {
    agent {
        kubernetes {
            yamlFile 'kubernetes/pod.yaml'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn clean package'
                }
            }
        }
    }
}

资源限制 #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command:
    - cat
    tty: true
    resources:
      requests:
        memory: "2Gi"
        cpu: "1"
      limits:
        memory: "4Gi"
        cpu: "2"
'''
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

持久化存储 #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command:
    - cat
    tty: true
    volumeMounts:
    - name: maven-repo
      mountPath: /root/.m2
  volumes:
  - name: maven-repo
    persistentVolumeClaim:
      claimName: maven-repo-pvc
'''
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

Secret挂载 #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: kubectl
    image: bitnami/kubectl:latest
    command:
    - cat
    tty: true
    volumeMounts:
    - name: kube-config
      mountPath: /root/.kube
      readOnly: true
  volumes:
  - name: kube-config
    secret:
      secretName: kube-config-secret
'''
        }
    }
    
    stages {
        stage('Deploy') {
            steps {
                sh 'kubectl get pods'
            }
        }
    }
}

ServiceAccount #

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  serviceAccountName: jenkins-deployer
  containers:
  - name: kubectl
    image: bitnami/kubectl:latest
    command:
    - cat
    tty: true
'''
        }
    }
    
    stages {
        stage('Deploy') {
            steps {
                sh 'kubectl apply -f k8s/'
            }
        }
    }
}

动态Agent选择 #

基于条件选择 #

groovy
def selectAgent() {
    if (env.BRANCH_NAME == 'main') {
        return {
            kubernetes {
                yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command: ["cat"]
    tty: true
    resources:
      limits:
        memory: "4Gi"
        cpu: "2"
'''
            }
        }
    } else {
        return {
            docker {
                image 'maven:3.8-openjdk-11'
            }
        }
    }
}

pipeline {
    agent selectAgent()
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
}

完整示例 #

groovy
pipeline {
    agent none
    
    environment {
        APP_NAME = 'myapp'
        VERSION = "${BUILD_NUMBER}"
        DOCKER_REGISTRY = 'registry.example.com'
    }
    
    stages {
        stage('Build') {
            agent {
                docker {
                    image 'maven:3.8-openjdk-11'
                    args '-v $HOME/.m2:/root/.m2'
                }
            }
            steps {
                sh 'mvn clean package -DskipTests'
                stash includes: 'target/*.jar', name: 'artifacts'
            }
        }
        
        stage('Test') {
            agent {
                kubernetes {
                    yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command: ["cat"]
    tty: true
    resources:
      requests:
        memory: "1Gi"
        cpu: "500m"
  - name: postgres
    image: postgres:14
    env:
    - name: POSTGRES_PASSWORD
      value: test
    - name: POSTGRES_DB
      value: testdb
'''
                }
            }
            steps {
                unstash 'artifacts'
                container('maven') {
                    sh '''
                        mvn test -Ddb.url=jdbc:postgresql://localhost:5432/testdb
                    '''
                }
            }
            post {
                always {
                    junit '**/target/surefire-reports/*.xml'
                }
            }
        }
        
        stage('Docker Build') {
            agent {
                kubernetes {
                    yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: docker
    image: docker:latest
    command: ["cat"]
    tty: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
'''
                }
            }
            steps {
                unstash 'artifacts'
                container('docker') {
                    withCredentials([usernamePassword(
                        credentialsId: 'docker-registry',
                        usernameVariable: 'DOCKER_USER',
                        passwordVariable: 'DOCKER_PASS'
                    )]) {
                        sh """
                            docker login -u ${DOCKER_USER} -p ${DOCKER_PASS} ${DOCKER_REGISTRY}
                            docker build -t ${DOCKER_REGISTRY}/${APP_NAME}:${VERSION} .
                            docker push ${DOCKER_REGISTRY}/${APP_NAME}:${VERSION}
                        """
                    }
                }
            }
        }
        
        stage('Deploy') {
            agent {
                kubernetes {
                    yaml '''
apiVersion: v1
kind: Pod
spec:
  serviceAccountName: jenkins-deployer
  containers:
  - name: kubectl
    image: bitnami/kubectl:latest
    command: ["cat"]
    tty: true
'''
                }
            }
            when {
                branch 'main'
            }
            steps {
                container('kubectl') {
                    sh """
                        kubectl set image deployment/${APP_NAME} \
                            ${APP_NAME}=${DOCKER_REGISTRY}/${APP_NAME}:${VERSION} \
                            -n production
                    """
                }
            }
        }
    }
    
    post {
        always {
            echo 'Build completed'
        }
    }
}

下一步学习 #

小结 #

  • 容器化Agent提供动态构建环境
  • Docker Agent适合简单场景
  • Kubernetes Agent适合复杂场景
  • 支持多容器Pod
  • 合理配置资源限制
  • 使用持久化存储优化构建速度
最后更新:2026-03-28