持续集成 检查 Jenkins Master 和 Slave 的连接状态

不二家的小球迷 · 2017年07月10日 · 最后由 舒克 回复于 2018年08月21日 · 51 次阅读

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

背景

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

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

确认有无判断 OFFLINE 出现的 API

  • 确认 Slave 是否 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 的时候,就可以预警了。

解决方案

  • 编写一个 Curl 脚本,然后在 Mac Slave 内通过 Crontab 制定一个每五分钟执行一次的轮询机制,如果出现 Offline 为 True 则进行预警。编写 check.sh:
#!/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中,加入调用发送邮件的脚本,就解决了。

写在最后

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

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

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 4 条回复 时间 点赞

可以试试 jenkinsapi,里面有 2 个方法,应该可以做到报警后恢复
jenkins.get_node('').is_online()
jenkins.get_node('').set_online()

kanchi240 回复

是在 Jenkins 里面用 groovy 写然后直接调用吗?

题主的构建是放在哪里去做呢?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册