Saltstack中ZeroMQ那点事

基本简介

前置阅读

环境说明

Salt中的ZeroMQ patterns

Salt Master

Salt Minion

Salt

总结

基本简介

Salt 底层网络架构采用 ZeroMQ 进行实现(2014.1及之前版本, 从2014.7起, Salt新增 RAET ), 官方手册 有简短描述. 那么今天就一窥在Salt内部使用了哪些 ZeroMQ pattern? 各个组件间又是如何协作的哪?

前置阅读

0MQ - The Guide: Sockets and Patterns

环境说明

CentOS6.4

Salt 2014.1.10 ,默认配置

Salt中的ZeroMQ patterns

Salt Master

Salt Master为Salt中心管控节点. 为Salt环境提供命令下发, 文件, 结果收集等服务.

在Master启动时, 首先启动名为 ReqServer , ReqServer在初始化 时, 立即创建如下ZeroMQ patterns:

clients:

ZeroMQ pattern: zmq.ROUTER

listen地址: tcp://0.0.0.0:4506

listen方式: bind

作用: Salt Master Ret接口, 支持认证(auth), 文件服务, 结果收集等功能

workers:

ZeroMQ pattern: zmq.DEALER

listen地址: ipc:///var/run/salt/master/workers.ipc

listen方式: bind

作用: Salt Master任务处理进程接口

同时clients与workers, 建立了一个 zeromq.device :

zmq.device(zmq.QUEUE, self.clients, self.workers)

通过zmq.device, 实现了clients接收到请求后, 转发到workers进程接口上进行处理

接下来, Master会启动 Publisher , 立即创建了如下ZeroMQ patterns:

pub:

ZeroMQ pattern: zmq.PUB

listen地址: tcp://0.0.0.0:4505

listen方式: bind

作用: Salt Master pub接口, 提供远程执行命令发送功能

pull:

ZeroMQ pattern: zmq.PULL

listen地址: ipc:///var/run/salt/master/publish_pull.ipc

listen方式: bind

作用: Salt Master远程执行命令pull接口

pull接口在接收到数据后, 会将数据从pub接口上进行发送:

package = pull_sock.recv()

pub_sock.send(package)

接下来, Master启动 EventPublisher, 以实现Event BUS, 创建了如下ZeroMQ patterns:

epub:

ZeroMQ pattern: zmq.PUB

listen地址: ipc:///var/run/salt/master/master_event_pub.ipc

listen方式: bind

作用: Salt Master event pub接口, 以方便其他或第三方应用订阅event bus上的event

epull:

ZeroMQ pattern: zmq.PULL

listen地址: ipc:///var/run/salt/master/master_event_pull.ipc

listen方式: bind

作用: Salt Master event pull接口

同时epull接口在收到包时, 会将数据在pub接口上进行发送:

package = self.epull_sock.recv()

self.epub_sock.send(package)

在启动EventPublisher之后, Salt Master会继续启动Halite, Reactor系统, 该部分暂不描述. 随后, Salt会启动多个Work进程(默认是5, 在规模较大的环境中, 建议增加配置文件中的 worker_threads 数目来增加该类进程)来进行任务处理, 每个Worker进程会创建如下ZeroMQ patterns:

socket

ZeroMQ pattern: zmq.REP

listen地址: ipc:///var/run/salt/master/workers.ipc

listen方式: connect

作用: Salt Master任务处理进程, 处理验证Minion, 获取Master配置, Mine, pillar, fileserver文件获取, minion event fire到master的event接口, 收集minions的返回结果等任务

Salt Minion

Salt Minion为Salt环境操作节点, 远程命令从Master发送过来后, 会在该主机上进行执行并将结果返回给Master.

Salt Minion 在启动时从配置文件中获取Master的地址, 如果为域名, 则进行解析. 解析完毕后, 会连接Master的Ret接口进行key认证. 认证通过, 会获取到master的 publish_port , 这就是为什么在Minion的配置文件中只需要指定Minion的 ret_port (对应minion配置文件中的master_port) 即可.

在获取到master的publish_port(默认为4505)之后, 会建立minion本地的Event接口:

epub:

ZeroMQ pattern: zmq.PUB

listen地址: ipc:///var/run/salt/minion/minion_event_{id_hash}_pub.ipc

listen方式: bind

作用: Salt Minion event pub接口, 以便其他或第三方应用通过该event bus获取event信息

epull:

ZeroMQ pattern: zmq.PULL

listen地址: ipc:///var/run/salt/minion/minion_event_{id_hash}_pull.ipc

listen方式: bind

作用: Salt Minion event pull接口

epull接口在接收到数据后, 会检查是否需要处理, 如果需要处理, 则进行执行. 随后将该数据包传送到epub接口:

# Check the event system

if socks.get(self.epull_sock) == zmq.POLLIN:

package = self.epull_sock.recv(zmq.NOBLOCK)

log.debug("Handling event %r", package)

try:

if package.startswith(‘module_refresh‘):

self.module_refresh()

elif package.startswith(‘pillar_refresh‘):

self.pillar_refresh()

elif package.startswith(‘grains_refresh‘):

if self.grains_cache != self.opts[‘grains‘]:

self.pillar_refresh()

self.grains_cache = self.opts[‘grains‘]

elif package.startswith(‘fire_master‘):

tag, data = salt.utils.event.MinionEvent.unpack(package)

log.debug("Forwarding master event tag={tag}".format(tag=data[‘tag‘]))

self._fire_master(data[‘data‘], data[‘tag‘], data[‘events‘], data[‘pretag‘])

self.epub_sock.send(package)

except Exception:

log.debug("Exception while handling events", exc_info=True)

在event接口建立完毕后, 会建立如下ZeroMQ pattern:

socket:

ZeroMQ pattern: zmq.SUB

listen地址: "tcp:/":tcp://{master_ip}:4505

listen方式: connect

作用: 订阅来自Master pub接口的任务

由于远程执行命令的发送, 是通过ZeroMQ PUB/SUB pattern进行建立的, 即当master下发操作指令时, 所有的minion均可以接收到, 然后minion会检查本机是否target match, 如果match, 则进行执行.执行完毕后, 会通过 SREQ 发送到Master的Ret接口, 期间会创建如下ZeroMQ pattern:

socket:

ZeroMQ pattern: zmq.REQ

listen地址: "tcp:/":tcp://{master_ip}:4506

listen方式: connect

作用: 将执行结果发送给Master

更多关于Minion如何来执行任务, 请访问: http://devopstarter.info/yuan-ma-jie-du-saltstackyun-xing-ji-zhi-zhi-job-runtime/

Salt

Salt Master与Salt Minion建立了对应的ZeroMQ pattern, 那么当一个远程执行指令下发下去, 其数据流向是怎么个流程哪? 以执行test.ping为例:

1. 在master端bash下, 执行:

salt ‘*‘ test.ping

其对应的 python执行 是:

client = salt.cli.SaltCMD()

client.run()

在内部, 又是调用:

local = salt.client.LocalClient()

cmd_fun = local.cmd_cli()

for full_ret in cmd_func(kwargs):

ret, out = self._format_ret(full_ret)

self._output_ret(ret, out)

2. 在 LocalClient 对象初始化时, 会创建用于对发送的数据进行序列化的 Serial 对象, 及 MasterEvent 对象. MasterEvent对象会创建如下ZeroMQ pattern:

sub:

ZeroMQ pattern: zmq.SUB

listen地址: ipc:///var/run/salt/master/master_event_pub.ipc

listen方式: connect

作用: 用于订阅来自于Master event pub接口的数据

3. cmd_cli 在执行时, 会首先通过 run_job 将操作指令封装成如下内容:</p>

{‘tgt_type‘: ‘glob‘, ‘jid‘: ‘‘, ‘key‘: ‘LCkViTMgqKBqb5ooG8kznznztLYPsWR1xdTYnAz9udkU9/Lla32yDvUmVKLPaUNSMtbWdBoQPIs=‘, ‘tgt‘: ‘*‘, ‘arg‘: [], ‘fun‘: ‘test.ping‘, ‘kwargs‘: {‘show_timeout‘: False}, ‘cmd‘: ‘publish‘, ‘ret‘: ‘‘, ‘user‘: ‘root‘}

将发送到本地master的Ret接口, 期间会创建如下ZeroMQ pattern:

socket:

ZeroMQ pattern: zmq.REQ

listen地址: tcp://127.0.0.1:4506

listen方式: connect

作用: 将封装后的指令发送到Master Ret接口

4. Master Ret接口接收到3中发送的数据后, 会通过chminions.check_minions获取本次需要哪些minions执行, 并产生jid, 然后在master event接口上进行fire_event操作, 之后对数据使用master私钥(master.pem)进行签名, 然后创建如下ZeroMQ pattern:

pub_socket:

ZeroMQ pattern: zmq.PUSH

listen地址: ipc:///var/run/salt/master/publish_pull.ipc

listen方式: connect

作用: 将指令传送到Master Pull接口

Master Pull接口接收到数据后, 会迅速的在Master Pub接口上发送将之前收到的数据

同时将jid及minions封装后的结果返回给3, 3中cmd_cli获取到数据后, 调用 get_cli_event_returns ,监听Master端的Event bus, 过滤出本次任务jid所对应的event, 用来获取执行结果

5. 此时Minion通过PUB/SUB, 即可收到来自于Master Pub接口的消息. Minion接收到消息后, 会首先通过本地的master pub_key(minion_master.pub)进行解密, 已确保消息来自于Master. 解密完成后, 本地进行target匹配, 如果匹配上, 表示需要执行, 派生出一个新的进程进行执行. 反之则直接忽略.

6. Minion执行完毕后, 会通过 _return_pub 将封装后的结果通过AES加密发送到Master的Ret接口.

7. Master Ret接收到6中发送的数据后, 会进行AES解密, 然后通过 _return, 首先将解密后的数据在本地event接口上进行fire_event, 并将结果存储在master本地.

8. 由于7中进行fire_event, 此时4中的get_cli_event_returns即可捕捉到, 由于采用迭代器, 每个收到的结果均能马上显示出来, 一旦捕获到的minions的结果大于等于之前获得的minions数目, 即表示所有minions均已返回结果, 退出.

总结

Salt利用ZeroMQ灵活高效的patterns, 使Salt网络拓扑变得非常灵活高效. 利用PUB/SUB, 实现了高效的远程执行指令下发机制; 利用ROUTER/REQ, 实现认证及异步的远程执行结果返回; 利用DEALER/REP, 实现多进程任务处理机制; 利用PULL/PUB, 实现Event BUS, 使其他或第三方应用可以快速的使用PUB/SUB接收到Event BUS上的消息.

I love Salt, I love ZeroMQ!

Powered by Redmine ? 2006-2014 Jean-Philippe Lang

时间: 2024-10-09 15:58:03

Saltstack中ZeroMQ那点事的相关文章

Saltstack中Pillar那点事

Salt中Pillar那点事 基本简介 在 SaltStack 中, Pillar作为定义minion全局数据的接口. 默认存储在master端, Minion启动时会连接master获取最新的pillar数据. Pillar使用类似于State Tree的结构, 默认使用 YAML 作为其描述格式, 在Minion内部最终转换成 Python字典 . 那么在Salt内部, Pillar是如何工作的? 在哪些情况下,需要先执行刷新Pillar操作? 而哪些又不需要? 本文基于 Salt 2014

C语言中关于内存那些事

因为要学IOS开发,为了更好的学习OC所以又从头开始学习C语言,这篇文章主要记录关于C语言中内存布局.以及不同的内存区域的特点. C语言的程序内存布局,从高到低依次为:栈区.堆区.未初始化数据区.初始化数据区.代码区. 一.栈区 由编译器自动管理,无需程序员手工控制.存放函数的参数值.局部变量的值等.栈区内容从高地址到低地址分配,从低地址到高地址存取. int a = 0; int b = 0; int array[5] = {1, 2, 3, 4, 5}; printf("&a....

那一夜,我被梦中笑醒的事之(数据库)

那一夜,我被梦中笑醒的事之数据库 我的法则弱肉强食 适者生存 数据库 一个呆呆的,不会动也不会叫更不能吃的,但是却是一个必不可少的东东.是吧. 不用说是我知道了,下面我们一起看看吧 数据库 为何要使用数据库? 数据库的必要性: 1.  可以结构化储存大量的数据信息,方便用户进行有效的检索和访问. 可以有效的保持数据信息的一致性,完整性,降低数据冗余. 可以满足应用的共享和安全方面的要求. 数据库技术能够方便智能化地分析,产生新的有用的信息. 行:(记录) 列:(字段) 2.数据冗余:数据的重复性

JavaScript中面向对象那点事

鉴于自己在JavaScript这方面比较薄弱,所以就找了一本书恶补了一下(被称为犀利书的JavaScript权威指南).书的内容虽然多了点,但这也充分说明了js中的东西还是挺多的.虽然我们的定位不是前端,但最好还是了解一下js这个发展了将近20年但依然很火的技术. 两年前,写过一篇关于JavaScript闭包的博客,所以对闭包这个词印象很深,在看这书的时候,又看到了闭包,那么这次再看闭包,会有什么不同的理解呢? 大家都知道,在JavaScript中是没有类的概念的,更没有私有.公有的成员变量这样

有时候,人生中最艰难的事,反而锻造了最坚强的你。

讨厌自己明明不甘平凡,却又不好好努力. 看到一段话:有些姑娘,读书也好,工作也好,整容也好,目标只有一个,那就是为了嫁个好男人.而另一些姑娘,做的所有事情都只是为了让自己变的更强.也许前者在刚开始会活的很好,但人生很长,慢慢你就会发现,依靠别人,始终是场赌博.而让自己变更好,那才是一辈子的事情. 有时候,人生中最艰难的事,反而锻造了最坚强的你.

(转载)JavaScript中面向对象那点事

鉴于自己在JavaScript这方面比较薄弱,所以就找了一本书恶补了一下(被称为犀利书的JavaScript权威指南).书的内容虽然多了点,但这也充分说明了js中的东西还是挺多的.虽然我们的定位不是前端,但最好还是了解一下js这个发展了将近20年但依然很火的技术. 两年前,写过一篇关于JavaScript闭包的博客,所以对闭包这个词印象很深,在看这书的时候,又看到了闭包,那么这次再看闭包,会有什么不同的理解呢? 大家都知道,在JavaScript中是没有类的概念的,更没有私有.公有的成员变量这样

saltstack中stae用法

#salt  '*'  state.sls   httpd 这个命令会先在目录/srv/salt下找httpd.sls(yml语法格式编写的)文件,若:有就安装文件内容执行,若没有的话就继续找/srv/salt/httpd目录下init.sls,找到了安装文件内容执行,没有的话就报错: #salt  '*'  state.sls   httpd.install 按照文件/srv/salt/httpd/install.sls文件内容执行,没有的话就报错: [[email protected]_2 

如何命名:编程中最难的事1

本文译者:isaced       审校:李庆 原文链接:slideshare 译文链接:JF杰微刊出品 本文由杰微刊编辑人员在译文基础上编辑而成.如有问题,欢迎交流. 如何命名,其实是编程中最难的事. 乔治·奥威尔的命名规范 如何命名? 简言之,根据语意来选择词汇,别无它法……然而,有时我们会不知用什么词汇更合适. 当你想到某个抽象的东西,你更倾向于最先想到的词语,除非你故意不这样,这些词也会抢着出现,直到模糊或改变你的想法. 当你想到一个具体的对象,你觉得词穷,然后你想描述的已经看到了,然后

SaltStack与ZeroMQ(二)

SaltStack与ZeroMQ SaltStack底层是基于ZeroMQ进行高效的网络通信. ZeroMQ简介     ?MQ (也拼写作ZeroMQ,0MQ或ZMQ)是一个为可伸缩的分布式或并发应用程序设计的高性能异步消息库.它提供一个消息队列, 但是与面向消息的中间件不同,ZeroMQ的运行不需要专门的消息代理(message broker).该库设计成常见的套接字风格的API.能够提供进程内(inproc).进程间(IPC).网络(TCP)和广播方式的消息信道, 并支持扇出(fan-ou