引言:很久没有认真的写一篇分享了,今天记录一下处理 Jenkins Master 和 Slave 之间连接中断的时候的如何预警的问题。

背景

我们基于 Jenkins 有一系列的持续集成工作,类如打包,API 可达性监控,Gerrit Code Verify 等等,但是经过这么长时间的观察,我发现 Jenkins master 经过一段时间就会有报错,
导致我们的 Slave 和 Master 连接中断,这个时候,所有的 Nodes 都会出现 Offline。

我特意找了一下,没注意到 Jenkins 的插件可以检测并随时监控反馈 Offline 的问题预警。所以想通过自己的方式解决。

确认有无判断 OFFLINE 出现的 API

通过寻找,确认https://<Jenkins域名>/computer/<Slave name>/api/json,这里有查找 Slave 和 Master 断连接的信息。只截取我需要的内容

{
    "numExecutors": 4, 
    "offline": false, 
    "offlineCause": null, 
    "offlineCauseReason": "", 
    "oneOffExecutors": [ ], 
    "temporarilyOffline": false
}

可以看到这里的 offline 的字段是 False,说明连接是正常的,当 Offline 的值是 True 的时候,就可以预警了。

解决方案

#!/bin/bash

JENKINS_URL="xxx"
JENKINS_NODE_MAC=`hostname -s | cut -d'0' -f1`
JENKINS_NODE_NR=`hostname -s | cut -d'0' -f2`

# 关注一下Jenkins设置,Nodename是什么
JENKINS_NODENAME="${JENKINS_NODE_MAC}"0"${JENKINS_NODE_NR}"
CHECKED=`curl -u xxx:xxx --silent \
$JENKINS_URL/computer/$JENKINS_NODENAME/api/json | grep -o '"offline":true' |\
cut -d':' -f2`

if [[ "$CHECKED" == "true" ]]; then
        echo "INFO: $JENKINS_NODENAME was offline and trigger Python Mail Script"
        # 执行预警操作
        exit 0
fi
echo "INFO: $JENKINS_NODENAME is online, no need to restart."
exit 0

之前的思路是通过 Mac 内自带的 iMessage,然后编写了脚本,操作分为两步:
先编写一个 iMessage.applescript

#!/usr/bin/osascript
on run {targetBuddyPhone, targetMessage}
    tell application "Messages"
        set targetService to 1st service whose service type = iMessage
        set targetBuddy to buddy targetBuddyPhone of targetService
        send targetMessage to targetBuddy
    end tell
end run

然后调用osascript jenkins.applescript +86-xxx-xxxx-xxxx "Slave连接中断"
奇怪的是 iMessage,一直连接不了,我试了各种方式,升级系统,重新登录账号,我确认脚本没有问题,但是 iMessage 就是连接登录不了。没办法,还是通过邮件吧。

由于公司的自带邮箱是 Office 365,那么编写一个可以发邮件的脚本就解决了。

#coding=utf-8

import smtplib
from email.mime.text import MIMEText
from email.header import Header
import datetime

mail_host = "smtp.xxx.xxx"  # 设置服务器
mail_user = "xxxx"  # 用户名
mail_pass = "xxxx"  # 口令

sender = 'xxxx'
receivers = ['xxxx']  # 接收邮件

content = "请注意:"+str(datetime.datetime.now().strftime("%Y-%m-%d
%H:%M:%S"))+'Jenkins和Slave连接断开,请及时处理'

message = MIMEText(content, 'plain', 'utf-8')
message['From'] = Header("注意Jenkins Master Slave连接出错", 'utf-8')
message['To'] = Header("持续集成处理", 'utf-8')

subject = "预警!!!!!!!!!!"
message['Subject'] = Header(subject, 'utf-8')

try:
    smtpObj = smtplib.SMTP(mail_host, 587)
    smtpObj.ehlo()
    smtpObj.starttls()
    smtpObj.ehlo
    smtpObj.login(mail_user, mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print "邮件发送成功"
except smtplib.SMTPException:
    print "Error: 无法发送邮件"

同样的,只要在轮询执行*/5 * * * * sh /Users/xx/Documents/check.sh中,加入调用发送邮件的脚本,就解决了。

写在最后

维护持续集成的稳定,还是一件很繁琐的事情,需要更多的耐心。

虽然这件事很简单,我不清楚是否有更好的方案,也希望知道的可以给我指一条路,谢谢了。


↙↙↙阅读原文可查看相关链接,并与作者交流