当前位置: 首页 > news >正文

Jenkins运维之路(Jenkins流水线改造Day02-1-容器项目)

这回对线上容器服务器的流水线进行了一定的改造来满足目前线上的需求,还是会将所有的自动化脚本都放置到代码库中统一管理,我感觉一章不一定写的完,所以先给标题加了个-1,话不多说开干

1.本次流水线的流程设计

对于这个流水线我想说每家公司的流程和制度都不一样,我的流水线也只是个参考。我先用2张图来将我这次流水线的部署流程给做下解释

image-20250912164347373

image-20250912164347373

image-20250912164127499

image-20250912164127499

2. 运维的代码库结构

image-20250912165146765

image-20250912165146765

3. Jenkinsfile

def createVersion() {// 创建了一个方法createVersion()// 定义一个时间戳+构建ID作为版本号,为tag使用return new Date().format('yyyyMMddHHmmss') + "_${env.BUILD_ID}"
}
pipeline {//执行构建的节点名称agent { node { label "node47"}}//指定构建工具集tools {git 'Git'maven 'maven399'jdk 'jdk2102'}// 定义环境变量environment {//代码库地址GIT_REPO_URL = 'git@xxxxx/spring-boot-3-hello-world-jdk21.git'//有些字体要有颜色输出 这里定义为变量,后期输出时直接引用RED = "\u001B[31m"GREEN = "\u001B[32m"   // 绿色PURPLE = "\u001B[35m"  // 紫色RESET = "\u001B[0m"    // 重置//harbor地址REGISTRY_URL = 'harbor.xxx.top'//docker登录时需要使用到https协议所以这里还需要在定义一个有协议的harbor地址HARBOR_URL = 'https://harbor.xxxx.top'//harbor 容器组PROJECT_GROUP = 'devops'//harbor的项目名PROJECT_NAME = 'hello-world-jdk21'//在服务器上的服务容器名,这个用来部署时搜索或者删除CONTAINER_NAME = 'hello-world-jdk21'//运维代码库,在部署和回滚时会拉取代码库中信息,在执行不同的playbookOPS_SHARE_LIBRARY = 'xxxxx/ops-share-librarya.git'}options {//整个项目的超时时间timeout(time: 10, unit: 'MINUTES')// 不允许同时执行流水线disableConcurrentBuilds()// 构建时的时间信息timestamps()}  // 参数话构建中的参数parameters {// git参数gitParameter(name: 'BRANCH_TAG',      //这个作为后面调用的变量名type: 'PT_BRANCH_TAG',  //这里是同时显示分支和tagdefaultValue: 'master',description: '请选择你要部署的分支或Tag',useRepository: 'xxxx/spring-boot-3-hello-world-jdk21.git', // 这里要使用完整的Git仓库地址quickFilterEnabled: true // 启用快速筛选)// 定义回滚条件booleanParam(defaultValue: false, description: '是否进行项目回滚?', name: 'ROLLBACK_TAG')}stages {// 校验发布条件stage('Check requirement') {steps {script {if (params.ROLLBACK_TAG && env.BRANCH_TAG.startsWith('rel-')) {echo "条件满足:ROLLBACK_TAG 为真,且 BRANCH_TAG 以 rel- 开头,继续执行后续步骤。"} else if (!params.ROLLBACK_TAG && !env.BRANCH_TAG.startsWith('rel-')) {echo "条件满足:ROLLBACK_TAG 为假,且BRANCH_TAG 不以 rel- 开头,继续执行后续步骤。"} else {echo "条件不满足,终止整个流程。"error("构建中止:条件不满足。")}}}}// 将需要的构建人等显示信息抓取并显示,部署(执行人,发布分支,成功后代码库tag信息),回滚(执行人,回滚容器的rel-id,显示项目回滚)stage('Show info') {steps {script {if (params.ROLLBACK_TAG) {wrap([$class: 'BuildUser']) {echo "Built by: ${env.BUILD_USER_ID}"currentBuild.description = "Built by: ${env.BUILD_USER_ID}, Rollback: ${env.BRANCH_TAG}, tag: '项目回滚'"}} else {// 如果你选择了发布master那么在这里会调用上面定义的全局时间戳方法createVersion来生成数字作为代码和容器的tag// 生成tag并给与变量_tag_tag = createVersion()wrap([$class: 'BuildUser']) {echo "Built by: ${env.BUILD_USER_ID}"currentBuild.description = "Built by: ${env.BUILD_USER_ID}, Branch: ${env.BRANCH_TAG}, tag: ${_tag}"}}}}}// 清理工作空间,很多人会在构建后清理,我习惯在构建前清理下,个人习惯不同stage('CleanWorkDir') {steps {cleanWs()}}// 拉取代码stage('Checkout') {steps {script {//这里引用的环境变量 GIT_REPO_URLcheckout([$class: 'GitSCM', branches: [[name: params.BRANCH_TAG]], userRemoteConfigs: [[url: "${GIT_REPO_URL}", credentialsId: "GiteeKey"]]])}}}// 开始进行构建这里也会做个判断,如果你前面选择的master分支那么进行代码打包,如果你选择的是rel-开头的tag和回滚则跳过打包stage('Build') {// when 当达到什么条件时执行下面的步骤when {expression { // 检查 BRANCH_TAG 是否不以 'rel-' 开头return !params.BRANCH_TAG.startsWith('rel-')}}steps {ansiColor('xterm') { // 启用 AnsiColorecho "${GREEN}项目开始构建${RESET}"echo "Building"}sh 'mvn clean package -Dmaven.test.skip=true'}}// 构建容器镜像并推送到私有库中,同样如果选择的是rel-开头的tag和回滚跳过stage('Dockerbuild') {when {expression { // 检查 BRANCH_TAG 是否不以 'rel-' 开头return !params.BRANCH_TAG.startsWith('rel-')}}steps {ansiColor('xterm') { // 启用 AnsiColorecho "${GREEN}构建容器${RESET}"echo "Docker Building"}script {sh 'pwd'  // 打印当前工作目录(调试用)sh 'ls -la'  // 列出当前目录中的文件(调试用)// 构建镜像(这里用上面的环境变量进行拼接)def image = docker.build("${REGISTRY_URL}/${PROJECT_GROUP}/${PROJECT_NAME}:${_tag}",".")// 推送镜像docker.withRegistry("${HARBOR_URL}", "Harbor") {image.push()  // 推送镜像到注册表}// 删除本地镜像sh "docker rmi ${REGISTRY_URL}/${PROJECT_GROUP}/${PROJECT_NAME}:${_tag}"}}}//使用Ansible进行部署或回滚stage('Ansible Deploy') {steps {ansiColor('xterm') { // 启用 AnsiColor//sh "ansible 192.168.1.98 -m shell -a 'ls /root'"  测试的时候用了一下echo "${PURPLE}Ansible 部署项目${RESET}"}script {// 下载运维代码sh "git clone ${OPS_SHARE_LIBRARY} ./ops-share-librarya"// 登录harborwithCredentials([usernamePassword(credentialsId: 'Harbor', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) {// 定义一个通用的 Map,这里是传入Ansible中使用的参数,有一个变量因为会涉及到部署和回滚所以在下面的判断中在进行加入def extraVars = [container_name: "${CONTAINER_NAME}",docker_registry: "${HARBOR_URL}",docker_username: "${HARBOR_USERNAME}",docker_password: "${HARBOR_PASSWORD}"].collectEntries { [(it.key): it.value] }// 根据 BRANCH_TAG 的值添加特定的参数if (!env.BRANCH_TAG.startsWith('rel-')) {// 当你选择正常部署master的时候会追加参数,这个参数是容器名称extraVars['new_image_name'] = "${REGISTRY_URL}/${PROJECT_GROUP}/${PROJECT_NAME}:${_tag}"// 执行正常的部署ansiblePlaybook(playbook: "./ops-share-librarya/Ansible/HelloWorld-Pipeline/deploy.yml",inventory: "./ops-share-librarya/Ansible/HelloWorld-Pipeline/hosts",extraVars: extraVars)} else {// 当你选择的是回滚的时候 会对你选择的回滚tag进行tag处理去除rel- 只要后面的数字def branchTag = env.BRANCH_TAGdef extractedValue = branchTag.replaceFirst(/^rel-/, '')  // 去掉前缀 "rel-"println "Extracted Value: ${extractedValue}"  // 输出提取的值// 回滚时添加的参数extraVars['rel_image_name'] = "${REGISTRY_URL}/${PROJECT_GROUP}/${PROJECT_NAME}:${extractedValue}"// 执行回滚ansiblePlaybook(playbook: "./ops-share-librarya/Ansible/HelloWorld-Pipeline/rollback.yml",inventory: "./ops-share-librarya/Ansible/HelloWorld-Pipeline/hosts",extraVars: extraVars)}}}}}}  post {//通知和告警,这个下章在和Ansible一起发出来}
}


文章转载自:

http://8WN2QcnA.tssmk.cn
http://wOhiLPZ3.tssmk.cn
http://TmmHOh7q.tssmk.cn
http://yWqqwPKt.tssmk.cn
http://iSeIwnbO.tssmk.cn
http://vt8zHNSD.tssmk.cn
http://PmATalIL.tssmk.cn
http://CO8E29jV.tssmk.cn
http://7X1T18aJ.tssmk.cn
http://EF1MOySQ.tssmk.cn
http://oX8UMeOE.tssmk.cn
http://GSzXpkyI.tssmk.cn
http://EhBYXALj.tssmk.cn
http://Gq2lYUrE.tssmk.cn
http://jHAg1JPG.tssmk.cn
http://YHG7hn7t.tssmk.cn
http://XA0ONqR6.tssmk.cn
http://DYNG6bz5.tssmk.cn
http://3sfLihor.tssmk.cn
http://DocWWP25.tssmk.cn
http://b8PFSrmg.tssmk.cn
http://Um1pP9Jo.tssmk.cn
http://hzUKj0tW.tssmk.cn
http://HtlXf6bb.tssmk.cn
http://yyOEumwe.tssmk.cn
http://j4gsGT7l.tssmk.cn
http://3kCJ25Vf.tssmk.cn
http://5eIwaU5f.tssmk.cn
http://0hZxQf2n.tssmk.cn
http://y1CH22oj.tssmk.cn
http://www.dtcms.com/a/380739.html

相关文章:

  • Netty从0到1系列之Netty逻辑架构【上】
  • com.google.common.cache实现本地缓存
  • LeetCode 面试经典 150 题之最后一个单词的长度:逆向遍历高效解法
  • 详解JWT
  • Spring Boot 分布式事务常见问题:Seata、XA 与本地消息表对比
  • 如何在Hugging Face中下载全部文件?
  • AI之VideoTool:AI-Video-Transcriber​​​​​​​的简介、安装和使用方法、案例应用之详细攻略
  • Qt6实现了一个打地鼠小游戏,支持AI自动打地鼠
  • Chapter5—抽象工厂模式
  • WebSocket连接状态监控与自动重连实现
  • 目标计数论文阅读(1)Class-Agnostic Counting
  • LVGL移植2048小游戏全攻略
  • 大模型系列——ChatBI重构企业知识库
  • DEM(数字高程模型)详解
  • 软考 系统架构设计师系列知识点之杂项集萃(144)
  • R语言生物群落(生态)数据统计分析与绘图实践技术应用
  • DPO 深度解析:从公式到工程,从偏好数据到可复用训练管线
  • 今天继续学习Linux系统中shell脚本
  • 开源端到端训练多模态大模型LLaVA 深度拆解
  • 周志华《机器学习导论》第10章 降维与度量学习
  • PyQt置顶窗口
  • 基于图像和激光的多模态点云融合与视觉定位
  • 企业数据防护利器:Curtain e-locker 支持NCA合规
  • 【Vue2 ✨】Vue2 入门之旅 · 进阶篇(九):Vue2 性能优化
  • Java面试问题记录(二)
  • 势能分析 线段树 学习记录
  • 创维在线算号器-Skyworth创维密码计算器
  • 电商导购平台的搜索引擎优化:基于Elasticsearch的商品精准推荐系统
  • c++怎么读取文件里的内容和往文件里写入数据
  • C++实战:搜索引擎项目(二)