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

作者:乔克
公众号:运维开发故事
上线发布是运维的日常工作,常见的发布方式有:
- 手动发布
- Jenkins发布平台
- Gitlab CI
- ......
除此之外还有需要开源软件,他们都有非常不错的发布管理功能。
面临的问题
作为运维人员,上线发布是必不可少的一环,一个正常的发布流程是怎么样的?
- 需求方提发布任务,走发布流程
- 供应方执行发布上线
环节看似简单,但是中间其实是有断层的。一般企业在走上线流程都是通过一些公共渠道,比如邮件、钉钉、飞书的流程,这些都很难和运维执行上线发布平台进行关联上,而且也不够直观。所以我们就需要解决以下几个问题:
- 流程和运维平台建立连接
- 从发起到结束形成闭环
为啥选择JIRA?
JIRA优秀的项目管理,问题跟踪的工具,另外它的流程管理和看板模式也能够非常直观看到目前流程处在什么位置。另外它可以通过webhook和其他平台建立友好的连接,方便扩展。再者对于开发、测试、项目管理人员等来说Jira是他们日常的工具,使用熟练度非常高,降低了额外的学习成本。鉴于此,我们选择JIRA作为运维发布平台,争取做到一个平台做所有事。
方案设计
设计思路
充分利用Jira、Gitlab的webhook功能,以及Jenkins的灵活性。
- Jira上更新状态触发Jenkins执行合并分支流水线
- Gitlab上代码合并成功后触发Jenkins执行发布流水线
- 将发布结果通过钉钉等软件通知相应的人
整体思路相对简单,难点主要集中在Jenkins获取Jira、Gitlab的数据,所幸Jenkins的插件功能非常丰富,这里就使用Generic Webhook Trigger插件,可以很灵活地获取到触发软件地信息。
发布流程方案
然后整理出如下地发布流程。

涉及软件
| 软件 | 功能 |
|---|---|
| Jira | 发布流程管理 |
| Jenkins | 执行各种流水线 |
| Gitlab | 代码仓库 |
| Kubernetes | 应用管理 |
| Helm/kustomize | 包管理 |
| 钉钉 | 消息通知 |
| trivy | 镜像扫描 |
| 镜像仓库 | 阿里云镜像仓库 |
PS:这里没有具体的软件部署
Jira与Jenkins进行集成合并分支
Jenkins配置
Jenkins的配置主要有两部分,如下:
- 配置Jenkins ShareLibrary功能
- 编写Jira触发相应的Jenkinsfile
(1)Jenkins上配置ShareLibarary
系统配置-->系统配置-->Global Pipeline Libraries

(2)创建流水线,配置Webhook以及添加Jenkinsfile
- 配置触发器
先配置一个变量和正则

再配置一个Token即可

- 配置流水线,添加对于的Jenkinsfile

(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
建立工作流

将工作流关联项目组

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

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

然后进行拖拽或者点击发布按钮,即可改变状态,触发流水线进行相应的操作了。
Gitlab与Jenkins集成发布系统
开发分支简要
这里主要使用的是功能分支开发模式,主要分为以下几个分支:
- DEV分支:开发环境分支
- TEST分支:测试环境分支
- UAT分支:联调环境分支
- PRE分支:预发布环境分支
- MASTER分支:生产环境分支
代码合并路线是:DEV->TEST->UAT->PRE->MASTER
然后根据不同的分支判断执行不同环境的部署。
Jenkins配置流水线
(1)配置Webhook插件参数

获取Gitlab分支

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



定义过滤正则表达式

这样就只有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

到这里,Gitlab和Jenkins集成就差不多完成了,后面就是具体的调试以及配置了。
写到最后
道路千万条,适合自己才最好。
上面是根据工作的实际情况做的运维发布,整体思路还有实现方式并不复杂,主要是充分利用各个软件地webhook能力,以及充分利用Jenkins灵活的插件功能,使得从创建发布计划和执行发布进行打通。
个人觉得还是有必要记录一下,也希望能帮助到有这方面需要的人。
基于Jira的运维发布平台的设计与实现的更多相关文章
- 不看好运维竖井产品模式,优云打造融合化运维PaaS平台
2018年1月13号中国双态运维用户大会上,优云软件总裁刘东海接受了36Kr记者的专访,期间谈到了新时代下的企业运维模式,新兴技术和传统运维的融合以及优云未来的发展方向等问题.以下为访谈实录: 优云软 ...
- 建设DevOps统一运维监控平台,全面的系统监控 Zabbix VS Nagios VS Open-Falcon OR Prometheus
前言 随着Devops.云计算.微服务.容器等理念的逐步落地和大力发展,机器越来越多,应用越来越多,服务越来越微,应用运行基础环境越来多样化,容器.虚拟机.物理机不一而足.面对动辄几百上千个虚拟机.容 ...
- 开源运维自动化平台-opendevops
开源运维自动化平台-opendevops 简介 官网 | Github| 在线体验 CODO是一款为用户提供企业多混合云.自动化运维.完全开源的云管理平台. CODO前端基于Vue iview开发. ...
- 详解Linux运维工具:运维流程管理、运维发布变更、运维监控告警
概述 应用上线后,运维工作才刚开始,具体工作可能包括:升级版本上线工作.服务监控.应用状态统计.日常服务状态巡检.突发故障处理.服务日常变更调整.集群管理.服务性能评估优化.数据库管理优化.随着应用 ...
- 13. Redis监控运维云平台CacheCloud
13. Redis监控运维云平台CacheCloud13.1 CacheCloud是什么13.1.1 现有问题13.1.2 CacheCloud基本功能13.2 快速部署13.2.1 CacheClo ...
- 【原创】基于Docker的CaaS容器云平台架构设计及市场分析
基于Docker的CaaS容器云平台架构设计及市场分析 ---转载请注明出处,多谢!--- 1 项目背景---概述: “在移动互联网时代,企业需要寻找新的软件交付流程和IT架构,从而实现架构平台化,交 ...
- ylbtech-KeFuYunWei(服务运维考核系统)-数据库设计
ylbtech-DatabaseDesgin:ylbtech-KeFuYunWei(服务运维考核系统)-数据库设计 DatabaseName:KEFUYUNWEI Model:Admin 用户后台管理 ...
- Docker搭建Jenkins+Gogs+Maven/Gradle——代码自动化运维部署平台(三)
一.简介 1.CI/CD CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法.CI/CD 的核心概念是持续集成.持续交付和持续部署.作为一个面向开发和运营团队的解决方案,CI/C ...
- 基于 ANSIBLE 自动化运维实践
摘要:运维这个话题很痛苦,你做任何的产品都离不开运维.不管你用什么语言.什么平台.什么技术,真正能够决定你产品成熟度的很有可能就是你运维的能力.取自 云巴 CEO 张虎在 ECUG 大会上的分享. 云 ...
随机推荐
- python 闭包函数与装饰器
1.什么是闭包函数 (1):什么是闭包函数: #内部函数包含对外部作用域而非全局作用域的引用, 简而言之, 闭包的特点就是内部函数引用了外部函数中的变量. 在Python中,支持将函数当做对象使用,也 ...
- 一文带你掌握MySQL查询优化技能
查询优化本就不是一蹴而就的,需要学会使用对应的工具.借鉴别人的经验来对SQL进行优化,并且提升自己. 分享一套博主觉得讲的很详细很实用的MySQL教程给大家,可直接点击观看! https://www. ...
- WordPress伪静态规则设置
伪静态:即网站本身是动态网页如.php..asp..aspx等格式,而这类网页还带"?"加参数来读取数据库.开启伪静态后,动态网页即被转换重写成静态网页类型页面. WordPres ...
- 过 DNF TP 驱动保护(一)
过 DNF TP 驱动保护(一) 文章目录: 01. 博文简介: 02. 环境及工具准备: 03. 分析 TP 所做的保护: 04. 干掉 NtOpenProc ...
- 文档翻译第001篇:Process Monitor帮助文档(Part 1)
[译者注] Process Monitor是一款非常著名的系统进程监视软件.总体来说,Process Monitor相当于Filemon+Regmon,其中的Filemon专门用来监视系统中所有文件的 ...
- UVA11549计算器谜题
题意: 有一个计算机只能保留数字的前n位,你有一个数字k(k<=9),反复平方后在计算机上显示的最大数字是多少. 思路: 显然这个题目是有循环节的,为什么有循环节?首先 ...
- Windows PE第6章 栈与重定位表
第六章 栈与重定位表 本章主要介绍栈和代码重定位.站和重定位表两者并没有必然的联系,但都和代码有关.栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构. ...
- windows-API劫持(API-HOOK)
API Hook ApiHook又叫做API劫持,也就是如果A程序调用了B.cll里面的C函数,我们可以做到当A调用C函数执行的时候,直接执行我们自己事先准备好的函数,之后我们在执行真正的C,当然我们 ...
- JSON对象与字符串的互换——JSON.parse()和JSON.stringify()
parse用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":&qu ...
- Day009 面向对象和方法回顾
面向过程&面向对象 面向过程思想 步骤清晰简单,第一步做什么,第二步做什么..... 面象过程适合处理一些较为简单的问题 面向对象思想 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些 ...