# 基于 Jenkins + Kubernetes 的 CI/CD 流水线实战:Vue 3 与 Java 11 项目

## 前言

在现代软件开发中,持续集成和持续部署(CI/CD)已成为标配。本文将介绍如何使用 **Jenkins** 配合 **Kubernetes** 构建高效的 CI/CD 流水线,分别以 **Vue 3 前端项目** 和 **Java 11 后端项目** 为例,展示完整的自动化构建流程。

## 架构概述

我们的流水线采用以下技术栈:

- **Jenkins**:CI/CD 编排引擎
- **Kubernetes**:容器化运行环境,提供动态 Agent
- **Kaniko**:无守护进程的 Docker 镜像构建工具
- **SonarQube**:代码质量扫描
- **Harbor**:私有 Docker 镜像仓库

## 流水线核心结构

### 1. Kubernetes Agent 配置

两个项目都使用 Kubernetes Pod 作为运行环境,每个 Pod 包含多个容器:

```groovy
agent {
    kubernetes {
        label 'containerd'
        yaml '''
            apiVersion: v1
            kind: Pod
            spec:
              containers:
              - name: jnlp
                image: jenkins/inbound-agent:latest
              - name: node      # Vue 项目使用
                image: node:18-alpine
              - name: maven     # Java 项目使用
                image: maven:3.8.6-openjdk-11
              - name: sonar
                image: sonarsource/sonar-scanner-cli:latest
              - name: kaniko
                image: xxx/executor:debug
        '''
    }
}
```

**关键设计点:**
- 每个容器负责特定任务(构建、扫描、镜像打包)
- `command: ["cat"]` 和 `tty: true` 保持容器运行状态
- `imagePullPolicy: Always` 确保使用最新镜像

### 2. 参数化构建

支持用户自定义参数:

```groovy
parameters {
    string(name: 'IMAGE_TAG', defaultValue: 'v1.0.0', description: 'Docker 镜像版本标签')
    booleanParam(name: 'DEPLOY_TO_K8S', defaultValue: false, description: '是否部署到 K8S')
}
```

### 3. 环境变量管理

```groovy
environment {
    GIT_REPO = 'http://xxx/xxx/vue3-demo.git'
    GIT_BRANCH = 'master'
    HARBOR_REGISTRY = 'xxx:6443'
    HARBOR_PROJECT = 'library'
    HARBOR_USERNAME = 'xxx'
    HARBOR_PASSWORD = 'xxx'  // 生产环境建议使用 Credentials
}
```

## Vue 3 项目流水线详解

### 阶段一:拉取代码

```groovy
stage('拉取代码') {
    steps {
        checkout scmGit(
            branches: [[name: "*/${GIT_BRANCH}"]],
            userRemoteConfigs: [[
                url: "${GIT_REPO}",
                credentialsId: 'xxx'
            ]]
        )
    }
}
```

### 阶段二:安装依赖

在 Node.js 容器中执行,使用国内镜像源加速:

```groovy
stage('安装依赖') {
    steps {
        container('node') {
            sh 'npm install --registry=https://registry.npmmirror.com'
        }
    }
}
```

### 阶段三:代码编译

```groovy
stage('代码编译') {
    steps {
        container('node') {
            sh 'npm run build'
        }
    }
}
```

### 阶段四:SonarQube 代码扫描

```groovy
stage('代码扫描') {
    steps {
        container('sonar') {
            withSonarQubeEnv('sonarqube') {
                sh '''
                    sonar-scanner \
                        -Dsonar.projectKey=vue3-demo \
                        -Dsonar.sources=src \
                        -Dsonar.host.url=http://xxx/
                '''
            }
        }
    }
}
```

### 阶段五:构建 Docker 镜像

使用 Kaniko 在 K8s 中安全构建镜像:

```groovy
stage('构建 Docker 镜像') {
    steps {
        container('kaniko') {
            sh """
                /kaniko/executor \\
                    --context=. \\
                    --dockerfile=${DOCKER_FILE_PATH}/Dockerfile \\
                    --destination=${HARBOR_REGISTRY}/${HARBOR_PROJECT}/vue3-demo:${IMAGE_TAG} \\
                    --cache=true \\
                    --cache-dir=/tmp/kaniko-cache
            """
        }
    }
}
```

## Java 11 项目流水线详解

Java 项目的流程与 Vue 类似,主要区别在于构建工具:

### Maven 编译与测试

```groovy
stage('代码编译') {
    steps {
        container('maven') {
            sh 'mvn clean compile -DskipTests'
        }
    }
}

stage('单元测试') {
    steps {
        container('maven') {
            sh 'mvn test'
        }
    }
}

stage('构建 JAR 包') {
    steps {
        container('maven') {
            sh 'mvn clean package -DskipTests'
        }
    }
}
```

### SonarQube 扫描(Java 专用)

```groovy
stage('代码扫描') {
    steps {
        container('sonar') {
            withSonarQubeEnv('sonarqube') {
                sh '''
                    mvn sonar:sonar \\
                        -Dsonar.projectKey=java11-demo \\
                        -Dsonar.sources=src/main/java \\
                        -Dsonar.host.url=http://xxx/
                '''
            }
        }
    }
}
```

## 条件部署阶段

两个项目都支持条件部署到 Kubernetes:

```groovy
stage('部署到 K8S') {
    when {
        expression { return params.DEPLOY_TO_K8S }
    }
    steps {
        sh '''
            echo "部署镜像:${HARBOR_REGISTRY}/${HARBOR_PROJECT}/app:${IMAGE_TAG}"
            # kubectl set image deployment/app app=${HARBOR_REGISTRY}/${HARBOR_PROJECT}/app:${IMAGE_TAG}
        '''
    }
}
```

## 构建后处理

```groovy
post {
    always {
        echo 'Pipeline 执行完成'
    }
    success {
        echo "构建成功!镜像版本:${IMAGE_TAG}"
    }
    failure {
        echo '构建失败,请检查日志!'
    }
}
```

## 最佳实践总结

### 安全建议

| 问题 | 建议 |
|------|------|
| 明文密码 | 使用 Jenkins Credentials 管理敏感信息 |
| 硬编码地址 | 使用环境变量或 ConfigMap |
| 镜像标签 | 避免使用 `latest`,使用语义化版本 |

### 性能优化

1. **启用 Kaniko 缓存**:`--cache=true --cache-dir=/tmp/kaniko-cache`
2. **使用国内镜像源**:npm 使用 npmmirror,Maven 使用阿里云镜像
3. **容器并行**:Kubernetes Pod 内容器可并行执行任务

### 可维护性

1. **模板化 Pipeline**:使用 Shared Library 复用通用逻辑
2. **参数化构建**:支持灵活配置
3. **清晰阶段命名**:使用中文或英文保持一致性

## 总结

本文展示了如何使用 Jenkins + Kubernetes 构建现代化的 CI/CD 流水线。通过容器化 Agent,我们实现了:

- ✅ 环境隔离,避免污染
- ✅ 弹性伸缩,按需分配资源
- ✅ 多容器协作,职责分离
- ✅ 安全构建,无需 Docker in Docker

你可以根据项目需求调整流水线,添加自动化测试、通知、灰度发布等功能。

---

*作者:基于实际项目实践整理*
*日期:2026 年 3 月*