背景
360私有云平臺(tái)(HULK平臺(tái))管理著360公司90%以上的業(yè)務(wù)線,面對(duì)如此眾多的服務(wù)器,如何進(jìn)行管理?當(dāng)然需要一套完善的工具來(lái)自動(dòng)化。HULK 平臺(tái)的命令系統(tǒng)可以對(duì)批量機(jī)器執(zhí)行腳本,命令系統(tǒng)的底層是基于 SaltStack 開(kāi)發(fā)。
當(dāng)然最大的問(wèn)題在于機(jī)器部署的機(jī)房多,機(jī)器數(shù)量多,部署 SaltStack 的 Master 就會(huì)遇到問(wèn)題,我們使用的是多級(jí)多機(jī)房 Master 的架構(gòu)。
多級(jí) Master 就要用到 Syndic。Syndic 消息傳輸比較依賴(lài)網(wǎng)絡(luò),但是公司內(nèi)部多機(jī)房間網(wǎng)絡(luò)比較復(fù)雜,Syndic 丟失消息的機(jī)率也相對(duì)比較高,下面就介紹一下使用 Syndic 的一些“坑”和改善丟消息的辦法。
SaltStack結(jié)構(gòu)
大概介紹下 Salt 結(jié)構(gòu),方便入門(mén)同學(xué)后面閱讀。Master 節(jié)點(diǎn)負(fù)責(zé)發(fā)布命令,管理下面這些機(jī)器,被管理機(jī)器節(jié)點(diǎn)部署 Minion 來(lái)監(jiān)聽(tīng)指令
Salt Syndic 介紹
當(dāng) Minions 的數(shù)量超過(guò)一定規(guī)模,Master 的性能就會(huì)成為瓶頸,這時(shí)會(huì)考慮部署多個(gè)節(jié)點(diǎn)的 Masters 來(lái)解決性能問(wèn)題,但是隨之而來(lái)就是使用性的降低,執(zhí)行命令需要到相應(yīng)的 Master 節(jié)點(diǎn)。在 SaltStack 0.9.0的版本中加入了 Syndic,Syndic 架構(gòu)的出現(xiàn)正好解決了這個(gè)問(wèn)題,Syndic 是一個(gè)特殊的 Minion,核心代碼就在 minion.py 中,Syndic 和低級(jí)別的 Master 運(yùn)行在同一臺(tái)主機(jī),Syndic 連接的 Master 是一個(gè)高級(jí)別 Master。
優(yōu)點(diǎn)
通過(guò) Syndic,可以建立多層的架構(gòu),所有的命令都可以由高級(jí)別的 Master執(zhí)行,這個(gè) Master 我們成為 Master Of Masters,架構(gòu)更為靈活
由于 Syndic 只是訂閱了 Master Of Masters 的消息,其他如文件服務(wù)等需要在 Syndic 節(jié)點(diǎn)配置,大大降低了 Master Of Masters 的壓力
缺點(diǎn)
Syndic 上 file_roots 和 pillar_roots 的配置要和 Master Of Masters 上的保持一致
Master Of Masters 只和 Syndic 通信,低級(jí)別的 Master 管理所屬的 Minions 認(rèn)證,致使 Master Of Masters 不知道下面有多少臺(tái) Minions;在 Master Of Masters 上執(zhí)行命令,在下發(fā)到 Syndic 過(guò)程中,如果網(wǎng)絡(luò)出現(xiàn)抖動(dòng),導(dǎo)致沒(méi)有收到消息或者延遲收到,Master Of Masters 并無(wú)感知,最終會(huì)導(dǎo)致整個(gè)任務(wù)的返回結(jié)果不完整
架構(gòu)圖
問(wèn)題
Syndic 在網(wǎng)絡(luò)不可靠的情況下,致使消息傳遞可靠性也相對(duì)降低,如果 Syndic 沒(méi)有收到消息,那么下面所屬的 Minions 也就不會(huì)收到這個(gè)任務(wù)。官方的建議是增加 syndic_wait 參數(shù),但是這也只是能緩解一部分情況,在實(shí)際環(huán)境中效果并不明顯。
思考
通過(guò)上面的介紹, Syndic 其實(shí)也是一個(gè) Minion,那是否可以用別的方案代替Syndic?這里首先要解決的問(wèn)題 ZeroMQ,Redis 也支持 Pub/Sub 模式,并且可以用主從架構(gòu)多機(jī)房部署,Redis 的 Pub/Sub 模式性能還是不錯(cuò)的。
測(cè)試
首先對(duì) ZeroMQ 和 Redis 的 Pub/Sub 模式進(jìn)行測(cè)試
結(jié)論
上訴測(cè)試是同機(jī)房測(cè)試,在網(wǎng)絡(luò)情況相同的情況下,ZeroMQ 要比 Redis 完成消息傳輸快一些,但是有丟失消息情況,Redis 的測(cè)試結(jié)果還可以,可以嘗試用 Redis 代替 ZeroMQ。 主要流程
一、在 Master Of Masters 上啟動(dòng)一個(gè) Subscribe 進(jìn)程,用來(lái)將數(shù)據(jù) Publish 到 Redis 特定的 Channel 中,詳細(xì)代碼如下:
self.opts['master_addr'] = salt.utils.dns_check(self.opts['master'])
//獲取master的ip地址
context = zmq.Context()
master_pub ='tcp://{0}:{1}'.format(self.opts[' master_addr '],self.opts['master_publish_port'])
ub_sock = context.socket(zmq.SUB)
sub_sock = set_tcp_keepalive(sub_sock,opts=self.opts)
sub_sock.connect(master_pub)
sub_sock.setsockopt(zmq.SUBSCRIBE,b'')
//啟動(dòng)Subscribe
try:
pool=ConnectionPool(host=self.opts['redis_host'],port=self.opts['redis_port'],db=self.opts['redis_db'],password=self.opts['redis_pass'])
# Send messages to puber PUB sock
while True:
message = sub_sock.recv_multipart()
//從ZeroMQ 訂閱消息
r = Redis(connection_pool=pool)
r.publish("salttest",message)
//將訂閱到的消息Publish到Redis中的Channel,Channel名為”salttest”
二、在二級(jí) Master 節(jié)點(diǎn)(原 Syndic 節(jié)點(diǎn))啟動(dòng) Publish 和 Return 處理消息,詳細(xì)代碼如下:
Publish:
self.opts['master_addr'] =salt.utils.dns_check(self.opts['master'])
context = zmq.Context()
pub_uri = 'tcp://{interface}:{publish_port}'.format(**self.opts)
pub_sock = context.socket(zmq.PUB)
pub_sock =set_tcp_keepalive(pub_sock,opts=self.opts)
pub_sock.bind(pub_uri)
try: conn_pool=client.ConnectionPool(host=self.opts['redis_host'],port=self.opts['redis_port'],db=self.opts['redis_db'],password=self.opts['redis_pass'])
sub = client.PubSub(conn_pool)
sub.subscribe('salttest')
//訂閱channel為”salttest”的消息
for msg in sub.listen():
if msg['type']=='message':
//判斷消息類(lèi)型
data=eval(msg['data'])
pub_sock.send_multipart(data)
//通過(guò)ZeroMQ將消息Publish下去
注:Return代碼比較簡(jiǎn)單,這里就省略了。
三、在 Master的配置文件中指定剛剛配置的端口(這里使用4515和4516是因?yàn)槭窃贛aster啟動(dòng))。
syndic_master:node1.example.com syndic_master_port:4516syndic_master_publish_port:4515
總結(jié)
做完之后,可以發(fā)現(xiàn)其實(shí)這個(gè)就是個(gè)用Redis Pub/Sub的SaltSyndic,這個(gè)模式用了一段時(shí)間,發(fā)現(xiàn)消息丟失的情況已經(jīng)大大減少。