最近在看minion的啟動的源代碼,一路曲折啊,經過一番努力,終于了解了流程。現在記錄下,友善以後查閱。
總體來說流程如下:
1、解析指令行參數和minion配置檔案,得到options和config字典
2、設定日志(salt.log.setup.setup_logfile_logger負責)
3、設定pidfile
4、根據master參數決定調用salt.minion.MultiMinion或者salt.minion.Minion初始化
5、調用tune_in方法
解析指令行參數和配置檔案調用的是salt.Minion,這個類極其複雜,使用了進階概念元類,多重繼承。我看的時候特别暈,隻是了解了大概。
對應檔案是salt/__init__.py,這個檔案中的Minion類是salt.utils.parsers.MinionOptionParser的子類。
下面代碼對應檔案是salt/utils/parsers.py。
class MinionOptionParser(MasterOptionParser):
__metaclass__ = OptionParserMeta # 元類
description = (
'The Salt minion, receives commands from a remote Salt master.'
)
# ConfigDirMixIn config filename attribute
_config_filename_ = 'minion'
# LogLevelMixIn attributes
# LOGS_DIR = '/var/log/salt'
_default_logging_logfile_ = os.path.join(syspaths.LOGS_DIR, 'minion')
# 設定self.config字典的
def setup_config(self):
return config.minion_config(self.get_config_file_path(),
minion_id=True)
設定日志,調用的是salt.log.setup.setup_logfile_logger函數,主要是設定handler,loglevel,formatter。用到的是logging子產品。對應的檔案是salt/log/setup.py
初始化是一般調用的是salt.minion.Minion,如果設定的多個masters,則會調用salt.minion.MultiMinion。這裡以salt.minion.Minion講解過程。對應檔案是salt/minion.py
salt.minion.Minion初始化過程如下:
1、驗證ZMQ的版本
2、擷取grains
3、向ret端口發送驗證請求,擷取master的aes和pub端口
4、擷取pillar資料
5、裝載可用的minion子產品和returners
6、設定schedule
向ret端口發送驗證請求,進行數字簽名過程如下:
對應的接口是salt.crypt.Auth
1、調用get_keys方法load key,如果沒有則生成密鑰對,密鑰儲存到minion.pem,公鑰儲存到minion.pub,然後再load key,使用的子產品是M2Crypto.RSA
2、進行數字簽名,向master_ip:4506發送請求
請求格式:
payload = {
'enc':'clear',
'load':{
'cmd':'_auth',
'id':minion的id,
'pub':minion.pub的内容,
}
傳回格式:
'aes':加密的資料,
'enc':'pub',
'pub_key':key,
'publish_port':'4505',
'sig':加密的資料
3、将pub_key字段對應的資料寫入minion_master.pub
4、對aes和sig字段對應的資料解密,代碼如下
key = self.get_keys()
key_str = key.private_decrypt(payload['aes'], RSA.pkcs1_oaep_padding)
if 'sig' in payload:
m_path = os.path.join(self.opts['pki_dir'], self.mpub)
if os.path.exists(m_path):
try:
mkey = RSA.load_pub_key(m_path)
except Exception:
return '', ''
digest = hashlib.sha256(key_str).hexdigest()
m_digest = mkey.public_decrypt(payload['sig'], 5)
if m_digest != digest:
return '', ''
else:
return '', ''
if '_|-' in key_str:
return key_str.split('_|-')
else:
if 'token' in payload:
token = key.private_decrypt(payload['token'], RSA.pkcs1_oaep_padding)
return key_str, token
elif not master_pub:
return key_str, ''
擷取grains資料主要調用的是salt.loader.grains,這個方法會間接去調用salt.loader.Loader類,對應檔案是salt/loader.py,這個是調用imp子產品加載子產品的。
擷取pillar資料主要調用的是salt.pillar.get_pillar,對應檔案是salt/pillar/__init__.py。
後期會針對pillar和grains的擷取詳細介紹下,或者看看saltstack中國使用者組的介紹。
tune_in的這個方法屬于salt.minion.Minion的。流程如下:
1、擷取pub和pull的位址,預設是檔案,通過ipc通信
2、綁定pub和pull
3、建立sub socket連接配接master的pub位址并保持長連接配接
4、執行死循環,觸發event
這裡隻是大概的記錄下流程,寫的不怎麼詳細,還請大家海涵。
接下來的任務就是研究salt-minion去處理一個job的流程。
參考:
http://www.saltstack.cn/projects/cssug-kb/wiki/Salt-zeromq-01