背景
熟悉SaltStack的都知道,master/minions间所有的交互操作都是通过一个事件总线完成的。从master发出一个管理命令的同时,就生成了一个Job,当minions执行完作业并返回结果数据给master时,则又是以另外一个Job的形式返回的。
因此,我们在排查一些基于salt实现的自动化运维服务故障时,经常要做的一个操作就是登录到master系统,执行salt-run state.event test=True
命令,然后观察当执行特定管理或配置任务时,salt底层的事件总线上面究竟是发生了什么,在C/S交互过程中,哪个步骤中有什么错误信息等。
由于以上命令查看的是事件总线上所有的事件交互信息,所以对一个业务繁忙的系统,可能不太容易观察,当你准备进行问题调试时,其它的各种任务产生的事件信息有可能会像刷屏一般地滚过。
把salt jobs信息接入到elasticsearch进行管理还有以下的考虑:
- salt job缓存数据在使用默认的Default Salt Cache时,只会保存24小时内的数据。由于是通过在master设备本地以文件形式存储的,从很多方面考虑,延长缓存保留时间都会遇到查询性能、空间存储的挑战。
- 查询salt作业信息时的性能和便利性,通过Kibana查询一个elasticsearch的分布式集群,在使用体验上要强很多。
- 故障排查要求,有时会遇到一些意料之外的情况,部署的管理或配置任务在运行中出现异常,或是部分主机节点存在异常。这些故障信息需要可以容易被查看、监控和报警出来。
- 审计要求,是否存在系统管理人员违规使用Salt执行高风险的批量管理命令的行为,是否存在滥用Salt或是错误使用Salt功能的行为。
Salt 提供了十几种开箱即用的Returner模块,像mysql, redis, mongodb这些都有很成熟的接入实践了。此外,参照官网的说明,自己开发一个Returner模块,也很容易,只需要自定义一个Python函数即可。大家有兴趣的可以看下官网的这个链接:https://docs.saltstack.com/en/latest/ref/returners/index.html
将minions的返回结果信息将入到elasticsearch中,很多资料都语焉不详,比较要命的是这篇 elasticsearch_return 官网上介绍elasticsearch return模块的资料已经过时了,此处有坑。
接下来我们,先介绍正确的接入配置方法,再来谈谈哪些官网上介绍的功能或方法是不能使用的。
配置minions向elasticsearch提供作业结果数据的方法
- 在salt minion上安装必要的依赖工具包
yum install python27-pip -y
pip2.7 install elasticsearch
- 我们这里的示例均是在CentOS6/CentOS7系统上配置和测试的
- 在minion的配置文件中增加elasticsearch return的配置信息
我们在这里只给出最简单的一个示例,由于该return模块是基于SALT.MODULES.ELASTICSEARCH二次开发实现的,所以如果有更复杂的使用要求时,可以看一下salt elasticsearch模块的文档,例如使用https加密传输时的证书配置方法。
cat >> /etc/salt/minion << EOF
return: elasticsearch
elasticsearch:
hosts:
- "192.168.100.10:9200"
- "192.168.100.11:9200"
- "192.168.100.12:9200"
index_date: True
number_of_shards: 5
number_of_replicas: 1
debug_returner_payload: True
states_count: True
states_order_output: True
states_single_index: True
functions_blacklist:
- test.ping
- saltutil.find_job
- saltutil.running
EOF
- number_of_shards,按需设定一个索引分片数量
- number_of_replicas,设定数据副本数量
- index_date,使用一个日期格式风格的索引名称 (e.g. -2016.11.29)
- functions_blacklist,设定哪些模块函数是不需要返回给elasticsearch的
- 其它可选参数及含义,请参照SALT.RETURNERS.ELASTICSEARCH_RETURN
- 重启salt minion服务使配置生效
service salt-minion restart
- 验证测试
我们使用的测试机是gqtest,接入到salt master,同时按前述步骤配置了minion侧的一个elasticsearch return,把作业结果数据向elasticsearch提交一份。
root@sleeper-VirtualBox:~# salt gqtest test.ping
gqtest:
True
root@sleeper-VirtualBox:~#
执行以下几个命令,再到kibana上观察下采集到了哪些salt jobs结果数据。
root@sleeper-VirtualBox:~# salt gqtest test.ping
gqtest:
True
root@sleeper-VirtualBox:~# salt gqtest cmd.run "ls /etc/salt"
gqtest:
cloud
cloud.conf.d
cloud.deploy.d
cloud.maps.d
cloud.profiles.d
cloud.providers.d
master
master.d
minion
minion.d
minion.rpmnew
minion_id
pki
proxy
proxy.d
proxy.rpmnew
roster
root@sleeper-VirtualBox:~# salt gqtest saltutil.running
gqtest:
root@sleeper-VirtualBox:~# salt-run jobs.active
打开浏览器,在kibana上创建一个salt-*的index pattern,然后查询已经采集到的数据。
- 从上图看到,除了最上面的一条是我们执行cmd模块管理命令产生的作业结果数据外,像其它的test.ping, saltutil.running等因为都在黑名单函数列表中,所以均未被提交给elasticsearch服务。
- 至于采集到的其他几条数据,从函数名和_index名称可看出,这是因为我们重启salt minion时,重载配置文件内容时执行的几个加载配置文件的命令所产生的。
以上就是将一个salt minion的作业结果数据接入到elasticsearch中所需要的全部配置工作了。
接下来,我们再谈谈在Salt Returnner功能中,目前存在哪些bug或功能不完善之处。针对这些存在问题的功能,需要二次开发补足功能缺陷才能正常使用。
Elasticsearch Returnner 使用在 Salt master-job-cache & ext-job-cache 功能时存在bug
master-job-cache 和 ext-job-cache 是Salt提供的一套可用于替换掉系统默认的Default Job Cache机制的功能插件,通过在master配置文件中进行配置和启用这两个功能。
注意:这里讲的是替换,而不是可以同时存在。而前面我们介绍的returner模块则是属于在Salt 原有机制之上额外增加的负载。这两个功能项,是要替换掉默认的Default Job Cache机制,意味着Salt master/minion将不必再自己缓存和管理作业处理结果数据了。
master-job-cache: elasticsearch
ext-job-cache: elasticsearch
以上两个选项,必须二选一。
- 在启用master-job-cache时,需要在master上安装elasticsearch-py依赖包,并将下面配置添加在master配置文件中。
- 在启用ext-job-cache时,需要在minion上安装elasticsearch-py依赖包,并将下面配置添加在minion配置文件中。
elasticsearch:
hosts:
- "192.168.100.10:9200"
- "192.168.100.11:9200"
- "192.168.100.12:9200"
index_date: True
number_of_shards: 5
number_of_replicas: 1
debug_returner_payload: True
states_count: True
states_order_output: True
states_single_index: True
functions_blacklist:
- test.ping
- saltutil.find_job
- saltutil.running
- 完成以上配置后,重启master/minion服务。
警告:以上两个功能在配置好以后,elasticsearch可以采集到salt jobs处理结果的数据。但是!因为elasticsearch returner插件对master-job-cache, ext-job-cache的功能支持不完善,此时在执行很多其他salt管理模块命令时,如cmd模块,在master日志、minion日志,甚至是执行管理命令的窗口中都会不断得打印报错信息。
下面不区分错误信息出现的位置,只是挑几处典型的报错看一下:
Exception occurred in runner jobs.active: Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/client/mixins.py", line 382, in _low
data['return'] = self.functions[fun](*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/runners/jobs.py", line 71, in active
data = mminion.returners['{0}.get_jid'.format(returner)](jid)
File "/usr/lib/python2.7/site-packages/salt/loader.py", line 1114, in __getitem__
func = super(LazyLoader, self).__getitem__(item)
File "/usr/lib/python2.7/site-packages/salt/utils/lazy.py", line 101, in __getitem__
raise KeyError(key)
KeyError: 'elasticsearch.get_jid'
[WARNING ][22475] Returner unavailable: expected string or buffer
CommandExecutionError: Cannot create document in index salt-master-job-cache, server returned code 400 with message mapper_parsing_exception
这些报错让人百思不得其解。
最后不得已翻出来github上的elasticsearch returnner源码找线索,发现错误信息提到的get_jid
函数在源码中并不存在!
反复阅读关于master-job-cache, ext-job-cache的技术资料后,发现官网的 Returners页面中,明确指出了,要使用master-job-cache
功能,必须在你的插件中实现prep_jid,save_load,get_load
三个函数,函数功能大家自行看资料中的介绍:master-job-cache-support
而要使用ext-job-cache
功能,必须在returner插件中再实现get_jid,get_fun, get _jids, get_minions
这四个函数,详见:external-job-cache-support
而在目前的elasticsearch returner插件中只实现了以上7个函数中的master-job-cache
要求的3个,即便这样,在配置和使用master-job-cache: elasticsearch
时会报错Returner unavailable: expected string or buffer
。至于ext-job-cache: elasticsearch
功能,就完全没有可行性了。
结论:Salt elasticsearch returner 可以作为一个普通returner模块使用,但不能使用像master-job-cache, ext-job-cache这些高级功能。
在分析以上问题的过程中,我也浏览了下
mysql.py
,redis_return.py
等其它Salt returner模块的源码,发现它们对master-job-cache, ext-job-cache这两个高级管理功能的支持就很完善了,源码详见:https://github.com/saltstack/salt/tree/develop/salt/returners 。
一点思考:
- 什么样的场景下适合使用master-job-cache, ext-job-cache这两个高级功能呢。
- 这两个管理功能是对默认的Default Job Cache机制进行完整地替换,这样做可以获得哪些好处。
- 当前的elasticsearch returner的源码中还缺少4个用于支持ext-job-cache功能的子函数,如果让你补足短板,可以怎么实现。
注意:当使用master-job-cache, ext-job-cache替换了默认的Default Job Cache时,在master本地就不保存作业缓存数据了,所有作业数据信息的查询和管理都应该是通过salt returner模块读写第三方存储服务来实现的,比如是mysql, redis或elasticsearch 。