目的是什么,为什么要开发ChatOps?那是什么?现在各种Ops,DevOps、AIOps、ChatOps、NoOps等等,反正背后的意思就是各种量运维,让运维无处可去。既然如此,我们为什么还要吃力不讨好地开发ChatOps?我的理解是“闲”,以聊天的形式做一些运维工作。典型应用场景如下:(1)结合Jenkins、GitLab、GitHub等CI/CD工具进行构建、发布、代码合并等(2)结合JIRA、Trello等办公系统,塔、禅道、邮件处理任务。(3)结合Kubernetes云平台进行容器的创建、发布等管理。(4)、结合Zabbix、Prometheus、Open-Falcon等监控系统,接收监控消息ChatOps站在巨人的肩膀上发展,也给工作带来了明显的好处:公开透明。所有工作信息都沉淀在同一个聊天平台,并公开给所有相关成员,消除沟通障碍,工作履历可追溯,团队合作更顺畅。上下文共享。减少工作台切换导致的消息截断,保证消息的完整性,使工作接管有序。每个角色和每个工具都成为工作流程的一部分,以创造真正流畅的工作体验。移动友好。您只需与前台预设的机器人对话,即可完成与后台工具和系统的交互。在移动环境下,不需要直接连接很多复杂的工具,大大提高了移动办公的可行性。DevOps文化建设。使用简单的与机器人对话的方式,降低了DevOps的接受门槛,更容易将这种自动化办公的概念延伸到团队的每一个角落。本文简单使用钉钉机器人来做ChatOps。添加钉钉机器人登录钉钉开发者后台,选择应用开发>内部开发>机器人,点击创建应用。然后记住AppKey和AppSecret,如下:配置服务器出口IP和消息接收地址,如下:注意:配置https地址需要相应的有效证书。开发机器人HTTPHEADER{"Content-Type":"application/json;charset=utf-8","timestamp":"1577262236757","sign":"xxxxxxxxxx"}参数说明timestamp消息发送时间戳,单位毫秒.sign签名值。开发者需要验证时间戳并签入header来判断是否是钉钉的合法请求,避免其他仿冒钉钉调用开发者的HTTPS服务传输数据。具体验证逻辑如下:时间戳与当前系统时间戳如果相差超过1小时则认为是非法请求。如果标志与开发者计算的结果不一致,则视为非法请求。只有同时验证了时间戳和签名,才能认为是钉钉的合法请求。sign的计算方法:以header中的时间戳+“\n”+机器人的appSecret作为签名串,使用HmacSHA256算法计算签名,再进行Base64编码,得到最终的签名值。使用Go开发的一个示例如下:url""strconv""github.com/gin-gonic/gin")(appSecret="xxx-xxx"baseHookUrl="https://oapi.dingtalk.com/robot/send"accessToken="xxx")//Body请求正文传入{MsgType`json:"msgtype"`Text*Text`json:"text"`MsgId`json:"msgId"`CreateAt`json:"createAt"`ConversationType`json:"conversationType"`//1-单个聊天,2组聊天ConversationId`json:"conversationId"`////加密会话IDConversationTitle`json:"conversationId"`//会话标题(仅用于群聊)SenderId`json:"senderId"`SenderNick`json:"senderNick"`SenderCorpId`json:"senderCorpId"`SenderStaffId`json:"senderStaffId"`ChatbotUserId`json:"chatbotUserId"`AtUsers[][]`json:"atUsers"`SessionWebhook`json:"sessionWebhook"`IsAdmin`json:"isAdmin"`}//MessageDingdingmessageMessage{MsgType`json:"msgtype"`At`json:"at,omitempty"`Text*Text`json:"text,omitempty"`Markdown*Markdown`json:"markdown,omitempty"`Link*Link`json:"link,omitempty"`}//定义用户谁需要At{AtMobiles[]`json:"atMobiles,omitempty"`IsAtAll`json:"isAtAll,omitempty"`}//MarkDowntypeMarkdown{Title`json:"title,omitempty"`Text`json:"text,omitempty"`}//Text文本类型Text{Content`json:"content,omitempty"`}//链接feedCard类型链接参数Link{Title`json:"title,omitempty"`Text`json:"text,omitempty"`MessageURL`json:"messageURL,omitempty"`PicURL`json:"picURL,omitempty"`}(){r:=gin.New()r.POST("/chatops",(c*gin.Context){//定义两个变量,其中data为请求体,sign为签名(signdata[])//获取body中的请求参数//fmt.Println(c.Request.Header)httpSign:=c.Request.Header.Get("Sign")httpTimestamp:=c.Request.Header.Get("Timestamp")//如果时间戳与系统当前时间戳相差大于1小时,视为非法请求tsi,err:=strconv.ParseInt(httpTimestamp,10,64);err!={fmt.Println("请求头可能没有附加时间戳信息!!")}{data,_=ioutil.ReadAll(c.Request.Body)sign=signature(tsi,appSecret)}//验证passedhttpSign==sign{//获取消息体传入err:=json.Unmarshal(data,&body);err!={fmt.Println(err)}//获取文本内容content:=body.Text.Contentfmt.Println(content)//根据要处理的内容进行判断//将处理结果返回给机器人sendDingTalk("Master,"+content)}})r.Run(":9000")}(ts,secret){strToSign:=fmt.Sprintf("%d\n%s",ts,secret)hmac256:=hmac.New(sha256.New,[](秘密))hmac256.Write([](strToSign))data:=hmac256.Sum()base64.StdEncoding.EncodeToString(data)}(content){msg:=&Message{MsgType:"markdown",在:在{},Markdown:&Markdown{Title:"MessageTest",Text:content,},}query:=url.Values{}query.Set("access_token",accessToken)hookUrl,_:=url.Parse(baseHookUrl)hookUrl.RawQuery=复制代码query.Encode()消息内容t,_:=json.Marshal(msg)//创建请求req,err:=http.NewRequest("POST",hookUrl.String(),bytes.NewReader(msgContent))err!={//处理错误fmt.Println(err)}client:=&http.Client{}//设置请求头req.Header.Set("Content-Type","application/json;charset=utf-8")//发送请求resp,err:=client.Do(req)err!={//处理错误fmt.Println(err)}//关闭请求resp.Body.Close()}然后部署到对应的服务器,在钉钉对话测试组中测试如下:可以看到可以正常回答,具体返回内容根据业务逻辑开发。注意:钉钉机器人需要添加特定的关键词。只有当内容有相应的关键字时,它们才会被列在组中。收到消息。
