文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

基于Jira的运维发布平台的设计与实现

2024-12-03 04:32

关注

本文转载自微信公众号「运维开发故事」,作者乔克 。转载本文请联系运维开发故事公众号。

上线发布是运维的日常工作,常见的发布方式有:

除此之外还有需要开源软件,他们都有非常不错的发布管理功能。

面临的问题

作为运维人员,上线发布是必不可少的一环,一个正常的发布流程是怎么样的?

环节看似简单,但是中间其实是有断层的。一般企业在走上线流程都是通过一些公共渠道,比如邮件、钉钉、飞书的流程,这些都很难和运维执行上线发布平台进行关联上,而且也不够直观。所以我们就需要解决以下几个问题:

流程和运维平台建立连接

从发起到结束形成闭环

为了选择JIRA?

JIRA优秀的项目管理,问题跟踪的工具,另外它的流程管理和看板模式也能够非常直观看到目前流程处在什么位置。另外它可以通过webhook和其他平台建立友好的连接,方便扩展。再者对于开发、测试、项目管理人员等来说Jira是他们日常的工具,使用熟练度非常高,降低了额外的学习成功。鉴于此,我们选择JIRA作为运维发布平台,争取做到一个平台做所有事。

方案设计

设计思路

充分利用Jira、Gitlab的webhook功能,以及Jenkins的灵活性。

整体思路相对简单,难点主要集中在Jenkins获取Jira、Gitlab的数据,所幸Jenkins的插件功能非常丰富,这里就使用Generic Webhook Trigger插件,可以很灵活地获取到触发软件的信息。

发布流程方案

然后整理出如下的发布流程。

涉及软件

软件 功能
Jira 发布流程管理
Jenkins 执行各种流水线
Gitlab 代码仓库
Kubernetes 应用管理
Helm/kustomize 包管理
钉钉 消息通知
trivy 镜像扫描
镜像仓库 阿里云镜像仓库

PS:这里没有具体的软件部署

Jira与Jenkins进行集成合并分支

Jenkins配置

Jenkins的配置主要有两部分,如下:

(1)Jenkins上配置ShareLibarary 系统配置-->系统配置-->Global Pipeline Libraries

(2)创建流水线,配置Webhook以及添加Jenkinsfile

先配置一个变量和正则

再配置一个Token即可

image.png

(3)Jenkinsfile的主要逻辑如下

PS:下面仅列出大致的框架,并没有详细的代码

  1. #!groovy 
  2.  
  3. @Library('lotbrick') _ 
  4.  
  5. def gitlab = new org.devops.gitlab() 
  6. def tool = new org.devops.tools() 
  7. def dingmes = new org.devops.sendDingTalk() 
  8.  
  9. pipeline { 
  10.     agent { node { label "master"}} 
  11.  
  12.     environment { 
  13.         DINGTALKHOOK = "https://oapi.dingtalk.com/robot/send?access_token=xxxx"    
  14.     } 
  15.  
  16.     stages{ 
  17.  
  18.         stage("FileterData"){ 
  19.             steps{ 
  20.                 script{ 
  21.                     response = readJSON text: """${webHookData}""" 
  22.  
  23.                     // println(response) 
  24.  
  25.                     env.eventType = response["webhookEvent"
  26.  
  27.                     if (eventType == "jira:issue_updated"){ 
  28.                         // 获取状态值 
  29.                         env.jiraStatus = response['issue']['fields']['status']['name'
  30.                         env.gitlabInfos = response['issue']['fields']['customfield_10219'
  31.                         infos = "${gitlabInfos}".split("\r\n"
  32.                         for (info in infos){ 
  33.                             prName = "$info".split("/")[0] 
  34.                             // brName = "$info".split("/")[1] 
  35.                             brName = info - "${prName}/" 
  36.                             println(prName) 
  37.                             println(brName) 
  38.                             if (jiraStatus == "已发布(UAT)"){ 
  39.                                 println('进行合并PRE分支操作'
  40.                             }else if (jiraStatus == "已发布(PROD)"){ 
  41.                                 println('进行合并PROD分支操作'
  42.                             }else if (jiraStatus == "已完成"){ 
  43.         println('进行分支打Tag并删除原分支'
  44.                             }else
  45.                                 println("查无此项"
  46.                             } 
  47.                         } 
  48.                     } 
  49.                 } 
  50.             } 
  51.         } 
  52.     } 
  53.     // 构建后的操作 
  54.  post { 
  55.   failure { 
  56.    script{  
  57.     println("failure:只有构建失败才会执行"
  58.     dingmes.SendDingTalk("分支合并失败 ❌"
  59.    } 
  60.   } 
  61.   aborted { 
  62.             script{ 
  63.     println("aborted:只有取消构建才会执行"
  64.     dingmes.SendDingTalk("分支合并取消 ❌","暂停或中断"
  65.             } 
  66.   } 
  67.  } 

以上Jenkins上配置基本完成。

Jira上配置

Jira上的主要配置如下:

建立工作流

将工作流关联项目组

配置webhook

设置-->系统-->网络钩子

上面配置完成后,即完成Jira上配置,然后就可以在对应项目的看板上查看所以待发布的项目,如下:

然后进行拖拽或者点击发布按钮,即可改变状态,触发流水线进行相应的操作了。

Gitlab与Jenkins集成发布系统

开发分支简要

这里主要使用的是功能分支开发模式,主要分为以下几个分支:

代码合并路线是:DEV->TEST->UAT->PRE->MASTER 然后根据不同的分支判断执行不同环境的部署。

Jenkins配置流水线

(1)配置Webhook插件参数

获取Gitlab分支

定义gitlab push条件,不是任何改动都需要触发流水线

定义过滤正则表达式

这样就只有commit的时候才会触发流水线。

(2)配置Jenkinsfile

  1. def labels = "slave-${UUID.randomUUID().toString()}" 
  2.  
  3. // 引用共享库 
  4. @Library('jenkins_shareLibrary'
  5.  
  6. // 应用共享库中的方法 
  7. def tools = new org.devops.tools() 
  8.  
  9. def branchName = "" 
  10.  
  11. // 获取分支 
  12. if ("${gitlabWebhook}" == "gitlabPush"){ 
  13.     branchName = branch - "refs/heads/" 
  14.  currentBuild.description = "构建者${userName} 分支${branchName}" 
  15.  
  16. pipeline { 
  17.     agent { 
  18.         kubernetes { 
  19.             label labels 
  20.             yaml ""
  21. apiVersion: v1 
  22. kind: Pod 
  23. metadata: 
  24.   labels: 
  25.     some-label: some-label-value 
  26. spec: 
  27.   volumes: 
  28.   - name: docker-sock 
  29.     hostPath: 
  30.       path: /var/run/docker.sock 
  31.       type: '' 
  32.   - name: maven-cache 
  33.     persistentVolumeClaim: 
  34.       claimName: maven-cache-pvc 
  35.   containers: 
  36.   - name: jnlp 
  37.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/inbound-agent:4.3-4 
  38.   - name: maven 
  39.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/maven:3.5.0-alpine 
  40.     command: 
  41.     - cat 
  42.     tty: true 
  43.     volumeMounts: 
  44.     - name: maven-cache 
  45.       mountPath: /root/.m2 
  46.   - name: docker 
  47.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/docker:19.03.11 
  48.     command: 
  49.     - cat 
  50.     tty: true 
  51.     volumeMounts: 
  52.     - name: docker-sock 
  53.       mountPath: /var/run/docker.sock 
  54.   - name: sonar-scanner 
  55.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/sonar-scanner:latest 
  56.     command: 
  57.     - cat 
  58.     tty: true 
  59.   - name: kustomize 
  60.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/kustomize:v3.8.1 
  61.     command: 
  62.     - cat 
  63.     tty: true 
  64.   - name: kubedog 
  65.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/kubedog:v0.5.0 
  66.     command: ['cat'
  67.     tty: true 
  68.   - name: trivy 
  69.     image: registry.cn-hangzhou.aliyuncs.com/rookieops/trivy:v2 
  70.     command: ['cat'
  71.     tty: true 
  72.     volumeMounts: 
  73.       - name: docker-sock 
  74.         mountPath: /var/run/docker.sock 
  75. ""
  76.         } 
  77.     } 
  78.  
  79.     environment { 
  80.         auth = 'joker' 
  81.     } 
  82.  
  83.     options { 
  84.         timestamps()    // 日志会有时间 
  85.         skipDefaultCheckout()    // 删除隐式checkout scm语句 
  86.         disableConcurrentBuilds()    //禁止并行 
  87.         timeout(time:1, unit:'HOURS') //设置流水线超时时间 
  88.     } 
  89.  
  90.     stages { 
  91.         // 拉取代码 
  92.         stage('GetCode') { 
  93.             steps { 
  94.                 checkout([$class: 'GitSCM', branches: [[name"${gitBranch}"]], 
  95.                     doGenerateSubmoduleConfigurations: false
  96.                     extensions: [], 
  97.                     submoduleCfg: [], 
  98.                     userRemoteConfigs: [[credentialsId: '83d2e934-75c9-48fe-9703-b48e2feff4d8', url: "${gitUrl}"]]]) 
  99.             } 
  100.         } 
  101.  
  102.         // 单元测试和编译打包 
  103.         stage('Build&Test') { 
  104.             steps { 
  105.                 container('maven') { 
  106.                     script { 
  107.                         tools.PrintMes('编译打包''blue'
  108.                     } 
  109.                 } 
  110.             } 
  111.         } 
  112.         // 代码扫描 
  113.         stage('CodeScanner') { 
  114.             steps { 
  115.                 container('sonar-scanner') { 
  116.                     script { 
  117.       tools.PrintMes('代码扫描''blue'
  118.                     } 
  119.                 } 
  120.             } 
  121.         } 
  122.         // 构建镜像 
  123.         stage('BuildImage') { 
  124.             steps { 
  125.                 container('docker') { 
  126.      script { 
  127.       tools.PrintMes('构建镜像''blue'
  128.      } 
  129.     } 
  130.             } 
  131.         } 
  132.    
  133.   // 镜像扫描 
  134.   stage('Vulnerability Scanner') { 
  135.             steps { 
  136.                 container('trivy') { 
  137.                     script{ 
  138.       tools.PrintMes('镜像扫描''blue'
  139.      }             
  140.                 } 
  141.             } 
  142.         } 
  143.    
  144.   // 推送镜像 
  145.   stage('Push Image') { 
  146.             steps { 
  147.                 container('docker') { 
  148.                     script{ 
  149.       tools.PrintMes('推送镜像''blue'
  150.      }             
  151.                 } 
  152.             } 
  153.         } 
  154.    
  155.         // 部署 
  156.         stage('Deploy DEV') { 
  157.    when { 
  158.     branchName 'dev' 
  159.    } 
  160.             steps { 
  161.                 container('kustomize'){ 
  162.      script{ 
  163.       tools.PrintMes('部署DEV环境','blue'
  164.      } 
  165.     } 
  166.             } 
  167.         } 
  168.   stage('Deploy TEST') { 
  169.    when { 
  170.     branchName 'test' 
  171.    } 
  172.             steps { 
  173.                 container('kustomize'){ 
  174.      script{ 
  175.       tools.PrintMes('部署TEST环境','blue'
  176.      } 
  177.     } 
  178.             } 
  179.         } 
  180.   stage('Deploy UAT') { 
  181.    when { 
  182.     branchName 'uat' 
  183.    } 
  184.             steps { 
  185.                 container('kustomize'){ 
  186.      script{ 
  187.       tools.PrintMes('部署UAT环境','blue'
  188.      } 
  189.     } 
  190.             } 
  191.         } 
  192.   stage('Deploy PRE') { 
  193.    when { 
  194.     branchName 'pre' 
  195.    } 
  196.             steps { 
  197.                 container('kustomize'){ 
  198.      script{ 
  199.       tools.PrintMes('部署PRE环境','blue'
  200.      } 
  201.     } 
  202.             } 
  203.         } 
  204.   stage('Deploy PROD') { 
  205.    when { 
  206.     branchName 'master' 
  207.    } 
  208.             steps { 
  209.                 container('kustomize'){ 
  210.      script{ 
  211.       tools.PrintMes('部署PROD环境','blue'
  212.      } 
  213.     } 
  214.             } 
  215.         } 
  216.    
  217.   // 跟踪应用启动情况 
  218.   stage('Check App Start') { 
  219.    steps{ 
  220.     container('kubedog'){ 
  221.      script{ 
  222.       tools.PrintMes('跟踪应用启动''blue'
  223.      } 
  224.     } 
  225.    } 
  226.   } 
  227.    
  228.         // 接口测试 
  229.         stage('InterfaceTest') { 
  230.             steps { 
  231.                 sh 'echo "接口测试"' 
  232.             } 
  233.         } 
  234.  
  235.     } 
  236.     // 构建后的操作 
  237.     post { 
  238.         success { 
  239.             script { 
  240.                 println('success:只有构建成功才会执行'
  241.                 currentBuild.description += '\n构建成功!' 
  242.                 dingmes.SendDingTalk("构建成功 ✅"
  243.             } 
  244.         } 
  245.         failure { 
  246.             script { 
  247.                 println('failure:只有构建失败才会执行'
  248.                 currentBuild.description += '\n构建失败!' 
  249.                 dingmes.SendDingTalk("构建失败 ❌"
  250.             } 
  251.         } 
  252.         aborted { 
  253.             script { 
  254.                 println('aborted:只有取消构建才会执行'
  255.                 currentBuild.description += '\n构建取消!' 
  256.                 dingmes.SendDingTalk("构建失败 ❌","暂停或中断"
  257.             } 
  258.         } 
  259.     } 

(3)在Gitlab上配置钩子 settings->webhook

到这里,Gitlab和Jenkins集成就差不多完成了,后面就是具体的调试以及配置了。

写到最后

道路千万条,适合自己才最好。

上面是根据工作的实际情况做的运维发布,整体思路还有实现方式并不复杂,主要是充分利用各个软件的webhook能力,以及充分利用Jenkins灵活的插件功能,使得从创建发布计划和执行发布进行打通。

 

个人觉得还是有必要记录一下,也希望能帮助到有这方面需要的人。

 

来源:运维开发故事内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯