跳到主要内容

Jenkins

架构

组件说明
Master主节点,负责调度 Job、管理 Agent、提供 Web UI
Agent(Node)执行 Job 的工作节点,通过 SSH / JNLP 连接
Pipeline用 Jenkinsfile 定义的自动化流水线
Plugin插件生态,1800+ 插件扩展各种功能

Jenkinsfile(声明式)

Jenkinsfile
pipeline {
// 在任何可用 Agent 上运行
agent any

// 环境变量
environment {
REGISTRY = 'registry.example.com'
IMAGE = "${REGISTRY}/myapp"
CRED_ID = 'docker-registry-cred'
}

// 构建参数
parameters {
choice(name: 'DEPLOY_ENV', choices: ['staging', 'production'], description: '部署环境')
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试')
}

// 全局选项
options {
timeout(time: 30, unit: 'MINUTES')
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '10'))
}

stages {
stage('Checkout') {
steps {
checkout scm
}
}

stage('Lint') {
steps {
sh 'pnpm lint'
}
}

stage('Test') {
when {
expression { !params.SKIP_TESTS }
}
steps {
sh 'pnpm test -- --coverage'
}
post {
always {
junit 'test-results/*.xml'
publishHTML([
reportDir: 'coverage/lcov-report',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
}

stage('Build Docker Image') {
steps {
script {
def tag = "${env.BUILD_NUMBER}-${env.GIT_COMMIT[0..6]}"
docker.withRegistry("https://${REGISTRY}", CRED_ID) {
def img = docker.build("${IMAGE}:${tag}")
img.push()
img.push('latest')
}
}
}
}

stage('Deploy') {
when {
branch 'main'
}
steps {
// 生产环境需要人工审批
script {
if (params.DEPLOY_ENV == 'production') {
input message: '确认部署到生产环境?', ok: '部署'
}
}
sh """
kubectl set image deployment/myapp \
myapp=${IMAGE}:${env.BUILD_NUMBER}-${env.GIT_COMMIT[0..6]} \
-n ${params.DEPLOY_ENV}
"""
}
}
}

post {
success {
slackSend(color: 'good', message: "✅ 构建成功: ${env.JOB_NAME} #${env.BUILD_NUMBER}")
}
failure {
slackSend(color: 'danger', message: "❌ 构建失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}")
}
}
}

Jenkins 管理

插件推荐

类型插件用途
PipelinePipeline / Blue Ocean流水线定义和可视化
代码管理Git / GitHubSCM 集成
DockerDocker PipelineDocker 构建推送
K8sKubernetes动态 Agent Pod
通知Slack / 钉钉构建通知
安全Role-based Auth权限管理
质量SonarQube Scanner代码质量扫描

Kubernetes Agent(动态 Pod)

K8s Agent Jenkinsfile
pipeline {
agent {
kubernetes {
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: node
image: node:20-alpine
command: ['sleep', 'infinity']
- name: docker
image: docker:24-dind
securityContext:
privileged: true
"""
}
}
stages {
stage('Build') {
steps {
container('node') {
sh 'npm ci && npm run build'
}
}
}
stage('Docker') {
steps {
container('docker') {
sh 'docker build -t myapp:latest .'
}
}
}
}
}

Shared Library(共享库)

vars/deployToK8s.groovy
// 共享库:可复用的部署步骤
def call(Map config) {
sh """
kubectl set image deployment/${config.app} \
${config.app}=${config.image} \
-n ${config.namespace}
kubectl rollout status deployment/${config.app} \
-n ${config.namespace} --timeout=300s
"""
}
Jenkinsfile 中调用
@Library('my-shared-lib') _
pipeline {
stages {
stage('Deploy') {
steps {
deployToK8s(app: 'myapp', image: 'myapp:v2', namespace: 'production')
}
}
}
}

常见面试问题

Q1: Jenkins 声明式和脚本式 Pipeline 的区别?

答案

特性声明式(Declarative)脚本式(Scripted)
语法结构化的 pipeline {}自由的 Groovy 脚本
学习曲线低,有固定结构高,需要 Groovy 知识
灵活性受限,但可通过 script {} 扩展完全自由
错误检查启动前语法校验运行时才报错
推荐度✅ 推荐(日常使用)复杂逻辑使用

Q2: Jenkins 如何实现高可用?

答案

  1. Master HA:多 Master + 共享存储(NFS/EFS)或 Jenkins HA 插件
  2. Agent 弹性:K8s Agent 动态创建 Pod,按需伸缩
  3. 数据备份:定期备份 JENKINS_HOME(配置、Job 定义、插件)
  4. 配置即代码:Jenkinsfile 存在 Git,Job 用 JCasC 插件管理
  5. 分布式构建:多 Agent 分担构建负载

相关链接