第九章:分布式构建

构建高可用、高性能的分布式 Jenkins 架构,包括 Kubernetes 和 Docker 部署。

最后更新: 2024-01-15
页面目录

分布式构建

本章介绍如何构建高可用、高性能的 Jenkins 分布式架构,应对大规模 CI/CD 需求。

分布式架构概述

单节点瓶颈

┌─────────────────────────────────────────────────────────────────┐
│                    单节点架构                                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    Jenkins Master                        │   │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐         │   │
│  │  │Job Queue│ │ Scheduler│ │Executor1│ │Executor2│        │   │
│  │  └─────────┘ └─────────┘ └─────────┘ └─────────┘         │   │
│  └─────────────────────────────────────────────────────────┘   │
│                            ↓                                    │
│                    所有构建都在主节点执行                         │
└─────────────────────────────────────────────────────────────────┘

问题:
❌ CPU/内存瓶颈
❌ 磁盘 I/O 瓶颈
❌ 单点故障
❌ 无法并行构建

分布式架构优势

┌─────────────────────────────────────────────────────────────────┐
│                    分布式架构                                    │
│                                                                  │
│  ┌───────────────────┐                                          │
│  │  Jenkins Master   │  调度、配置、管理                           │
│  │     (小型)        │                                          │
│  └─────────┬─────────┘                                          │
│            │                                                     │
│    ┌───────┼───────┬────────┬────────┐                          │
│    ↓       ↓       ↓        ↓        ↓                          │
│ ┌─────┐ ┌─────┐ ┌─────┐  ┌─────┐ ┌─────┐                        │
│ │Node1│ │Node2│ │Node3│  │ K8s │ │ K8s │                        │
│ │Linux│ │Win  │ │Mac  │  │ Pod │ │ Pod │                        │
│ │ x4  │ │ x2  │ │ x2  │  │ x10 │ │ x10 │                        │
│ └─────┘ └─────┘ └─────┘  └─────┘ └─────┘                        │
│                                                                  │
│  优势:                                                          │
│  ✅ 水平扩展                                                     │
│  ✅ 负载均衡                                                     │
│  ✅ 平台隔离                                                     │
│  ✅ 高可用                                                       │
└─────────────────────────────────────────────────────────────────┘

高可用架构

架构设计

                         ┌─────────────────┐
                         │   Load Balancer  │
                         │    (Nginx/ELB)   │
                         └────────┬────────┘
              ┌───────────────────┼───────────────────┐
              │                   │                   │
     ┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐
     │  Jenkins Master │ │  Jenkins Master │ │  Jenkins Master │
     │    (Active)      │ │    (Standby)    │ │    (Standby)    │
     │                 │ │                 │ │                 │
     └────────┬────────┘ └────────┬────────┘ └────────┬────────┘
              │                   │                   │
              └───────────────────┼───────────────────┘
        ┌─────────────────────────┼─────────────────────────┐
        │                         │                         │
┌───────▼───────┐         ┌───────▼───────┐         ┌───────▼───────┐
│   Linux Farm  │         │ Windows Farm  │         │  K8s Cluster  │
│    (SSH)       │         │    (SSH)      │         │   (JNLP)       │
└───────────────┘         └───────────────┘         └───────────────┘

高可用配置

# docker-compose.yml for HA
version: '3.8'
services:
  jenkins-master-1:
    image: jenkins/jenkins:lts
    container_name: jenkins-master-1
    environment:
      - JENKINS_OPTS="--prefix=/jenkins"
      - JENKINS_HOME=/var/jenkins_home
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - "8080:8080"
      - "50000:50000"
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/login"]
      interval: 30s
      timeout: 10s
      retries: 5

  jenkins-master-2:
    image: jenkins/jenkins:lts
    container_name: jenkins-master-2
    environment:
      - JENKINS_OPTS="--prefix=/jenkins"
      - JENKINS_HOME=/var/jenkins_home
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == worker
    restart: unless-stopped

volumes:
  jenkins_home:

共享存储配置

# NFS 存储配置
# /etc/exports
/srv/jenkins *(rw,sync,no_subtree_check,no_root_squash)

# K8s PersistentVolume
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-home
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  resources:
    requests:
      storage: 100Gi

Kubernetes 部署方案

Helm 部署

# 添加 Jenkins 仓库
helm repo add jenkins https://charts.jenkins.io
helm repo update

# 自定义配置
helm show values jenkins/jenkins > values.yaml

# 安装
helm install jenkins jenkins/jenkins \
  -n jenkins \
  --create-namespace \
  -f values.yaml

values.yaml 配置

# values.yaml
controller:
  image: jenkins/jenkins:lts-jdk17
  tagLabel: jdk17
  
  persistence:
    enabled: true
    storageClass: nfs-client
    size: 100Gi
  
  resources:
    requests:
      cpu: 500m
      memory: 512Mi
    limits:
      cpu: 2000m
      memory: 4Gi
  
  serviceType: ClusterIP
  
  ingress:
    enabled: true
    hostName: jenkins.example.com
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
  
  route:
    enabled: true
    termination: edge
  
  javaOpts: >-
    -Xmx2g
    -Xms1g
    -Dhudson.footerURL=https://example.com
    -Djenkins.ui.refresh=true

  installPlugins:
    - kubernetes
    - workflow-aggregator
    - git
    - configuration-as-code
    - blueocean
    - slack

agent:
  enabled: true
  defaultAgent:
    enabled: true
    image: jenkins/inbound-agent
    tagLabel: jdk11

persistence:
  enabled: true
  storageClass: nfs-client

Kubernetes Agent 配置

# Agent Pod 模板
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: jenkins-agent-templates
  namespace: jenkins
data:
  maven-template: |
    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: jnlp
        image: jenkins/inbound-agent:latest-jdk11
      - name: maven
        image: maven:3.8-openjdk-11
        command: sleep
        args: infinity
        resources:
          requests:
            memory: "1Gi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        volumeMounts:
        - name: maven-cache
          mountPath: /root/.m2
      volumes:
      - name: maven-cache
        emptyDir: {}

构建农场管理

节点分组策略

分组 标签 用途 节点数
通用构建 build 普通构建任务 4-8
Docker 构建 docker 需要 Docker 的任务 2-4
特殊构建 special 特殊环境需求 1-2
K8s 动态 k8s 按需创建 弹性
部署节点 deploy 部署任务 2

负载均衡策略

// 优先选择空闲度高的节点
pipeline {
    agent {
        label {
            label 'docker'
            nodeSelector 'disktype=ssd'
            softRequisition 'maven'
        }
    }
}

节点健康检查

系统管理 → 节点管理 → 配置节点
    ✓ 记录节点健康
        ✓ 使用自定义启动延迟: 30
        ✓ 启动失败阈值: 3

性能优化

Executor 数量配置

CPU 核心 内存 推荐 Executor 数 说明
2 核 4 GB 2 基础配置
4 核 8 GB 4 标准配置
8 核 16 GB 8 高性能配置
16+ 核 32+ GB CPU 核心数 专业构建服务器

内存配置

# /etc/default/jenkins
JENKINS_HOME=/var/jenkins_home
JENKINS_PORT=8080
JENKINS_OPTS="-Xmx4g -Xms2g -XX:+UseG1GC"

并行构建优化

pipeline {
    options {
        // 禁用并发构建(避免资源竞争)
        disableConcurrentBuilds()
        
        // 或使用锁资源控制并发
    }
    
    stages {
        stage('Parallel Build') {
            parallel {
                stage('Backend') {
                    agent { label 'java' }
                    steps { sh 'mvn package' }
                }
                stage('Frontend') {
                    agent { label 'nodejs' }
                    steps { sh 'npm run build' }
                }
            }
        }
    }
}

监控与告警

监控指标

指标 工具 告警阈值
Master CPU Prometheus > 70%
Master 内存 Prometheus > 80%
Agent CPU Prometheus > 90%
构建队列长度 Prometheus > 10
构建等待时间 Prometheus > 5 分钟
节点离线 Alertmanager 立即

Prometheus 监控配置

# jenkins-config.yaml
unclassified:
  globalLibraries:
    libraries:
      - name: monitoring-library
        defaultVersion: master
        retriever:
          modernSCM:
            scm:
              git:
                remote: https://github.com/jenkinsci/monitoring-library.git

  metrics:
    retentionDays: 30
    enabledDiagnosticSummaries: true

Grafana Dashboard

关键监控面板:

  1. 构建趋势图
  2. 队列状态
  3. 节点状态
  4. Executor 利用率
  5. 构建时间分布

自动扩展

Kubernetes 自动扩缩容

# HPA 配置
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: jenkins-agent
  namespace: jenkins
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: jenkins-agent-deploy
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

基于队列的扩展

// Pipeline 中请求特定资源
pipeline {
    agent {
        kubernetes {
            label 'auto-scaled'
            yaml '''
apiVersion: v1
kind: Pod
metadata:
  name: jenkins-agent
spec:
  nodeSelector:
    jenkins/agent: "true"
  tolerations:
  - key: "jenkins"
    operator: "Exists"
    effect: "NoSchedule"
'''
        }
    }
}

最佳实践

架构设计原则

  1. 小而专注的 Master:Master 只负责调度,Agent 负责执行
  2. 标签化分组:按功能/平台分组节点
  3. 共享存储:使用 NFS/云存储实现构建产物共享
  4. 安全隔离:使用 K8s namespace 隔离不同团队
  5. 监控先行:部署前配置好监控告警

容量规划

团队规模 日构建量 Master 配置 Agent 配置
< 10 人 < 50 4C/8GB 4 节点 x 2 executor
10-50 人 50-200 8C/16GB 8 节点 x 2 executor
50-200 人 200-1000 16C/32GB 16 节点 + K8s
200+ 人 1000+ HA 集群 K8s 动态 + 静态节点

下一步

接下来让我们学习备份与恢复策略。

👉 备份与恢复


💡 提示:生产环境建议使用 Kubernetes 部署方案,便于弹性扩展和高可用。