企业级Devops— 打造完整 CICD 实践指南(九):Jenkins自动化构建

🔧 Jenkins自动化构建

Jenkins自动化构建的好处

  1. 提高开发效率

Jenkins可以自动化整个构建和部署过程,开发人员不需要手动进行繁琐的构建操作。这样,开发人员可以将精力集中在编写代码和解决实际问题上,减少了等待和手动干预的时间。

  1. 持续集成(CI)支持

Jenkins提供了强大的持续集成功能,能够在代码每次提交后自动触发构建,确保代码始终保持可用状态。通过快速反馈,开发人员可以在代码有问题时尽早发现并修复,降低了集成时出现大规模问题的风险。

  1. 减少人为错误

手动构建过程容易受到人为错误的影响,而Jenkins通过自动化流程可以确保构建过程的一致性和准确性,减少了因为操作失误而导致构建失败的情况。

  1. 提高代码质量

Jenkins支持与各种测试工具的集成,如单元测试、集成测试等。每次构建后,自动执行测试,确保新提交的代码不会引入问题。这样可以大大提高代码质量,减少bug的产生。

  1. 快速反馈

Jenkins可以提供实时反馈,开发人员可以及时知道构建的状态。如果构建失败,Jenkins会及时通知相关人员,确保问题能够快速定位和解决。

  1. 自动化部署

Jenkins不仅仅用于构建,还可以与部署工具(如DockerKubernetes等)集成,自动化部署到测试环境、生产环境等。这样可以加速部署流程,并减少部署过程中可能出现的错误。

  1. 可扩展性

Jenkins拥有丰富的插件生态,可以与各种工具、框架和服务集成,支持从源码管理到自动化部署的整个过程。无论是与GitMavenDockerKubernetes等工具的结合,还是集成测试和通知系统,Jenkins都可以灵活适配。

  1. 提高团队协作

通过自动化构建,团队成员可以更清楚地了解整个项目的进度与状态。Jenkins的构建历史记录和报告能够帮助团队识别瓶颈、跟踪问题,并促进团队协作。

  1. 持续交付(CD)支持

Jenkins可以与持续交付工具结合使用,将代码从开发到生产的过程进行自动化。这使得团队能够更快速、更频繁地发布功能和修复,缩短了软件的交付周期。

  1. 降低运营风险

自动化构建和部署过程减少了人为干预,降低了生产环境中由于人为操作错误引发的问题。通过流水线(Pipeline)和自动化流程,Jenkins能够提供更为稳定、可靠的系统。

🖥️ Jenkins环境变量配置

👩‍💻 后端

  1. 新建一个文件夹开发环境构建
  1. 新建一个任务
  1. 进入任务,配置pipeline

pipeline内容:

groovy 复制代码
def createVersion() {
    // 定义一个版本号作为当前构建的版本
    return new Date().format("yyyyMMddHHmmss") + "${env.BUILD_ID}"
}
pipeline {
    agent any
    environment {
        HARBOR_CREDS= credentials('harbor')
        TAGS = createVersion()
    }
    parameters {
        string(name: 'HARBOR_HOST', defaultValue:'<your-domain>', description: 'harbor镜像仓库地址')
        string(name: 'APP_NAME', defaultValue:'release-test', description: 'k8s中标签名')
        string(name: 'K8S_NAMESPACE', defaultValue: 'develop', description: 'k8s的namespace名称')
        string(name: 'IMAGENAME', defaultValue: 'release-test', description: '镜像名')
        string(name: 'PROJECT', defaultValue: 'develop', description: '仓库项目名')
    }
    stages {
        
        stage("环境信息") {
            steps {
                sh 'java -version'
                echo "JAVA_HOME: ${env.JAVA_HOME}"
                echo "PATH: ${env.PATH}"
                echo "JENKINS USER: ${env.USER}"
                echo "BUILD_ID: ${BUILD_ID}"
                echo "Running on JENKINS   in : ${WORKSPACE}"
            }
        }
        
        stage("DeleteDir") {
            steps {
                sh 'rm -r /var/lib/jenkins/workspace/develop-backend/releaseTest/*' 
            }
        }
        
        
        // 1、拉取代码
        stage("Checkout") {
            steps {
                checkout([
                    $class: 'GitSCM',
                    branches: [[name: '*/main']],
                    extensions: [],
                    userRemoteConfigs: [[
                        credentialsId: 'gitlab',
                        url: '<release-test代码仓库clone_url>'
                    ]]
                ])    
            }
            
        }
        
        // 2、maven打包
        stage('Package') {
            steps {
                sh "mvnd clean package -DskipTests"
            }
        }
        
        stage('构建镜像') {
            steps {
                // sh "docker info" // 判断jenkins是否有权限访问docker
                sh "cat ./Dockerfile"
                sh "docker login ${HARBOR_HOST} -u ${HARBOR_CREDS_USR} -p ${HARBOR_CREDS_PSW}"
                sh "docker build -t ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS} ."
                sh "docker push ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS}"
                sh "docker rmi -f ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS}"
            }
        }
        
        stage('部署至k8s集群') {
          steps {
                sh "sed -i 's#image:.*REGISTRY.*#image: ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS}#g' k8s-releasetest.yaml"
                sh "sed -i 's#namespace:.*NAMESPACE#namespace: ${K8S_NAMESPACE}#g' k8s-releasetest.yaml"
                sh "cat k8s-releasetest.yaml"
                sh "kubectl apply -f k8s-releasetest.yaml"
          }
            
        }
        
    }
}
  1. 保存配置并运行:

👩‍💻 前端

前面的步骤和后端一模一样,我们直接进入pipeline配置

pipeline内容:

groovy 复制代码
def createVersion() {
    // 定义一个版本号作为当前构建的版本
    return new Date().format("yyyyMMddHHmmss") + "${env.BUILD_ID}"
}
pipeline {
    agent any
    environment {
        HARBOR_CERDS= credentials('harbor')
        TAGS= createVersion()
    }
    parameters {
        string(name: 'HARBOR_HOST', defaultValue: '<your-domain>', description: 'harbor镜像仓库地址')
        string(name: 'APP_NAME', defaultValue:'release-frontend', description: 'k8s中标签名')
        string(name: 'K8S_NAMESPACE', defaultValue: 'develop', description: 'k8s的namespace名称')
        string(name: 'IMAGENAME', defaultValue: 'release-frontend', description: '镜像名')
        string(name: 'PROJECT', defaultValue: 'develop', description: '仓库项目名')
    }
    stages {
        
        stage("环境信息") {
            steps {
                sh "node -v"
                sh 'npm -v'
                echo "NODE_HOME: ${env.NODE_HOME}"
                echo "PATH: ${env.PATH}"
                echo "JENKINS USER: ${env.USER}"
                echo "BUILD_ID: ${BUILD_ID}"
                echo "Running on JENKINS   in : ${WORKSPACE}"
            }
        }
        
        stage("DeleteDir") {
            steps {
                sh 'rm -r /var/lib/jenkins/workspace/develop-backend/releaseFrontend/*' 
            }
        }
        
        
        // 1 拉取代码
        stage("Checkout") {
            steps {
                checkout([
                    $class: 'GitSCM',
                    branches: [[name: '*/main']],
                    extensions: [],
                    userRemoteConfigs: [[
                        credentialsId: 'gitlab',
                        url: '<release-frontend代码仓库clone_url>'
                    ]]
                ])
            }
        }
        
        // 2 npm编译
        stage('Npm编译') {
            steps {
                sh "npm install --registry=https://registry.npmmirror.com --force --no-audit"
                sh "npm run build"
            }
        }
        
        
        stage('构建镜像') {
            steps {
                withCredentials([usernamePassword(credentialsId: 'harbor', usernameVariable: 'HARBOR_CREDS_USR', passwordVariable: 'HARBOR_CREDS_PSW')]) {
                    // sh "docker info" // 判断jenkins是否有权限访问docker
                    sh "cat ./Dockerfile"
                    sh "docker login ${HARBOR_HOST} -u ${HARBOR_CREDS_USR} -p ${HARBOR_CREDS_PSW}"
                    sh "docker build -t ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS} ."
                    sh "docker push ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS}"
                    sh "docker rmi -f ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS}"
                }
            }
        }
        
        stage('部署至k8s集群') {
          steps {
                sh "sed -i 's#image:.*REGISTRY.*#image: ${HARBOR_HOST}/${PROJECT}/${IMAGENAME}:${TAGS}#g' k8s-releasefrontend.yaml"
                sh "sed -i 's#namespace:.*NAMESPACE#namespace: ${K8S_NAMESPACE}#g' k8s-releasefrontend.yaml"
                sh "cat k8s-releasefrontend.yaml"
                sh "kubectl apply -f k8s-releasefrontend.yaml"
          }
            
        }
        
        // stage("检查k8s pod 状态") {
        //     steps {
        //         sleep 10
                
        //         int attempts = 6
        //         int sleepTime = 5
        //         for (int i=0; i< attempts; i++) {
        //             def podStatus = sh(script: 'kubectl get pod ${IMAGENAME} -o jsonpath="{.status.phase}"', returnStdout: true)
        //             echo "Pod status is : ${podStatus}"
        //             if(podStatus == "Running") {
        //                 echo "运行状态正常,已经准备就绪!"
        //                 return
        //             } else if(podStatus == ""){
        //                 echo "继续尝试检查k8s pod状态..."
        //                 sleep sleepTime
        //             }
        //         }
        //         error "经过 ${attempts} 次尝试检查后仍无法正常运行,请检查相关配置是否正确..........."
        //     }
        // }
        
    }
}

保存配置并运行:

🔍查看集群服务是否启动

status显示Running表示启动成功✅

service也部署成功✅

🌐 浏览器访问

后端接口地址:

前端:

⚠️ 注意 :此时访问端口是30002,为前端nodePort;点击按钮api test返回的是一段<html>代码; 后面Ingress搭建好后访问30007可正确返回接口内容,Ingress相关内容请到Ingress章节学习

相关推荐
易样2 小时前
企业级Devops— 打造完整 CICD 实践指南(八):容器化实战
自动化运维·devops
易样2 小时前
企业级Devops— 打造完整 CICD 实践指南(七):远程连接Kubernetes集群
自动化运维·devops
易样2 小时前
企业级Devops— 打造完整 CICD 实践指南(五):Harbor企业级镜像仓库
自动化运维·devops
易样2 小时前
企业级Devops— 打造完整 CICD 实践指南(六):Kubernetes集群搭建
自动化运维·devops
易样2 小时前
企业级Devops— 打造完整 CICD 实践指南(十一):Rancher可视化管理
自动化运维·devops
易样3 小时前
企业级Devops— 打造完整 CICD 实践指南(四):Gitlab代码仓库搭建
自动化运维·devops
易样3 小时前
企业级Devops— 打造完整 CICD 实践指南(三):Jenkins搭建
自动化运维·devops
易样3 小时前
企业级Devops— 打造完整 CICD 实践指南(一):手册核心内容亮点
devops
易样3 小时前
企业级DevOps——打造完整CICD实践指南(二):环境准备
自动化运维·devops