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

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

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


  • 手动发布
  • Jenkins发布平台
  • Gitlab CI
  • ......


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


面临的问题


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


  • 需求方提发布任务,走发布流程
  • 供应方执行发布上线


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


  • 流程和运维平台建立连接
  • 从发起到结束形成闭环


为了选择JIRA?


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


方案设计


设计思路


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


  • Jira上更新状态触发Jenkins执行合并分支流水线
  • Gitlab上代码合并成功后触发Jenkins执行发布流水线
  • 将发布结果通过钉钉等软件通知相应的人


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


发布流程方案


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


62739dcdfb92127da878b306057c8c7b.png


涉及软件


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


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


Jira与Jenkins进行集成合并分支


Jenkins配置


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


  • 配置Jenkins ShareLibrary功能
  • 编写Jira触发相应的Jenkinsfile


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


b7808989ad99ca99d7f75dd8ed72452c.png


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


  • 配置触发器


先配置一个变量和正则


5baeb6389cded08508e510280ee044d7.png


再配置一个Token即可


782b99555d872850b011c214a4e2911a.png


  • 配置流水线,添加对应的Jenkinsfile


ceed0bc3ece0b5eabb012fa5bd607829.png


(3)Jenkinsfile的主要逻辑如下


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


  • 获取Jira的配置信息进行解析
  • 根据不同信息执行不同的操作
  • 合并分支主要是通过调Gitlab的API接口完成


#!groovy
@Library('lotbrick') _
def gitlab = new org.devops.gitlab()
def tool = new org.devops.tools()
def dingmes = new org.devops.sendDingTalk()
pipeline {
    agent { node { label "master"}}
    environment {
        DINGTALKHOOK = "https://oapi.dingtalk.com/robot/send?access_token=xxxx"   
    }
    stages{
        stage("FileterData"){
            steps{
                script{
                    response = readJSON text: """${webHookData}"""
                    // println(response)
                    env.eventType = response["webhookEvent"]
                    if (eventType == "jira:issue_updated"){
                        // 获取状态值
                        env.jiraStatus = response['issue']['fields']['status']['name']
                        env.gitlabInfos = response['issue']['fields']['customfield_10219']
                        infos = "${gitlabInfos}".split("\r\n")
                        for (info in infos){
                            prName = "$info".split("/")[0]
                            // brName = "$info".split("/")[1]
                            brName = info - "${prName}/"
                            println(prName)
                            println(brName)
                            if (jiraStatus == "已发布(UAT)"){
                                println('进行合并PRE分支操作')
                            }else if (jiraStatus == "已发布(PROD)"){
                                println('进行合并PROD分支操作')
                            }else if (jiraStatus == "已完成"){
        println('进行分支打Tag并删除原分支')
                            }else{
                                println("查无此项")
                            }
                        }
                    }
                }
            }
        }
    }
    // 构建后的操作
 post {
  failure {
   script{ 
    println("failure:只有构建失败才会执行")
    dingmes.SendDingTalk("分支合并失败 ❌")
   }
  }
  aborted {
            script{
    println("aborted:只有取消构建才会执行")
    dingmes.SendDingTalk("分支合并取消 ❌","暂停或中断")
            }
  }
 }
}


以上Jenkins上配置基本完成。


Jira上配置


Jira上的主要配置如下:


  • 建立工作流
  • 工作流关联项目
  • 配置项目触发Webhook


建立工作流


d737ed622fb3a2759cec4ee3568b84f6.png


将工作流关联项目组


c49c32e984b39f0ba255ae877e4c8a76.png


配置webhook


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


4a2100e960d5d7f6c1ad484d9e730155.png


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


82d529a25ee94e93a1d882a8740573b0.png


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


Gitlab与Jenkins集成发布系统


开发分支简要


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


  • DEV分支:开发环境分支
  • TEST分支:测试环境分支
  • UAT分支:联调环境分支
  • PRE分支:预发布环境分支
  • MASTER分支:生产环境分支


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


Jenkins配置流水线


(1)配置Webhook插件参数


c6bbbf86f1f4f8071f3b09246d99cbfe.png


获取Gitlab分支


a17bde21ddde8a58a7bc9114a728db76.png


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


b532ea74371d79a5dbda5073c7f45aa3.png


984b73756db343c82974621c3b281435.png


7e212a15204176ae1db25feddfbdd090.png


定义过滤正则表达式


ffa6a71b8197582ad033b4fa93a4408c.png


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


(2)配置Jenkinsfile


def labels = "slave-${UUID.randomUUID().toString()}"
// 引用共享库
@Library('jenkins_shareLibrary')
// 应用共享库中的方法
def tools = new org.devops.tools()
def branchName = ""
// 获取分支
if ("${gitlabWebhook}" == "gitlabPush"){
    branchName = branch - "refs/heads/"
 currentBuild.description = "构建者${userName} 分支${branchName}"
}
pipeline {
    agent {
        kubernetes {
            label labels
            yaml """
apiVersion: v1
kind: Pod
metadata:
  labels:
    some-label: some-label-value
spec:
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
      type: ''
  - name: maven-cache
    persistentVolumeClaim:
      claimName: maven-cache-pvc
  containers:
  - name: jnlp
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/inbound-agent:4.3-4
  - name: maven
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/maven:3.5.0-alpine
    command:
    - cat
    tty: true
    volumeMounts:
    - name: maven-cache
      mountPath: /root/.m2
  - name: docker
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/docker:19.03.11
    command:
    - cat
    tty: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  - name: sonar-scanner
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/sonar-scanner:latest
    command:
    - cat
    tty: true
  - name: kustomize
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/kustomize:v3.8.1
    command:
    - cat
    tty: true
  - name: kubedog
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/kubedog:v0.5.0
    command: ['cat']
    tty: true
  - name: trivy
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/trivy:v2
    command: ['cat']
    tty: true
    volumeMounts:
      - name: docker-sock
        mountPath: /var/run/docker.sock
"""
        }
    }
    environment {
        auth = 'joker'
    }
    options {
        timestamps()    // 日志会有时间
        skipDefaultCheckout()    // 删除隐式checkout scm语句
        disableConcurrentBuilds()    //禁止并行
        timeout(time:1, unit:'HOURS') //设置流水线超时时间
    }
    stages {
        // 拉取代码
        stage('GetCode') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: "${gitBranch}"]],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [],
                    submoduleCfg: [],
                    userRemoteConfigs: [[credentialsId: '83d2e934-75c9-48fe-9703-b48e2feff4d8', url: "${gitUrl}"]]])
            }
        }
        // 单元测试和编译打包
        stage('Build&Test') {
            steps {
                container('maven') {
                    script {
                        tools.PrintMes('编译打包', 'blue')
                    }
                }
            }
        }
        // 代码扫描
        stage('CodeScanner') {
            steps {
                container('sonar-scanner') {
                    script {
      tools.PrintMes('代码扫描', 'blue')
                    }
                }
            }
        }
        // 构建镜像
        stage('BuildImage') {
            steps {
                container('docker') {
     script {
      tools.PrintMes('构建镜像', 'blue')
     }
    }
            }
        }
  // 镜像扫描
  stage('Vulnerability Scanner') {
            steps {
                container('trivy') {
                    script{
      tools.PrintMes('镜像扫描', 'blue')
     }            
                }
            }
        }
  // 推送镜像
  stage('Push Image') {
            steps {
                container('docker') {
                    script{
      tools.PrintMes('推送镜像', 'blue')
     }            
                }
            }
        }
        // 部署
        stage('Deploy DEV') {
   when {
    branchName 'dev'
   }
            steps {
                container('kustomize'){
     script{
      tools.PrintMes('部署DEV环境','blue')
     }
    }
            }
        }
  stage('Deploy TEST') {
   when {
    branchName 'test'
   }
            steps {
                container('kustomize'){
     script{
      tools.PrintMes('部署TEST环境','blue')
     }
    }
            }
        }
  stage('Deploy UAT') {
   when {
    branchName 'uat'
   }
            steps {
                container('kustomize'){
     script{
      tools.PrintMes('部署UAT环境','blue')
     }
    }
            }
        }
  stage('Deploy PRE') {
   when {
    branchName 'pre'
   }
            steps {
                container('kustomize'){
     script{
      tools.PrintMes('部署PRE环境','blue')
     }
    }
            }
        }
  stage('Deploy PROD') {
   when {
    branchName 'master'
   }
            steps {
                container('kustomize'){
     script{
      tools.PrintMes('部署PROD环境','blue')
     }
    }
            }
        }
  // 跟踪应用启动情况
  stage('Check App Start') {
   steps{
    container('kubedog'){
     script{
      tools.PrintMes('跟踪应用启动', 'blue')
     }
    }
   }
  }
        // 接口测试
        stage('InterfaceTest') {
            steps {
                sh 'echo "接口测试"'
            }
        }
    }
    // 构建后的操作
    post {
        success {
            script {
                println('success:只有构建成功才会执行')
                currentBuild.description += '\n构建成功!'
                dingmes.SendDingTalk("构建成功 ✅")
            }
        }
        failure {
            script {
                println('failure:只有构建失败才会执行')
                currentBuild.description += '\n构建失败!'
                dingmes.SendDingTalk("构建失败 ❌")
            }
        }
        aborted {
            script {
                println('aborted:只有取消构建才会执行')
                currentBuild.description += '\n构建取消!'
                dingmes.SendDingTalk("构建失败 ❌","暂停或中断")
            }
        }
    }
}


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


5248274675ed463a76f4f731459b5768.png


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


写到最后


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


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


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

相关文章
|
运维 监控 Java
java乡镇卫生院、二甲医院云HIS运维平台源码
运营管理是综合管理系统的核心部分,由运营商和医疗机构管理人员使用,运营管理包括:机构管理、药品目录管理、用户管理、角色管理、字典管理、模板管理、参数设置、消息管理、售后服务、运营配置、外部系统11个子模块,实现机构、用户、角色管理、药品目录管理以及通用的字典管理;可以根据业务需要为各医疗机构定制病历模板和报表模板;可以对医疗机构收费外接设备进行参数设置,对业务进行配置;可以管理消息及售后信息等。
147 3
|
26天前
|
运维 监控 自动驾驶
低代码运维平台:是“运维福音”,还是“甩手掌柜”?
低代码运维平台:是“运维福音”,还是“甩手掌柜”?
89 29
|
4月前
|
运维 监控 Linux
WGCLOUD运维平台的分布式计划任务功能介绍
WGCLOUD是一款免费开源的运维监控平台,支持主机与服务器性能监控,具备实时告警和自愈功能。本文重点介绍其计划任务功能模块,可统一管理Linux和Windows主机的定时任务。相比手动配置crontab或Windows任务计划,WGCLOUD提供直观界面,通过添加cron表达式、执行指令或脚本并选择主机,即可轻松完成任务设置,大幅提升多主机任务管理效率。
|
7月前
|
存储 人工智能 运维
阿里云操作系统控制台评测:国产AI+运维 一站式运维管理平台
本文详细评测了阿里云操作系统控制台,作为一款集运维管理、智能助手和系统诊断于一体的工具,它为企业提供了高效管理云资源的解决方案。文章涵盖登录与服务开通、系统管理与实例纳管、组件管理与扩展功能、系统诊断与问题排查以及实时热点分析与性能优化等内容。通过实际操作展示,该平台显著提升了运维效率,并借助AI智能助手简化了复杂操作。建议进一步完善组件库并增强第三方兼容性,以满足更多高级运维需求。
441 2
|
9月前
|
运维 监控 Cloud Native
构建深度可观测、可集成的网络智能运维平台
本文介绍了构建深度可观测、可集成的网络智能运维平台(简称NIS),旨在解决云上网络运维面临的复杂挑战。内容涵盖云网络运维的三大难题、打造云原生AIOps工具集的解决思路、可观测性对业务稳定的重要性,以及产品发布的亮点,包括流量分析NPM、网络架构巡检和自动化运维OpenAPI,助力客户实现自助运维与优化。
|
运维 算法 Java
springboot医院信息化云HIS运维平台源码
1、门诊部分 挂号及预约、划价及收费、门诊处方及病历、医生排班... 2、住院部分 入院及出院登记、住院收费、住院清单、出院结算、住院医生工作站、住院护士工作站... 3、电子病历 医嘱管理、护嘱管理、电子病历、护理病历、病历质控...
157 0
|
SQL 运维 前端开发
一款现代化、高颜值的一站式智能运维管理平台
orion-ops-pro —— 一款现代化、高颜值的一站式智能运维管理平台,集资产管理、资产授权、批量执行、计划任务、WebShell、WebSftp、角色管理、系统管理等功能于一体,致力于简化运维团队的治理工作。
210 1
一款现代化、高颜值的一站式智能运维管理平台
|
开发框架 运维 前端开发
构建一体化运维平台的八大功能
【6月更文挑战第6天】构建一体化运维平台的关键8个基本功能。
|
设计模式 运维 监控
运维一体化平台的能力要素
【6月更文挑战第7天】一体化运维平台的重要性,旨在建立覆盖运维全生命周期的统一平台,提升效率,保障业务连续性,实现数字化运维管理。

热门文章

最新文章