一、salt常用命令
-
salt 該命令執行salt的執行模塊,通常在master端運行,也是我們最常用到的命令
salt [options] '<target>' <function> [arguments] 如: salt '*' test.ping -
salt-run 該命令執行runner(salt帶的或者自定義的,runner以后會講),通常在master端執行,比如經常用到的manage
salt-run [options] [runner.func] salt-run manage.status ##查看所有minion狀態 salt-run manage.down ##查看所有沒在線minion salt-run manged.up ##查看所有在線minion -
salt-key 密鑰管理,通常在master端執行
salt-key [options] salt-key -L ##查看所有minion-key salt-key -a <key-name> ##接受某個minion-key salt-key -d <key-name> ##刪除某個minion-key salt-key -A ##接受所有的minion-key salt-key -D ##刪除所有的minion-key -
salt-call 該命令通常在minion上執行,minion自己執行可執行模塊,不是通過master下發job
salt-call [options] <function> [arguments] salt-call test.ping ##自己執行test.ping命令 salt-call cmd.run 'ifconfig' ##自己執行cmd.run函數 -
salt-cp 分發文件到minion上,不支持目錄分發,通常在master運行
salt-cp [options] '<target>' SOURCE DEST salt-cp '*' testfile.html /tmp salt-cp 'test*' index.html /tmp/a.html -
salt-ssh 0.17.1版本加入的salt-ssh
-
salt-master master運行命令
salt-master [options] salt-master ##前台運行master salt-master -d ##后台運行master salt-master -l debug ##前台debug輸出 -
salt-minion minion運行命令
salt-minion [options] salt-minion ##前台運行 salt-minion -d ##后台運行 salt-minion -l debug ##前台debug輸出 -
salt-syndic syndic是salt的代理,以后會說到
二、普通用戶執行salt
普通用戶執行salt兩種方案:1,salt ACL 2.salt external_auth
1.ACL
1) 設置master配置文件
client_acl: monitor: - test*: - test.* dev: - service.* sa: - .*
2) 重啟Master
service salt-master restart
3) 目錄和文件權限
chmod +r /etc/salt/master chmod +x /var/run/salt chmod +x /var/cache/salt
4) 測試
# su - monitor # salt 'test*' test.ping # exit; su - sa # salt '*' test.ping # salt '*' cmd.run 'uptime' # exit;
2.external_auth
1) 修改master配置文件
external_auth:
pam: monitor: – ‘test‘: – test. sa: – .* – 2) 3)與ACL相同
4) 測試
# salt -a pam 'test*' test.ping ##會提示輸入賬號密碼,所以external_auth與當前用戶無關 username: monitor password: # su - monitor # salt -a pam '*' cmd.run 'uptime' username: sa password:
5) 使用Token不必每次都輸入賬號密碼,使用external_auth每次都是需要密碼的,這樣多麻煩,這里引入了Token,它會保存一串字符到在當前用戶家目錄下.salt_token中,在有效時間內使用external_auth是不需要輸入密碼的,默認時間12hour,可以通過master配置文件修改
# salt -T -a pam '*' test.ping
username: sa
password:
#salt -a pam '*' test.ping #不會提示輸入密碼了
三、target
指定你的命令或者模塊應用哪寫Minion上
1.globbing 默認
salt 'test*' test.ping
2.RE 正則
salt -E 'web1-(pro|devel)' test.ping
3.List 列表
salt -L '127.0.0.1, test*' test.ping
4.grains
salt -G 'os:CentOS' test.ping #查看所有grains鍵/值 salt 'test*' grains.items #查看所有grains項 salt 'test*' grains.ls 查看某個grains的值 salt 'test*' grains.item num_cpus
在top file中匹配grains
'node_type:web': - match: grain #沒有s - webserver
top file中使用jinja模板
{% set self = grains['node_type'] %} - match: grain - {{ self }}
5.nodegroups 其實就是對Minion分組
首先在master的配置文件中對其分組,推薦寫到/etc/salt/master.d/中一個獨立的配置文件中,比如nodegroup.conf
vim /etc/salt/master.d/nodegroup.conf #寫到master中也是這個格式,master.d中*.conf是默認動態加載的 nodegroups: test1: 'L@test1,test2 or test3*' test2: ‘G@os:CenOS or test2' salt -N test1 test.ping #-N指定groupname 在top file中使用nodegroups 'test1': - match: nodegroup ##意沒s - webserver
6.混合指定,就是將以上的混合起來用
G Grains glob G@os:Ubuntu E PCRE Minion ID E@web\d+\.(dev|qa|prod)\.loc P Grains PCRE P@os:(RedHat|Fedora|CentOS) L List of minions L@minion1.example.com,minion3.domain.com or bl*.domain.com I Pillar glob I@pdata:foobar S Subnet/IP address S@192.168.1.0/24 or S@192.168.1.100 R Range cluster R@%foo.bar salt -C 'G@os:CentOS and L@127.0.0.1,192.168.1.12' test.ping
top file 指定:
'webserver* and G:CentOS or L@127.0.0.1,test1': - match: compound - webserver
7.一次在n個minion上執行
-b n --batch-size n 示例: salt '*' -b 5 test.ping 5個5個的ping
四、遠程批量執行
格式:
salt '<target>' <function> [argument]
注: function是salt帶的或自己寫的可執行模塊里面的function,自帶的所有列表http://docs.saltstack.com/ref/modules/all/index.html?highlight=full%20list%20builtin 實例:
salt '*' at.at 10.10am 'uptime' salt '*' test.ping
五、多Master
1.在另一台機器上安裝salt-master
yum -y install salt-master
2.將原來master上的master密鑰拷貝到新的master是一份
scp /etc/salt/pki/master/master* newmaster:/etc/salt/pki/master/
3.啟動新的Master
service salt-master start
4.修改minion配置文件/etc/salt/minion設置兩個master
master: - master1 - master2
5.重啟minion
service salt-minion restart
6.在新的master上接受所有key
salt-key -L salt-key -A
注意:
1.2個master並不會共享Minion keys,一個master刪除了一個key不會影響另一個
2.不會自動同步File_roots,所以需要手動去維護,如果用git就沒問題了
3.不會自動同步Pillar_Roots,所以需要手工去維護,也可以用git
4.Master的配置文件也是獨立的
六、pillar
Pillar在salt中是非常重要的組成部分,利用它可以完成很強大的功能,它可以指定一些信息到指定的minion上,不像grains一樣是分發到所有Minion上的,它保存的數據可以是動態的,Pillar以sls來寫的,格式是鍵值對
適用情景:
1.比較敏感的數據,比如密碼,key等
2.特殊數據到特定Minion上
3.動態的內容
4.其他數據類型
查看Minion的Pillar信息
salt '*' pillar.items
查看某個Pillar值
salt '*' pillar.item <key> #只能看到頂級的 salt '*' pillar.get <key>:<key> #可以取到更小粒度的
編寫pillar數據
1.指定pillar_roots,默認是/srv/pillar(可通過修改master配置文件修改),建立目錄
mkdir /srv/pillar cd /srv/pillar
2.編輯一個pillar數據文件
vim test1.sls name: 'salt' users: hadoop: 1000 redhat: 2000 ubuntu: 2001
3.建立top file指定minion到pillar數據文件
vim top.sls base: '*': - test1
4.刷新Pillar數據
salt '*' saltutil.refresh_pillar
5.測試
salt '*' pillar.get name salt '*' pillar.item name
在state中通過jinja使用pillar數據
vim /srv/salt/user.sls {% for user, uid in pillar.get(’users’, {}).items() %} ##pillar.get('users',{})可用pillar['users']代替,前者在沒有得到值的情況下,賦默認值 {{user}}: user.present: - uid: {{uid}} {% endfor %}
當然也可以不使用jinja模板
vim /srv/salt/user2.sls {{ pillar.get('name','') }}: user.present: - uid: 2002
通過jinja模板配合grains指定pillar數據
/srv/pillar/pkg.sls pkgs: {% if grains[’os_family’] == ’RedHat’ %} apache: httpd vim: vim-enhanced {% elif grains[’os_family’] == ’Debian’ %} apache: apache2 vim: vim {% elif grains[’os’] == ’Arch’ %} apache: apache vim: vim {% endif %}
七、grains
服務器的一些靜態信息,這里強調的是靜態,就是不會變的東西,比如說os是centos,如果不會變化,除非重新安裝系統
定義minion的grains可以寫在/etc/salt/minion中格式如下
grains: roles: - webserver - memcache deployment: datacenter4 cabinet: 13 cab_u: 14-15
或者寫在/etc/salt/grains中,格式如下
roles: - webserver - memcache deployment: datacenter4 cabinet: 13 cab_u: 14-15
也可以在master中編寫grains的模塊,同步到minion中,用Python來寫很簡單的
1.在/srv/salt中建立_grains目錄
mkdir /srv/salt/_grains
2.編寫grains文件,需要返回一個字典
vim test1.py def hello(): ##函數名字無所謂,應該是所有函數都會運行 agrain = {} agrain['hello'] = 'saltstack' return agrain ##返回這個字典
3.同步到各個minion中去
salt '*' saltutil.sync_grains salt '*' saltutil.sync_all salt '*' state.highstate
4.驗證
salt '*' grains.item hello
八、使用 salt state
它的核心是寫sls(SaLt State file)文件,sls文件默認格式是YAML格式(以后會支持XML),並默認使用jinja模板,YAML與XML類似,是一種簡單的適合用來傳輸數據的格式,而jinja是根據django的模板語言發展而來的語言,簡單並強大,支持for if 等循環判斷。salt state主要用來描述系統,軟性,服務,配置文件應該出於的狀態,常常被稱為配置管理!
通常state,pillar,top file會用sls文件來編寫。state文件默認是放在/srv/salt中,它與你的master配置文件中的file_roots設置有關
示例: apache.sls文件內容 ##/srv/salt/apahce.sls,以后沒有用絕對路徑意思就是在/srv/salt下
apache: ##state ID,全文件唯一,如果模塊沒跟-name默認用的ID作為-name pkg: ##模塊 - installed ##函數 #- name: apache ##函數參數,可以省略 service: ##模塊 - running ##函數 #- name: apache ##函數參數,這個是省略的,也可以寫上 - require: ##依賴系統 - pkg: apache ##表示依賴id為apache的pkg狀態
下面來解釋上面示例的意思:
聲明一個叫apache的狀態id,該id可以隨意,最好能表示一定意思
pkg代表的是pkg模塊
installed是pkg模塊下的一個函數,描述的是狀態,該函數表示apache是否部署,返回值為True或者False,為真時,表示狀態OK,否則會去滿足該狀態(下載安裝apache),如果滿足不了會提示error,在該模塊上面省略了參數-name: apache,因為ID為apache,這些參數是模塊函數需要的(可以去查看源碼)
service是指的service模塊,這個模塊下主要是描述service狀態的函數,running狀態函數表示apache在運行,省略-name不在表述,-require表示依賴系統,依賴系統是state system的重要組成部分,在該處描述了apache服務的運行需要依賴apache軟件的部署,這里就要牽涉到sls文件的執行,sls文件在salt中執行時無序(如果沒有指定順序,后面會講到order),假如先執行了service這個狀態,它發現依賴pkg包的安裝,會去先驗證pkg的狀態有沒有滿足,如果沒有依賴關系的話,我們可以想象,如果沒有安裝apache,apache 的service肯定運行會失敗的,我們來看看怎么執行這個sls文件:
salt '*' state.sls apache
在命令行里這樣執行就ok了,.sls不要寫,如果在目錄下,將目錄與文件用’.’隔開,如: httpd/apache.sls –> httpd.apache
或者
salt '*' state.highstate
這需要我們配置top file執定哪個minion應用哪個狀態文件
top.sls內容
base: '*': - apache
下面我們繼續看一些比較復雜的:
ssh/init.sls文件內容
openssh-client: pkg.installed /etc/ssh/ssh_config: file.managed: - user: root - group: root - mode 644 - source: salt://ssh/ssh_config - require: - pkg: openssh-client
ssh/server.sls文件內容
include: - ssh openssh-server: pkg.installed sshd: service.running: - require: - pkg: openssh-client - pkg: openssh-server - file: /etc/ssh/banner - file: /etc/ssh/sshd_config /etc/ssh/sshd_config: file.managed: - user: root - group: root - mode: 644 - source: salt://ssh/sshd_config - require: - pkg: openssh-server /etc/ssh/banner: file: - managed - user: root - group: root - mode: 644 - source: salt://ssh/banner - require: - pkg: openssh-server
ssh/init.sls,學過Python的都知道目錄下面的init文件是特殊文件,它怎么特殊呢,它特殊在當我們應用目錄時會應用該文件的內容,如我們執行 salt ‘*’ state.sls ssh時應用的就是init.sls文件,明白了嗎?再看里面的內容,前兩行我們已經看過了,是描述某個rpm包有沒有安裝的,第三行是ID,也可以用來表示-name,以省略-name,file.managed是file模塊與函數managed的快捷寫法,看server.sls下最后就知道了,managed它描述了某個文件的狀態,后面跟的是managed的參數,user,group,mode你們一看就知道什么意思了,關於這個source是指從哪下載源文件,salt://ssh/sshd_config是指的從salt的文件服務器里面下載,salt文件服務器其實就是file_roots默認/srv/salt/明白了嗎,所以salt://ssh/sshd_config指的就是 /srv/salt/ssh/sshd_config,出來用salt的文件服務器,也可以用http,ftp服務器。- require是依賴系統不表,以后會詳細說它的。再往下是server.sls文件,include表示包含意思,就是把ssh/init.sls直接包含進來
這時你會看到/srv/salt的目錄樹是:
ssh/init.sls ssh/server.sls ssh/banner ssh/ssh_config ssh/sshd_config
下面再來看一個官方樣例:
ssh/custom-server.sls 文件內容
include: - ssh.server extend: /etc/ssh/banner: file: - source: salt://ssh/custom-banner
python/mod_python.sls文件內容
include: - apache extend: apache: service: - watch: - pkg: mod_python
首先我們include的別的文件,但是里面的內容並不是全部符合我們的要求,這時我們就需要用extend來重寫部分內容,特殊的是依賴關系都是追加。custom-server.sls文件意思是包含ssh/server.sls,擴展/etc/ssh/banner,重新其source而其它的如user,group等不變,與include一致。 mode_python.sls文件意思是把apache.sls包含進來,想apache-service是追加了依賴關系(watch也是依賴系統的函數).
常用狀態配置 salt-states-master.zip
九、關於渲染器render system
我們上面也提過salt默認的渲染器是yaml_jinja,salt處理我們的sls文件時,會先把文件用jinja2處理,然后傳給ymal處理器在處理,然后生成的是salt需要的python數據類型。除了yaml_jinja還有yaml_mako,yaml_wempy,py,pydsl,我比較感興趣的就是yaml_jinja,還有py,yaml_jinja是默認的,而py是用純python來寫的。下面來看個樣例吧,
apache/init.sls文件內容
apache: pkg:installed: {% if grains['os'] == 'RedHat' %} - name: httpd {% endif %} service.running: {% if grains['os'] == 'Redhat' %} - name: httpd {% endif %} - watch: - pkg: apache
這個樣例很簡單,就是加了個判斷,如果Minion的grains的os是RedHat那么apache的包名是httpd,默認是apache,我們知道在別的Linux發行版上,如ubuntu,suse他們的apache的包名就是叫apache,而在redhat系上則叫httpd,所以才有了這個判斷寫法,下面的service也是如此。我們着重說語法,jinja中判斷,循環等標簽是放在{% %}中的,通常也會有結束標簽{% end** %},而變量是放在 {{ }}中的,salt,grains,pillar是salt中jinja里面的三個特殊字典,salt是包含所有salt函數對象的字典,grains是包含minion上grains的字典,pillar是包含minion上pillar的字典。
示例:for user/init.sls文件內容
{% set users = ['jerry','tom','gaga'] %} {% for user in users %} {{ user }}: user.present: - shell: /bin/bash - home: /home/{{ user }} {% endfor %}
示例;salt字典 user/init.sls文件內容
{% if salt['cmd.run']('uname -i') == 'x86_64' %} hadoop: user.present: - shell: /bin/bash - home: /home/hadoop {% elif salt['cmd.run']('uname -i') == 'i386' %} openstack: user.present: - shell: /bin/bash - home: /home/openstack {% else %} django: user.present: - shell: /sbin/nologin {% endif %}
py渲染器 說明:py渲染器是用純python寫的sls文件,它返回的數據與yaml_jinja經過jinja處理經過yaml處理后的數據類似 ,用其他渲染器需要在sls文件頭行聲明用的渲染器類型,#!py就是聲明用的py渲染器,py中可用的變量有salt,grains,pillar,opts,env,sls,前三個分別對應jinja里的salt,grains,pillar,opts是minion的配置文件的字典,env對應的是環境如base,sls對應的是sls的文件名
示例: user/init.sls
#!py import os def run(): '''add user hadoop''' platform = os.popen('uname -a').read().strip() if platform == 'x86_64': return {'hadoop': {'user': ['present',{'shell': '/bin/bash'}, {'home': '/home/hadoop'}]}} elif platform == 'i386': return {'openstack': {'user': ['present', {'shell': '/bin/bash'}, {'home': '/home/openstack'}]}} else: return {'django': {'user': ['present', {'shell': '/sbin/nologin'}]}}
說明: 首行聲明了使用py作為渲染器,導入了os模塊,聲明run函數,py渲染sls文件是從run函數開始的,其它的就是python的語法了,注意的是return的數據結構{ID: {module: [func, arg1,arg2,...,]}} 或 {ID: {module.func: [arg1,arg2,..,]}} 。表示的內容與“示例;salt字典”表達的相同
十、state的執行順序
以前我們說過,state的執行時無序,那個無序是指執行我們寫的那個sls是無序的,正是因為那個無序,salt保證每次執行的順序是一樣的,就加入了state order,在說它之前看看High Data(高級數據?)和Low Data(低級數據?),高級數據我理解的就是我們編寫sls文件的數據,低級數據就是經過render和parser編譯過的數據。
查看highdata
salt '*' state.show_highstate
查看lowdata
salt '*' state.show_lowstate
通過查看lowdata我們發現里面有一個字段order,因為salt默認會自動設置order,從10000開始。可以通過設置master配置文件參數state_auto_order: False來關閉
Order的設定:
1.include 被include的文件Order靠前,先執行
2.手動定義order字段,如
apache: pkg: - installed - order: 1 order的數字越小越先執行從1開始,-1是最后執行
3.依賴關系系統
十一、依賴關系系統requisite system
前面我們已經用過了依賴關系系統,就是定義狀態與狀態之間的依賴關系的,經常遇到的依賴系統的函數有’require’和’watch’和它們的變種’require_in’,’watch_in’,require和watch有什么區別嗎?
1.不是所有的state都支持watch,比較常用的是service
2.watch定義的依賴條件發生變化時會執行一些動作,如當配置文件改變時,service會重啟
示例: apache/init.sls文件內容
/etc/httpd/httpd.conf: file: - managed - source: salt://httpd/httpd.conf httpd: pkg: - installed service: - running - require: - pkg: httpd - watch: - file: /etc/httpd/httpd.conf ##當httpd.conf改變時,重啟httpd服務
require與require_in, watch與watch_in
require,watch是指依賴,require_in,watch_in是指被依賴
a reuire b 那么就是b require_in a
a watch b 那么就是b watch_in a
示例: apache/init.sls文件內容
/etc/httpd/httpd.conf: file: - managed - source: salt://httpd/httpd.conf - watch_in: - service: httpd httpd: pkg: - installed - require_in: - service: httpd service: - running
十二、salt state環境
針對不用環境,應用不同的state的file,salt支持多環境,比如開發,測試,生產等環境,我們通過修改Master配置文件對不同的環境應用不同的目錄!
file_roots: base: - /srv/salt/prod ##生產環境 qa: - /srv/salt/qa ##測試環境,如果沒發現去prod里面找 - /srv/salt/prod dev: - /srv/salt/dev ##開發環境,如果找不到,先去qa里找,如果找不到再去prod里面找 - /srv/salt/qa - /srv/salt/prod /srv/salt/prod/top.sls文件內容 base: 'web*prod*': - webserver.foobarcom qa: 'web*qa*': - webserver.foobarcom dev: 'web*dev': - webserver.foobarcom -
pillar的目錄與file_roots無關,所以Pillar的目錄默認還是/srv/salt,pillar只是Minion的一些信息,不會對系統有什么改變,所以不需要區分環境,通常base即可。
/srv/pillar/top.sls文件內容
base: 'web*prod*': - webserver.prod 'web*qa*': - webserver.qa 'web*dev*': - webserver.dev
/srv/pillar/webserver/prod.sls文件內容
webserver_role: prod
/srv/pillar/webserver/qa.sls文件內容
webserver_role: qa
/srv/pillar/webserver/dev文件內容
webserver_root: dev
最后sls文件/srv/salt/prod/webserver/foobarcom.sls(該文件會被所有環境訪問到)的內容:
{% if pillar.get('webserver_role', '') %} /var/www/foobarcom: file.recurse: - source: salt://webserver/src/foobarcom - env: {{ pillar['webserver_role'] }} - user: www - group: www - dir_mode: 755 - file_mode: 644 {% endif %}
開發完成后,應用sls文件
1.現在開發環境
salt -I ‘webserver_role:dev’ state.sls webserver.foobarcom
十三、salt schedule
schedule是salt中的crontab,就是周期性執行一些函數,需要注意的是在minion上執行的函數是salt的可執行模塊里的函數,在master上執行的是runner模塊的函數,下面看看如何設置: master是修改master配置文件/etc/salt/master:
schedule: overstate: ##這個是ID,可以隨意起,全文件唯一 function: state.over ##對於master,function就是runner seconds: 35 ##間隔秒數 minutes: 30 ##間隔分數 hours: 3 ##間隔小時數
這時每隔3小時30分35秒,master就會運行一個state.over這個runner
minion的schedule定義有兩種方式
1.通過修改minion的配置文件,這種方式需要修改所有Minion的配置文件略麻煩
schedule: highstate: function: state.highstate seconds: 30 minutes: 5 hours: 1
2.為Minion指定pillar
/srv/pillar/schedule.sls文件內容
schedule: highstate: function: state.highstate seconds: 30 minutes: 5 hours: 1
通過top file指定到Minion
/srv/pillar/top.sls文件內容
base: *: - schedule
十四、YAML語法風格
1.空格和Tabs
在YAML中不要使用Tab
2.縮進
YAML推薦縮進為2個空格,’:’,’-’后面縮進1個空格再寫
3.數字會解析成數字
如mode: 0644會解析成mode: 644,可用’括住防止mode: ’0644′此情況
4.YAML不允許雙簡寫
vim:
pkg.installed ##第一個簡寫,單一個簡寫沒問題 user.present ##第二個簡寫,加上它是不支持的
不要偷懶寫成下面這樣吧。
vim: pkg:
- installed user: – present – 5.YAML只支持ASCII
其它字符集最好不要使用,如果非要使用用以下格式:
- micro: ‘\u00b5′
6.下划線_將會被刪除
date: 2013_05_13 --> date: 20130513
通過’括住防止出現該問題
date: '2013_05_13'
十五、salt事件系統與反應系統 event and reacter system
我們知道Master與Minion是基於ZMQ通信的,他們通信我們看來是消息隊列,對它們來說這些消息就是一些事件,什么事件應該做什么,是salt基本已經預設好了。我們學習它的事件系統來完成一些自定義的行為,后面的反應系統就是基於事件系統的。一條消息其實就是一個事件,事件通常是一個字典數據,這個字典數據通常包含tag,這個tag是用來區分用途過濾消息的,詳見綠大-https://groups.google.com/forum/#!topic/saltstack-users-cn/wXVE4ydnnzc ,讓我們來看看這些事件。
捕捉事件(listen event)
1.下載官方給的事件捕捉程序eventlisten
https://github.com/saltstack/salt/blob/develop/tests/eventlisten.py 打開網址,復制下載,不要直接wget
2.運行該程序
Master: python2.6 eventlisten.py ##捕捉master端的event直接運行即可 Minion: python2.6 eventlisten.py -n minion <minion-id> ##捕捉minion端的需要額外參數,minion-id是該Minion的id
發送事件(fire event)
Master發給minion
salt '*' event.fire "{'data': 'some message'}" "tag" ##前面必須是字符串包住的字典,后面是tag,如果你的minion在監聽event,你會看到這條event的
Minion發給minion
salt-call event.fire_master 'some message' 'tag' ##前面數據類型沒有要求,后面是tag,去master那看看收到了沒有
Minion發給自己
salt-call event.fire "{'data': 'some message'}" 'tag' ##前面必須是字符串包住的字典,后面是tag
用code來捕捉,並發送event
捕捉事件 Master:
# python2.6 >>> import salt.utils.event >>> event = salt.utils.event.SaltEvent('master', '/var/run/salt/master') ##master表明是在master端監聽,/var/run/salt/master是你master的sock_dir >>> data = event.get_event() >>> print(data) ##查看內容 >>> data = event.get_event(wait=10, tag='auth') ##wait是指timeout時間,默認5s,用tag來過濾事件,可省略 >>> print(data) >>> for data in event.iter_events(tag='auth'): ##用迭代器一直查看事件 >>> print(data) Minion: #python2.6 >>> import salt.utils.event >>> event = salt.utils.event.SaltEvent('minion', '/var/run/salt/minion',id='minion_id') ##minion代表是在minion端監聽,/var/run/salt/minion是minion端的sock_dir,minion_id是該Minion的id >>> data = event.get_event() >>> print(data) >>> for data in event.iter_events(tag='auth'): ##用迭代器一直查看事件 >>> print(data)
—————–先這樣吧 發送事件:
Master: >>> import salt.utils.event >>> event = salt.utils.event.SaltEvent('master', '/var/run/salt/minion') >>> event.fire_event({'hello': 'world'}, 'hello')
—————–先這樣
反應系統(reacter system)
反應系統是基於事件系統的,它的作用是當master收到來自minion的特殊事件后就觸發某些動作,比如minion上線后發送一個init事件,master收到后,對其應用init的狀態文件,minion沒有反應系統,事情就是這樣的。
配置reactor
1.修改master配置文件或者在/etc/salt/master.d/中建立reactor.conf,內容
reactor: - 'testtag': ##接收到的tag - /srv/reactor/start.sls - /srv/reactor/monitor.sls - 'test1*tag': ##接收到的tag,支持通配符 - /srv/reactor/other.sls
- 2.建立reactor響應sls文件
/srv/reacter/start.sls文件內容
{% if data['id'] == 'mysql1' %} delete_file: cmd.cmd.run: - tgt: 'G@os:CentOS' - expr_form: compound - arg: - rm -rf /tmp/* {% endif %}
/srv/reactor/other.sls文件內容
{% if data['data']['state'] == 'refresh' %} overstate_run: runner.state.over {% endif %}
下面來解釋一下這兩個文件,reacter的sls文件是支持jinja的,所以第一行是通過jinja來判斷,reacter的sls支持兩個變量data和tag, data是接受事件的那個字典,tag就是事件的tag,所以第一行的判斷就很好理解了,第二行是id,可以隨意起,第三行是要運行的執行模塊或者runner,如果是執行模塊,以cmd.開始,如果是runner則以runner.開始,可執行模塊執行需要target,所以- tat:后面跟的就是可執行模塊的target,- expr_form指的target的匹配方式,- arg是只執行模塊函數的參數,runner一般不需要這些。所以第一個示例相當於執行了salt -C 'G@mysql1' cmd.run 'rm -rf /tmp/*' 第二個相當於執行了 salt-run state.over
十六、salt Mine
salt的用的詞都太高明,像Grains,Pillar,Mine真心沒一個合適的詞去翻譯,Mine是做什么的呢?Mine的作用是在靜態數據和動態數據建立起一座橋梁(官方文檔如是說),Mine從minon收集數據然后發送給Master,並緩存在Master端,所有Minion都可以輕易的共享到,Master通常會維護比較新的數據,如果需要維護長期數據,就要考慮retruner或外部的工作緩存了。 mine的出現是用來解決一定問題的. 在Salt的網絡體系中,各個minion是毫無關系,相互獨立的. 但是在實際應用中,minion之間其實是有一定關聯的,比如一台機器需要獲取到另一台機器的一些信息或者執行一些命令. 后來Salt加入了peer系統(http://docs.saltstack.com/ref/peer.html)使其成為可能. 但是peer系統每次使用的時候都會重新執行一遍, 顯然很多不常變化的信息重復執行效率較低,性能開銷較大. 所以就有了后來的mine(peer和mine的關系是我杜撰出來的,如有雷同,純屬巧合). mine系統存儲在master端, minion想獲取的時候, 通過mine.get獲取下就可以了,簡單方便
修改minion配置文件,配置Mine
mine_functions: network.interfaces: [] test.ping: [] mine_interval: 1
重啟Minion,在master端測試
salt '*' mine_get '*' network.interfaces salt '*' mine_get '*' test.ping salt 'test1' mine_get '*' test.ping ##查看test1上能得到mine數據
十七、salt ssh
從0.17.0開始salt加入salt ssh,salt ssh不需要在客戶端安裝salt-minion包了,是通過ssh協議來完成運城命令執行,狀態管理等任務的。它是作為master-minion形式的補充出現的,原理是有一個花名冊的文件,里面記錄了各個minion的信息,ip,賬號,密碼,等,需要遠程執行命令時,直接通過ssh來執行,速度與master-minion形式慢很多。
使用: 1.配置/etc/salt/roster格式如下
test1: host: 192.168.1.133 user: salt passwd: redhat sudo: True port: 22 timeout: 5 test2: host: 192.168.1.134 user: root passwd: redhat test3: host: 192.168.1.135 user: sa sudo: True
說明: test1我們定義了所有常見的選項,test2我們用了超級用戶,使用賬號密碼,test3我們使用普通用戶,沒有寫密碼,就是通過key來認證了,並且以sudo方式執行的,需要注意的是1.key認證用的是/etc/salt/pki/master/ssh/目錄下的密鑰。2.如果普通用戶的話,需要有sudo權限,因為一些功能,包括test.ping都需要sudo權限。
測試:
salt-ssh '*' test.ping salt-ssh '*' -r 'ls /' ##執行shell命令 salt-ssh '*' cmd.run 'ls /' ##用模塊來執行也是可以的 salt-ssh '*' state.sls ##執行狀態,state.sls在0.71.0中還存在bug,0.72.0中已解決
十八、Returners
默認所有minion返回的值都會發送到master端,我們可以看到,returner就是讓Minion把返回的值發給其它地方,如redis,MySQL,或者一個文本 下面我們來自定義一個returner:
1.建立自定義returner
mkdir -p /srv/salt/_returners; vim mysql.py ##就用官方給的例子吧,修改其中mysql的Host,user和pass
內容見https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py
2.建立需要的數據庫
見https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py注釋里的見表語句
3.授權其他主機用戶可寫該表
>grant all on salt.* to 'user_in_returner'@'%' identified by 'passwd_in_returner';
4.同步
salt '*' saltutil.sync_all ##同步到minion上去
5.測試
salt '*' test.ping --return mysql ##數據返回到mysql上去,打開mysql查看
十九、擴展salt
通過自定義各個模塊來擴展salt,常見自定義模塊有:
1.可執行模塊 Execution Modules
如我們常用的cmd.run , test.ping這樣的可執行模塊
2.Grains
擴展grains,grains是一些靜態信息,可能好多我們需要的沒有,我們可以通過編寫grains模塊自定義grains
3.狀態模塊 State Module
如我們常用的pkg.install,file.managed
4.Returners
我們可以自定義returner,將返回的數據發送到其他存儲,只要符合固定的格式就行了
5.Runner
Runner是在master端快速執行的模塊,自定義很方便
二十、自定義可執行模塊
所有可執行module見https://github.com/saltstack/salt/tree/develop/salt/modules,或http://docs.saltstack.com/ref/modules/all/index.html?highlight=full%20list%20builtin
1.建立自定義模塊目錄,通常所有自定義模塊放在該目錄下
mkdir /srv/salt/_modules
2.編寫模塊
vim test.py -*- coding: utf-8 -*- ''' support for yum of RedHat family! ''' def __virtual__(): ''' Only RedHat family os can use it. ''' if __grains__.get('os_family', 'unkown') == 'RedHat': return 'yum' else: return False def install(rpm): cmd = 'yum -y install {0}'.format(rpm) ret = __salt__['cmd.run'](cmd) return ret
說明:__virtual__函數通常用來匹配是否滿足該模塊的環境,如果滿足return出來的字符串作為該模塊的名字而不是文件名,如果return的是False代表的此模塊無效,不能使用。在自定義模塊中可以中__grains__是一個包含了minion 所有grains的字典,__pillar__是包含了所有Pillar的grains字典,__salt__是所有可執行函數對象的字典,通常最常使用的就是這三個變量了。再往下面是定義了函數install,在salt中一般不用’%s’ % var這種格式化形式,而是使用字符串的format方法,具體使用見百度。下面就是通過__salt__執行了cmd.run這個函數來運行yum命令,很簡單吧,最后把結果返回回去。
3.測試
salt '*' yum.install ftp ##查看返回值
二十一、自定義grains
自定義的grains也是由Python寫成的,通常放在/srv/salt/_grains下,grains需要返回一個字典,__salt__,__grains__,__pillar__也是可以在grains中使用的。前面已經介紹過寫簡單自定義grains了,復雜就就參照https://github.com/saltstack/salt/blob/develop/salt/grains/core.py官方這個吧
二十二、自定義returner
前面已經看過官方的mysql的returner了,今天來說說自定義returner需要注意的,來個例子吧。 /srv/salt/_returners/file.py內容
def __virtual__(): return 'file' def returner(ret): ''' Return information to /tmp/returns.txt. ''' # open a file result_file = '/tmp/returns.txt' f = open(result_file, 'a+') f.write(str(ret)) f.close() salt '*' saltutil.sync_all ##同步模塊 salt '*' test.ping --return file ##測試 cat /tmp/returns.txt ##在minion上查看 {'jid': '20131227153001246117', 'return': True, 'retcode': 0, 'success': True, 'fun': 'test.ping', 'id': 'test1'}
說明: 通過這個簡單的例子我們了解返回的值是個字典,字典包括的項就是上面我們看到的,以后寫其它returner時,也就是把這個字典的值寫到不同的地方而已。這個returner的意思就是把返回的值寫到各個minion的/tmp/returns.txt中。
二十三、file state backup
來例子看看吧。 /srv/salt/test.sls文件內容
/tmp/test.txt: file.managed: - source: salt://test.txt - backup: minion
其中多了一個參數backup,后面跟的值minion,意思是說這個文件在minion中備份一份,文件名帶着時間戳,備份位置在/var/cache/salt/minion/file_backup
執行並測試:
salt '*' state.sls test ##注,多修改幾次test.txt,多運行幾次該state salt '*' file.list_backups /tmp/test.txt ##這是會返回備份序號,時間,位置,大小
回退 當文件改錯后,我們可以用備份文件回退
salt '*' file.restore_backup /tmp/test.txt 2 ##回退的文件,與想要回退的序列號
刪除 刪除不需要的備份文件
salt '*' file.delete_backup /tmp/test.txt 3
二十四、應用實例
saltstack 遠程觸發文件備份、回滾
1、創建模塊方法文件
mkdir /srv/salt/_modules
默認沒有此文件,自己生成一個
下面的py文件自己定義,下面是我寫的兩個方法:
#!/usr/bin/python # -*- coding: utf-8 -*- import sys,string,shutil import os,tarfile import datetime,time tn=datetime.datetime.today() time_now=tn.strftime("%Y-%m-%d") data_bak='/data/databak' data_tmp='/data/databak/tmp/%s' % time_now com_f="%s/%s" % (data_bak,time_now) if not os.path.exists(com_f): os.makedirs(com_f) def CpFile(): id = sys.argv[1] dir = sys.argv[2] #傳入兩個變量,任務自動生成的id與要替換的文件 filename = '%s/%s.tar' % (com_f, id) mode = 'w:tar' os.chdir(data_bak) w_file=open("/tmp/tmp.list",'w') w_file.write(id+" "+dir) #記錄每次備份的id與相對應的備份目錄或文件的路徑 w_file.close() file = tarfile.open( filename, mode ) file.add( '/tmp/tmp.list' ) file.add( dir ) file.close() return 'ok' #測試過程,就先讓返回ok吧,之后再做判斷 def RollBack(): id = sys.argv[1] #想要回滾到的版本id if not os.path.exists(data_tmp): os.makedirs(data_tmp) filename = '%s/%s.tar' % (com_f, id) tar = tarfile.open("%s" % filename) for b in tar: tar.extract(b,path="%s" % data_tmp