fightclub

saltstack中的设计模式(三)

在上一篇中,我们还留下了一个问题。就是在响应器中,我们使用了一个_syndic_handle的特殊参数。
这个参数,引出了今天我们要讨论的话题

如何在syndic上进行事件处理

在于大规模的saltstack的部署环境,往往使用master,syndic的架构。
因为设计的原因,所有syndi接收到c的事件都会由底向上传播至上层master。
导致的结果是在事件处理中,同一个事件会被重复处理多次。
为了防止这个问题,我们可以采取以下几种方法

  • 禁用syndic的事件处理配置,由master统一处理
  • 禁用master的事件处理配置,由syndic统一进程处理
  • 在事件发送的时候添加一个标记, 并在处理逻辑中解析这个标记,并做应用层的路由

第一种方案最为简单,一旦master和syndic之间出现通讯故障,会导致syndic上的事件处理失效

而第二种方案的,在有些情况下,比如有很多minion直连master的场景下,就没办法使用

综上,还是最后一种方案适用性更广一点。

思路就是这样,根据实际的架构情况可以采取不同的做法。对于我现在的场景,实现方式如下:

  1. 从syndic下面触发的事件需要在发送事件的时候添加标记,例如_syndic_handle。对于整个配置文件是从master同步过去的syndic来讲,需要客户端动态的获得信息,知道自己是否是连接到syndic上面。salt-minion可以解析自己的配置文件,获取当前的master地址。我们将内置的salt架构信息通过pillar的方式下发给客户端,客户端就可以根据这些信息决定是否要设置这个标记
  2. 在reactor对应的入口文件进行判别,根据获取data中的标记,来决定是进行处理,还是直接忽略整个处理流

具体步骤:

添加pillar文件,告诉所有minion master地址

/srv/pillar/salt_info.sls

1
2
salt_info:
core_master: 10.0.0.1

在sls中通过对比自己的master和真实master的地址,决定是否添加syndic处理标记

/srv/salt/somejob.sls

1
2
3
4
5
6
7
somejob/someevent:
event.send:
- data:
{% if salt["config.get"]("master") != salt["pillar.get"]("salt_info:core_master") %}
_syndic_handle: True
{% endif %}
- otherdata: {{ otherdata }}

reactor配置

/etc/salt/master.d/reactor.conf

1
2
3
reactor:
- somejob/someevent:
- /srv/reactors/somejob/someevent.sls

为salt-master和salt-syndic上面打上grains标签

在master上,执行:

1
salt-call grains.append roles salt-master

在sydic上执行

1
salt-call grains.append roles salt-syndic

在打好标记以后,需要确认grains最终被写到了/etc/salt/grains下面,而不是在minion的配置文件里,否则是无效的

编写reactor文件

/srv/reactors/somejob/someevent.sls

1
2
3
4
5
6
{% if not "_syndic_handle" in data["data"] or "salt-syndic" in salt["grains.get"]("roles") %}
IPARENAME:
runner.somejob:
- args:
- otherdata: {{ data["data"]["other_info"] }}
{% endif %}