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

不二家的小球迷 · July 10, 2017 · Last by 舒克 replied at August 21, 2018 · 3001 hits

引言:很久没有认真的写一篇分享了,今天记录一下处理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"
))+'JenkinsSlave连接断开,请及时处理'

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写然后直接调用吗?

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

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up