運維工單的應用


一.說明

最開始培訓完入行的2年里,進的幾家公司和面試遇到的基本都是機器在200個虛擬機以下,運維加上我也就1-2個人。

這種都是自己說了算,做了什么操作自己記住就行了,添加權限也都是開發說一下這邊就給加上了,流程配合之間都靠嘴對嘴的傳遞,當然也可能用qq和微信。

工作環境還是很重要的,現在待的項目運維多的時候5個,虛擬機300往上,還有一大堆別的雲產品要維護。這就有必要進行分工了,而不是大家誰閑着就做,那會導致需求人找不到誰在負責,而且負責人也會來回變動。

那需求就來了,根據日常工作發現如下問題:
1.開發不知道找誰能把這件事做成
2.開發來申請添加權限、用qq之類的進行說明描述
3.因為每個人負責一塊,都參與工作,沒人知道整體進度
4.某個運維做了一些操作別人不太清楚
5.這塊他負責的,現在他請假了,接手后不知道怎么做

那看看開發怎么怎么解決上述問題的:
1.產品經理有需求要提jira
2.在jira上有任務表,可以看到每個人接到的任務,涉及哪一塊
3.代碼寫完后合並到master分支要開發組長去確認,注釋也寫的很多
file

具體還會有相應的工作流,將每個需求都從頭到尾追蹤好,后面上線測試環境甚至生產環境都有相應的管理流程。
file

二.初代設計

最開始想的是在內部confluence(一個筆記網站)上記錄下我們有哪些任務要做,按照日期划分,每天都記錄下,任務名稱后面寫上名字。
file

當然對於外部的需求,例如加權限,解決一些jenkins發版上的配置錯誤等等都是完成后來這里補。

現在想想真的很蠢,這記錄和沒記錄的區別完全不大,雖然知道誰什么時間做了哪件事,但維護起來實在費心費力,和其它組的交互也是原始的嘴對嘴交流。

同時這個也完全看不出[任務進度]、[誰在划水]、[某類任務數量]、[當月故障數量]等等,也就是只記錄了,但統計非常困難,需要人工去數。

在發現開發用jira后,探索了一下,發現確實很好用,可以實現我們的需求。通過搭配釘釘通知和看版,再建立好清晰完善的工作流程,可以最大效率避免在開發流程上花時間。

三.效果展示

用jira建立2個項目,一個是對外工單用於外部需求的處理,一個是對內工單只內部使用記錄任務。

給區分開是因為夾雜在一起會很亂,內部都好說就幾個人大家都按照任務進行類別創建,比如購買服務器就建立[資金管理]任務,處理故障就建立[故障處理]任務。

但開發是不管這些的,人家不管是申請權限、處理報錯、申請資源全都是[故障處理]這個默認問題類型。所以要精簡為2-3類最好,這里是權限和其它類型。

外部任務:
1.權限申請,這里權限申請會搭配釘釘腳本做超時通知,用戶要定時續期權限,當然可以調整更大的選項,例如6個月。單獨添加申請人選項,是因為申請者可能還沒有jira,或者是外包人員
file

當權限超過規定期限,會給jira的工單發布者和管理員均發送一個釘釘消息
file

2.其它任務
file

內部任務:
1.服務管理,這里是內部的任務,例如發版、搭建服務、備份數據等等操作。對於一個大任務一定要拆開成版本,也就是合集,把任務去細化。
file

不然你隨便寫個k8s優化那就假大空了,沒有一個目標和划水沒有區別,做2天感覺煩躁就懶得做了,就沒有意義了。同時對於生產等重要操作,要編寫配套任務的《操作用例》,你沒猜錯,就是對標測試的《測試用例》。因為運維不求快求穩,文檔操作不出事,比出現問題后補救要成本小得多。
file

2.報警可以選擇幾個類別,這里后面會做zabbix聯動建立jira任務,其實zabbix本身就可以針對每條報警做處理和記錄,但放到jira是統一管理了。
file

3.其它類別,都是自己人,可以把問題做的細致一點,這樣利於后面用jira的篩選器做統計。比如統計某人這個月發版多少次,鼠標勾選幾下就出來結果了。
file

像我自從工單建立后,正式生產發版一共10次
file

四.工單運作流程

對於外部工單,設置為默認經辦人是運維組長,到他那里后,看到釘釘通知,再進行后續任務分配,將人員調動起來。

可以根據jira中查詢每個人的任務量,再到grafana上進行綜合展示,這里還沒做完,后續再補圖,相當於做內部的《看板》,將大家的任務狀態用大盤做可視化。

這樣就會通過大屏看板一目了然,可以找到誰這周任務最少,或者做的拖沓,本來[ELK日志分析]建設這個大項目,里面有3個jira任務,預計是14天完成,結果第一個人任務2周過去了還沒完結,說明有問題。

對於這種,說明任務太有挑戰性,就多給他分配外部工單進行鍛煉,騰出其它組員的時間,晚上加班/值班,也都多安排他來。工單盡量要區分清楚,用強制選項的填選來規定,而不是都在備注里填,很多人懶得去備注里寫。

通知腳本

我是編寫python腳本定時去獲取jira上每個人的最新任務,進行對應人釘釘通知,每個人一個私有釘釘群,由其他運維同事拉一個3人組,加上機器人后再退掉即可,這樣省的麻煩別的同事了。

效果如下,這樣每個人就有一個私人通知的釘釘群,未來也可以增加入gitlab等等其它的私人通知,所以叫[信息通知小助手],群名稱叫[辦公信息通知]。
file

圖中可以看到第一個是我發布的任務別人完成了,當發布任務時,被發布者會收到這個信息,會寫明誰發布的和一些簡要說明。當接單人員完成后,發布者可以知道完成了,具體信息也都會加到附件和評論里,方便查閱。

當然也可以加一些別的工作流程,例如增加一個開始任務也進行通知一下,尤其對開發流程有復雜的工作流,當測試環境上線需要通知測試進行業務功能測試、測試人員完成后確認再通知開發人員進行uat環境上線,這就要每個環境都通知。

申請機器人

1.先添加一個機器人
file

2.選擇自定義類型
file

3.選擇關鍵字,這里意思是發送的信息,必須帶上這些關鍵字才能發成功,也就是圖片里的通知:xxx開頭。復制好token,寫到后續的配置文件里去。
file

具體腳本

定時跑的的腳本,可以設置三分鍾一次,那就3分鍾檢查一次有沒有新任務。
jira_notice.py

#!/usr/bin/python3
#釘釘token關鍵字jira

import datetime, os, sys, json, requests, configparser
from jira import JIRA
from datetime import datetime
from datetime import timedelta


#讀取配置文件
CONF_SITE="/data/tools/python_lib/script_conf.cfg"
cfg = configparser.ConfigParser()
cfg.read(CONF_SITE)

#[jira的url、jira賬號、jira密碼、]
JIRA_URL = cfg['jira']['jira_url']
JIRA_USERNAME = cfg['jira']['jira_username']
JIRA_PASSWORD = cfg['jira']['jira_password']
ISSUE_INFO_FILE = cfg['jira']['issue_info_file']
ISSUE_INFO_SIZE = cfg['jira']['issue_info_size']
START_STATUS_LIST = cfg['jira']['start_status'].split(',')
STOP_STATUS_LIST = cfg['jira']['stop_status'].split(',')
DD_URL = cfg['dingding']['dd_url']


def write_cfg(file_dict):
    #將字典寫入到配置文件里
    with open(ISSUE_INFO_FILE, 'w') as fp:
        fp.write(str(file_dict))

def read_cfg():
    #讀取配置文件內容
    with open(ISSUE_INFO_FILE, 'r') as fp:
        data = fp.read()
    file_dict = eval(data)
    return file_dict

def new_notice(notice_url, nowtime, title, is_summary, is_project, is_type, notice_type, is_notice, key_name):
    #[拼接字符串]
    msg = """### %s \n
> 時間: %s \n
> 概要: %s \n
> 項目: %s \n
> 類型:%s \n
> %s: %s \n
> 地址: [任務地址](%s/browse/%s?) \n
"""

    headers = {'Connection': 'close', "Content-Type": "application/json"}
    data = {"msgtype": "markdown", 
        "markdown": {
            "title": title,
            "text": msg %(title, nowtime, is_summary, is_project, is_type, notice_type, is_notice, JIRA_URL, key_name)
        }
    }

    print(title)
    print(notice_url)
    r = requests.post(notice_url, data=json.dumps(data), headers=headers, verify=False)
    print(r.text)


def jcpzrw_notice(notice_url, nowtime, is_summary, title, is_created, is_apply, is_duration, key_name):
    #[拼接字符串]
    msg = """### %s \n
> 時間: %s \n
> 概要: %s \n
> 申請日期: %s \n
> 申請人: %s \n
> 使用時長:%s \n
> 地址: [任務地址](%s/browse/%s?) \n
"""

    headers = {'Connection': 'close', "Content-Type": "application/json"}
    data = {"msgtype": "markdown", 
        "markdown": {
            "title": title,
            "text": msg %(title, nowtime, is_summary, is_created, is_apply, is_duration, JIRA_URL, key_name)
        }
    }

    print(title)
    r = requests.post(notice_url, data=json.dumps(data), headers=headers, verify=False)
    print(r.text)

def main():
    #[時間]
    nowtime = datetime.now()
    nowtime = str(nowtime.strftime('%Y-%m-%d %H:%M:%S'))

    #讀取記錄
    if os.path.exists(ISSUE_INFO_FILE):
        issue_data_dict = read_cfg()
    else:
        issue_data_dict = {}

    #查詢最近24小時內所有更新的issu
    jira = JIRA(basic_auth=(JIRA_USERNAME, JIRA_PASSWORD), options = {'server': JIRA_URL})
    query_sql = 'updated >= -24h ORDER BY updated DESC'
    query_info = jira.search_issues(query_sql  ,maxResults=100000)

    print("循環檢查jira任務")
    for i in query_info: #循環任務
        key_name = i.key #不能直接用,直接用是一個對象
        issue = jira.issue(key_name)
        is_summary = str(issue.fields.summary) #概要
        is_project = str(issue.fields.project) #項目名
        is_type = str(issue.fields.issuetype) #類型
        is_assignee = str(issue.fields.assignee) #經辦人
        is_creator = str(issue.fields.creator) #創建人
        is_status = str(issue.fields.status) #狀態

        #查看狀態是否是新建或者結束
        if is_status in STOP_STATUS_LIST:
            #查看是否在記錄中
            if key_name in issue_data_dict.keys():
                if  issue_data_dict[key_name][1] == "start": #issue從開始變為結束通知
                    one_user = "creator"
                else:
                    one_user = "none"
            else:
                one_user = "creator"
            job_status = "stop"

        else:
            #查看是否在記錄中
            if key_name in issue_data_dict.keys():
                if is_assignee != issue_data_dict[key_name][0]: #經辦人變了通知
                    one_user = "assignee"
                elif issue_data_dict[key_name][1] == "stop": #狀態重置了通知
                    one_user = "assignee"
                else:
                    one_user = "none"
            else:
                one_user = "assignee"
            job_status = "start"

        #把記錄寫入到字典中
        issue_data_dict[key_name] = [is_assignee, job_status]
        jira_name_list = cfg.sections()

        #發送通知
        if one_user == "assignee":
            if is_assignee in jira_name_list:
                dd_token = cfg[is_assignee]['dd_token']
                notice_url = DD_URL + dd_token
                title = "通知: jira新增任務" + key_name
                new_notice(notice_url, nowtime, title, is_summary, is_project, is_type, "報告人", is_creator, key_name)
            else:
                print(key_name + "中報告人的釘釘並未被記錄")
        elif one_user == "creator":
            if is_creator in jira_name_list:
                dd_token = cfg[is_creator]['dd_token']
                notice_url = DD_URL + dd_token
                title = "通知: jira完成任務" + key_name
                new_notice(notice_url, nowtime, title, is_summary, is_project, is_type, "經辦人", is_assignee, key_name)
            else:
                print(key_name + "經辦人的釘釘並未被記錄")
        else:
            print(key_name + "已經通知過,跳過通知")

    #清理字典文件,不要太龐大
    while len(issue_data_dict) > int(ISSUE_INFO_SIZE):
        tmp_key = list(issue_data_dict.keys())[0]
        if tmp_key == "JCPZRW_Usage_list":
            continue
        else:
            del issue_data_dict[tmp_key]

    write_cfg(issue_data_dict)

main()

配置文件腳本,因為我這里對所有pyton腳本進行了統一管理,凡是配置都放到固定文件里,就單獨做了一個文件。這里填寫jira地址和賬號密碼,用於調用API,不一定非要管理賬號,只要可以看到所有項目即可,因為要統計項目信息。

最后面的張三李四是每個人的釘釘顯示中文名稱,jira賬號名和他的釘釘機器人的token號。1000是臨時文件保存多少issue信息,防止過大。后面的status是jira工作流的狀態信息,一般《新建》代表任務開始,《關閉》代表任務完成,這里默認即可。最后notice_user表示權限過期時候通知哪些管理員。
file

script_conf.cfg

[jira]
jira_url = http://10.0.1.1:8080
jira_username = admin
jira_password = 123456
issue_info_file = /tmp/jira_issue_info.dict
issue_info_size = 1000
start_status = 待辦,待處理,已登記,新建,NEW
stop_status = DONE,線上驗證通過,關閉,問題關閉,已驗收,已關閉
jcpzrw_notice_user = 張三,李四

[dingding]
dd_url = https://oapi.dingtalk.com/robot/send?access_token=

[張三]
jira_name=zhangsan
dd_token=cdasdsadasd2dadas

[李四]
jira_name=lisi
dd_token=adasdadada


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM