使用SaltStack Returner将Salt作业信息接入Elasticsearch的实践(踩坑)

背景

熟悉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提供作业结果数据的方法

  1. 在salt minion上安装必要的依赖工具包
yum install python27-pip -y
pip2.7 install elasticsearch
  • 我们这里的示例均是在CentOS6/CentOS7系统上配置和测试的
  1. 在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
  1. 重启salt minion服务使配置生效
service salt-minion restart
  1. 验证测试
    我们使用的测试机是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 。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于篇幅限制,我无法在这里完整地展示一个完整的资产信息管理系统的Java代码。但是,我可以给你提供一些基本的代码框架和实现思路,以供参考。 1. 系统管理: 实现系统管理需要定义一个User类和一个Role类,分别表示系统用户和用户角色。同时需要定义一个SystemManager类,实现系统管理的各种功能。例如: ``` public class User { private String username; private String password; private Role role; // getter and setter methods } public class Role { private String roleName; private List<String> permissions; // getter and setter methods } public class SystemManager { private List<User> users; private List<Role> roles; public void addUser(User user) { // add user to the system } public void deleteUser(User user) { // delete user from the system } public void addRole(Role role) { // add role to the system } public void deleteRole(Role role) { // delete role from the system } // other methods } ``` 2. 资产信息管理: 实现资产信息管理需要定义一个Asset类,表示资产信息。同时需要定义一个AssetManager类,实现资产信息管理的各种功能。例如: ``` public class Asset { private String assetId; private String assetName; private String assetType; private Date purchaseDate; private String purchaser; private int status; // getter and setter methods } public class AssetManager { private List<Asset> assets; public void addAsset(Asset asset) { // add asset to the system } public void deleteAsset(Asset asset) { // delete asset from the system } public Asset searchAssetById(String id) { // search asset by id } public List<Asset> searchAssetByName(String name) { // search asset by name } public void updateAsset(Asset asset) { // update asset information } // other methods } ``` 3. 人员信息管理: 实现人员信息管理需要定义一个Person类,表示人员信息。同时需要定义一个PersonManager类,实现人员信息管理的各种功能。例如: ``` public class Person { private String personId; private String name; private String department; private String position; // getter and setter methods } public class PersonManager { private List<Person> persons; public void addPerson(Person person) { // add person to the system } public void deletePerson(Person person) { // delete person from the system } public Person searchPersonById(String id) { // search person by id } public List<Person> searchPersonByName(String name) { // search person by name } public void updatePerson(Person person) { // update person information } // other methods } ``` 4. 资产领用、资产归还、资产报废: 实现资产领用、资产归还、资产报废需要在Asset类中定义一些额外的属性和方法,同时需要在AssetManager类中添加相应的功能方法。例如: ``` public class Asset { private String assetId; private String assetName; private String assetType; private Date purchaseDate; private String purchaser; private int status; private String borrower; private Date borrowDate; private String returner; private Date returnDate; private String scrapReason; // getter and setter methods public void borrowAsset(Person person) { // set borrower and borrow date } public void returnAsset() { // set returner and return date } public void scrapAsset(String reason) { // set scrap reason and change status to "scrap" } } public class AssetManager { private List<Asset> assets; public void borrowAsset(String assetId, Person person) { // borrow asset and update asset information } public void returnAsset(String assetId) { // return asset and update asset information } public void scrapAsset(String assetId, String reason) { // scrap asset and update asset information } // other methods } ``` 以上是一个简单的基于Java的资产信息管理系统的设计方案和部分代码示例。具体实现方式还需要根据需求和实际情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值