Jenkins K8s 部署实例

梗概

通过 [Jenkins Pipeline](mdc:笔记/计算机知识/app应用/Jenkins Pipeline详解.md) 实现 Java 项目自动构建 Docker 镜像并部署到 Kubernetes 集群的完整流程。

前提条件

  1. 安装必要插件

    • Kubernetes Plugin
    • Docker Plugin
  2. 环境准备

    • Jenkins 可访问 Docker 服务
    • Jenkins 可访问 Kubernetes 集群
    • 配置好私有镜像仓库凭证

完整 Pipeline 实现

pipeline {
    agent any
    
    environment {
        DOCKER_REGISTRY = 'registry.example.com'
        APP_NAME = 'myapp'
        K8S_NAMESPACE = 'production'
    }
    
    stages {
        stage('拉取代码') {
            steps {
                git url: 'https://github.com/your-org/your-java-app.git', branch: 'main'
            }
        }
        
        stage('单元测试') {
            steps {
                sh 'mvn clean test'
            }
            post {
                always {
                    publishTestResults testResultsPattern: 'target/surefire-reports/*.xml'
                }
            }
        }
        
        stage('构建应用') {
            steps {
                sh 'mvn package -DskipTests'  // 跳过测试,因为前面已经执行过
            }
        }
        
        stage('构建 Docker 镜像') {
            steps {
                script {
                    // 使用构建号作为镜像标签
                    def imageTag = "${DOCKER_REGISTRY}/${APP_NAME}:${BUILD_NUMBER}"
                    
                    // 构建镜像
                    sh "docker build -t ${imageTag} ."
                    
                    // 推送到私有仓库
                    withCredentials([usernamePassword(credentialsId: 'docker-registry-creds', 
                                                    usernameVariable: 'DOCKER_USER', 
                                                    passwordVariable: 'DOCKER_PASS')]) {
                        sh "echo \$DOCKER_PASS | docker login ${DOCKER_REGISTRY} -u \$DOCKER_USER --password-stdin"
                        sh "docker push ${imageTag}"
                    }
                }
            }
        }
        
        stage('部署到 K8s') {
            steps {
                script {
                    def imageTag = "${DOCKER_REGISTRY}/${APP_NAME}:${BUILD_NUMBER}"
                    
                    // 更新 Deployment 镜像
                    sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${imageTag} -n ${K8S_NAMESPACE}"
                    
                    // 等待部署完成
                    sh "kubectl rollout status deployment/${APP_NAME} -n ${K8S_NAMESPACE} --timeout=300s"
                    
                    // 验证部署
                    sh "kubectl get pods -n ${K8S_NAMESPACE} -l app=${APP_NAME}"
                }
            }
        }
    }
    
    post {
        success {
            echo "🎉 部署成功!应用 ${APP_NAME} 已更新到版本 ${BUILD_NUMBER}"
        }
        failure {
            echo "❌ 部署失败!请检查日志"
            // 可以添加回滚逻辑
            script {
                sh "kubectl rollout undo deployment/${APP_NAME} -n ${K8S_NAMESPACE}"
            }
        }
        cleanup {
            // 清理本地 Docker 镜像节省空间
            sh "docker rmi ${DOCKER_REGISTRY}/${APP_NAME}:${BUILD_NUMBER} || true"
        }
    }
}

必要的 Kubernetes 配置文件

Deployment 配置示例 (deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: registry.example.com/myapp:latest
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

Service 配置示例 (service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  namespace: production
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

安全考虑

  1. 凭证管理:使用 Jenkins 凭证管理器存储敏感信息
  2. 镜像扫描:在推送前进行安全扫描
  3. 资源限制:在 K8s 中设置合理的资源限制
  4. 网络策略:配置适当的网络访问控制

监控与日志

stage('健康检查') {
    steps {
        script {
            // 等待服务就绪
            timeout(time: 5, unit: 'MINUTES') {
                waitUntil {
                    script {
                        def result = sh(script: "curl -f http://${APP_NAME}-service/health", returnStatus: true)
                        return result == 0
                    }
                }
            }
        }
    }
}

相关概念