常用Jenkins的人都知道任务可以限定到节点上运行,通常在通用配置栏目里,有个限制项目运行节点的勾选框。
在这个配置项下点击,可以进入到对应的label界面,这个label是和node上的label关联的,除开任务不配置上面的限制节点,且有可以跑全部任务的节点的情况,只有任务配置的label在node或者cloud上有机器才可正常运行。
当配置的节点和任务变多的时候,我们不可能进到任务里面去一个一个点击,如果有一种能够帮助我们对整个Jenkins进行分析的办法,那一定是众望所归的。
基本原理
依然使用的是python的jenkinsapi库对job们进行排查梳理。
第一步先将任务的限制项目运行节点配置提取出来。
第二步对这些节点进行查看label关联,看是否有对应的node和cloud。
需要注意的是有些节点是不限制运行的,比如在节点配置中设置了尽可能使用的节点。
而有些job也不限制自己在哪里运行,所以分析时要将其纳入进去。
代码实现
导入要用到的库并创建Jenkins实例。
from collections import defaultdict
from jenkinsapi.jenkins import Jenkins
from xml.dom.minidom import parseString
jks = Jenkins('http://127.0.0.1:8080/', username='admin', password='11597987c28c751f1750b4b4b0d4694551', use_crumb=True)
遍历工程配置,提取节点信息,生成一个字典。这里加上了对没有assignedNode配置的处理,响应前面的对不限制机器任务的处理。
label_count_dict = defaultdict(int)
job_names = jks.keys()
for job_name in job_names:
job = jks.get_job(job_name)
dt = parseString(job.get_config())
collection = dt.documentElement
try:
assign_node = collection.getElementsByTagName("assignedNode")[0]
label = assign_node.firstChild.data
except IndexError as e:
print(e)
label = built-in
label_count_dict[label] += 1
此时的字典在我机器上打印是这样的
提取节点的配置信息,生成字典。这里使用的是pythonapi的方式来读取节点数据,因为有些版本已经开始不支持这个Jenkinsapi来读取节点信息,所以可以用通用的api方式。这个方式无法支持获取具体的配置信息,所以还看不了节点配置的是尽可能使用还是限定标签。这里提取了节点的执行器数量,对节点而言,执行器的数量代表了能够同时运行的任务数。
node_executor_num_dict = defaultdict(int)
nodes_url = jks.get_nodes_url()
data = jks.get_data(jks.python_api_url(nodes_url))
print(data)
computers = data.get('computer')
for computer in computers:
assigned_labels = computer.get('assignedLabels')
label_names = [i.get('name') for i in assigned_labels]
executor_num = computer.get('numExecutors')
for label_name in label_names:
node_executor_num_dict[label_name] += executor_num
此时我这边机器上的打印是这样的。
云节点还不能被api观察,所以暂时不考虑。
对比两张图片,可以很清晰的看到任务对节点的需求情况和节点执行器的数量。规模较大时可以通过代码来对比。这个数据能够为节点的增减提供建议。
缺陷与改进
上面的方式首先是云节点无法监控,对于有些label就可能是没有node的。其次是任务的label可能是个表达式,需要配合运算才能得出节点的数量。