更新于 3.25 23:16
salt簡介
SaltStack是一個服務器基礎架構(gòu)集中化管理平臺粪小,具備配置管理、遠程執(zhí)行抡句、監(jiān)控等功能探膊,基于Python語言實現(xiàn),結(jié)合輕量級消息隊列(ZeroMQ)與Python第三方模塊(Pyzmq待榔、PyCrypto逞壁、Pyjinjia2、python-msgpack和PyYAML等)構(gòu)建究抓。
通過部署SaltStack猾担,我們可以在成千萬臺服務器上做到批量執(zhí)行命令袭灯,根據(jù)不同業(yè)務進行配置集中化管理刺下、分發(fā)文件、采集服務器數(shù)據(jù)稽荧、操作系統(tǒng)基礎及軟件包管理等橘茉,SaltStack是運維人員提高工作效率工腋、規(guī)范業(yè)務配置與操作的利器。
salt基本原理
SaltStack 采用 C/S模式畅卓,server端就是salt的master擅腰,client端就是minion,minion與master之間通過ZeroMQ消息隊列通信
minion上線后先與master端聯(lián)系翁潘,把自己的pub key發(fā)過去趁冈,這時master端通過salt-key -L命令就會看到minion的key,接受該minion-key后拜马,也就是master與minion已經(jīng)互信
master可以發(fā)送任何指令讓minion執(zhí)行了渗勘,salt有很多可執(zhí)行模塊,比如說cmd模塊俩莽,在安裝minion的時候已經(jīng)自帶了旺坠,它們通常位于你的python庫中,
locate salt | grep /usr/
可以看到salt自帶的所有東西扮超。這些模塊是python寫成的文件取刃,里面會有好多函數(shù),如cmd.run出刷,當我們執(zhí)行
salt '*' cmd.run 'uptime'
的時候璧疗,master下發(fā)任務匹配到的minion上去,minion執(zhí)行模塊函數(shù)馁龟,并返回結(jié)果病毡。master監(jiān)聽4505和4506端口,4505對應的是ZMQ的PUB system屁柏,用來發(fā)送消息折晦,4506對應的是REP system是來接受消息的。
具體步驟如下
- Salt stack的Master與Minion之間通過ZeroMq進行消息傳遞窟赏,使用了ZeroMq的發(fā)布-訂閱模式瞄摊,連接方式包括tcp,ipc
- salt命令裸删,將
cmd.run ls
命令從salt.client.LocalClient.cmd_cli
發(fā)布到master八拱,獲取一個Jodid,根據(jù)jobid獲取命令執(zhí)行結(jié)果涯塔。 - master接收到命令后肌稻,將要執(zhí)行的命令發(fā)送給客戶端minion。
- minion從消息總線上接收到要處理的命令匕荸,交給
minion._handle_aes
處理 -
minion._handle_aes
發(fā)起一個本地線程調(diào)用cmdmod執(zhí)行l(wèi)s命令爹谭。線程執(zhí)行完ls后,調(diào)用minion._return_pub
方法榛搔,將執(zhí)行結(jié)果通過消息總線返回給master - master接收到客戶端返回的結(jié)果诺凡,調(diào)用
master._handle_aes
方法东揣,將結(jié)果寫的文件中 -
salt.client.LocalClient.cmd_cli
通過輪詢獲取Job執(zhí)行結(jié)果,將結(jié)果輸出到終端腹泌。
安裝salt
導入salt
7版本
rpm --import https://repo.saltstack.com/yum/redhat/7/x86_64/latest/SALTSTACK-GPG-KEY.pub
6版本
rpm --import https://repo.saltstack.com/yum/redhat/6/x86_64/latest/SALTSTACK-GPG-KEY.pub
#新增文件 /etc/yum.repos.d/saltstack.repo
7 & 6版本
[saltstack-repo]
name=SaltStack repo for RHEL/CentOS $releasever
baseurl=https://repo.saltstack.com/yum/redhat/$releasever/$basearch/latest
enabled=1
gpgcheck=1
gpgkey=https://repo.saltstack.com/yum/redhat/$releasever/$basearch/latest/SALTSTACK-GPG-KEY.pub
安裝 salt-minion, salt-master,或Salt components:
yum install salt-master
yum install salt-minion
yum install salt-ssh
yum install salt-syndic
yum install salt-cloud
配置salt
master
一般使用默認就好 (/etc/salt/master)
#指定master嘶卧,冒號后有一個空格
master: 192.168.2.22
user: root
#-------以下為可選--------------
# salt運行的用戶,影響到salt的執(zhí)行權(quán)限
user: root
#s alt的運行線程凉袱,開的線程越多一般處理的速度越快芥吟,但一般不要超過CPU的個數(shù)
worker_threads: 10
# master的管理端口
publish_port : 4505
# master跟minion的通訊端口,用于文件服務专甩,認證运沦,接受返回結(jié)果等
ret_port : 4506
# 如果這個master運行的salt-syndic連接到了一個更高層級的master,那么這個參數(shù)需要配置成連接到的這個高層級master的監(jiān)聽端口
syndic_master_port : 4506
# 指定pid文件位置
pidfile: /var/run/salt-master.pid
# saltstack 可以控制的文件系統(tǒng)的開始位置
root_dir: /
# 日志文件地址
log_file: /var/log/salt_master.log
# 分組設置
nodegroups:
group_all: '*'
# salt state執(zhí)行時候的根目錄
file_roots:
base:
- /srv/salt/
# 設置pillar 的根目錄
pillar_roots:
base:
- /srv/pillar
啟動master
systemctl start salt-master
systemctl enable salt-master
minion
(/etc/salt/minion)
#指定master,冒號后有一個空格
master: 192.168.2.22
id: minion-01
user: root
#-------以下為可選--------------
# minion的識別ID配深,可以是IP携添,域名,或是可以通過DNS解析的字符串
id: 192.168.0.100
# salt運行的用戶權(quán)限
user: root
# master的識別ID篓叶,可以是IP烈掠,域名,或是可以通過DNS解析的字符串
master : 192.168.0.100
# master通訊端口
master_port: 4506
# 備份模式缸托,minion是本地備份左敌,當進行文件管理時的文件備份模式
backup_mode: minion
# 執(zhí)行salt-call時候的輸出方式
output: nested
# minion等待master接受認證的時間
acceptance_wait_time: 10
# 失敗重連次數(shù),0表示無限次俐镐,非零會不斷嘗試到設置值后停止嘗試
acceptance_wait_time_max: 0
# 重新認證延遲時間矫限,可以避免因為master的key改變導致minion需要重新認證的syn風暴
random_reauth_delay: 60
# 日志文件位置
log_file: /var/logs/salt_minion.log
# 文件路徑基本位置
file_roots:
base:
- /etc/salt/minion/file
# pillar基本位置
pillar_roots:
base:
- /data/salt/minion/pillar
啟動minion
systemctl start salt-minion
systemctl enable salt-minion
添加key
master 端查看key
[root@master salt]# salt-key
Accepted Keys:
Denied Keys:
Unaccepted Keys: #可看到 minion已經(jīng)檢測到,沒有認證key
minion-01
Rejected Keys:
[root@master salt]# salt-key -a minion-01
The following keys are going to be accepted:
Unaccepted Keys:
minion-01
Proceed? [n/Y] y #Y確認添加
Key for minion minion-01 accepted. #添加成功
[root@master salt]# salt-key
Accepted Keys:
minion-01
Denied Keys:
Unaccepted Keys:
Rejected Keys:
[root@master salt]#
salt-key常用參數(shù)
-a | 添加指定ID 的key |
---|---|
-A | 添加全部 |
-R | 拒絕全部 |
-d | 刪除指定ID的 |
-D | 刪除全部 |
測試連通性
[root@master salt]# salt 'minion-01' test.ping
minion-01:
True #返回結(jié)果表示成功
[root@master salt]#
簡單服務的安裝
[root/] ]$salt 'minion-01' pkg.install ftp #解釋
minion-01:
----------
ftp:
----------
new:
0.17-67.el7
old:
[root/] ]$
#去minion查看
[root@minion-01 tmp]# rpm -qa ftp
ftp-0.17-67.el7.x86_64
#salt 'minion-01' pkg.install ftp
#1.'*' 代表的是target是指在那些minion上操作
#2. 'pkg' 是一個執(zhí)行模塊,就像'test'
#3.'install' 是執(zhí)行模塊下面的函數(shù)佩抹,像test下的ping
#4.'ftp' 是函數(shù)的參數(shù)(arg)叼风,有的函數(shù)需要參數(shù),有的不需要比如test.ping就不需要參數(shù)
##查看所有執(zhí)行模塊的doc
salt 'minion' sys.doc
##查看test模塊的幫助
salt 'minion' sys.doc test
##查看test.ping函數(shù)的幫助
salt 'minion' sys.doc test.ping
salt常用命令
salt
該命令執(zhí)行salt的執(zhí)行模塊,通常在master端運行.常用命令
salt [option] '<target>' <function> [arguments]
#例如
salt 'minion-01' cmd.run 'ip addr'
salt-run
該命令執(zhí)行runner(salt自帶或者自定義的棍苹,)无宿,通常在master端執(zhí)行,比如經(jīng)常用到的manage
salt-run [options] [runner.func]
#例如
salt-run manage.status ##查看所有minion狀態(tài)
salt-run manage.down ##查看所有沒在線minion
salt-run manage.up ##查看所有在線minion
salt-key
密鑰管理枢里,通常在master端執(zhí)行
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上執(zhí)行孽鸡,minion自己執(zhí)行可執(zhí)行模塊,不通過master下發(fā)job
salt-call [options] <function> [arguments]
salt-call test.ping ##自己執(zhí)行test.ping命令
salt-call cmd.run 'ifconfig' ##自己執(zhí)行cmd.run函數(shù)
salt-cp
分發(fā)文件到minion上,不支持目錄分發(fā).運行在master
salt-cp [options] '<target>' SOURCE DEST
#例如
salt-cp '*' testfile.html /tmp
salt-cp 'test*' index.html /tmp/a.html
salt-master
salt-master [options]
salt-master ##前臺運行master
salt-master -d ##后臺運行master
salt-master -l debug ##前臺debug輸出
salt-minion
salt-minion [options]
salt-minion ##前臺運行
salt-minion -d ##后臺運行
salt-minion -l debug ##前臺debug輸出
普通用戶執(zhí)行salt
兩種方法
1: ACL(修改master)
client_acl:
monitor: #uonghu
- test*: #權(quán)限
- test.*
dev:
- service.*
sa:
- .*
#重啟master
#給予目錄和文件權(quán)限
chmod +r /etc/salt/master
chmod +x /var/run/salt
chmod +x /var/cache/salt
2 external_auth(修改master)
pam:
fred:
- test.*
#重啟master
#給予目錄和文件權(quán)限
chmod +r /etc/salt/master
chmod +x /var/run/salt
chmod +x /var/cache/salt
使用Token不必每次都輸入賬號密碼栏豺,使用external_auth每次都是需要密碼的彬碱,這樣多麻煩,這里引入了Token奥洼,它會保存一串字符到在當前用戶家目錄下.salt_token中巷疼,在有效時間內(nèi)使用external_auth是不需要輸入密碼的,默認時間12hour溉卓,可以通過master配置文件修改
salt -T -a pam '*' test.ping
target
target也就是目標,目的.指定master命令應該對誰執(zhí)行
- 正則匹配
[root@master /]# salt -E 'mini*' test.ping
minion-02:
True
minion-01:
True
- 列表匹配
[root@master ~]# salt -L minion-01,minion-02 test.ping
minion-02:
True
minion-01:
True
- grains匹配
[root@master ~]# salt -G 'os:CentOs' test.ping
minion-02:
True
minion-01:
True
- 組匹配
#開啟master 的default_include
vim /etc/salt/master.d/nodegroup.conf
#寫到master中也是這個格式
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
[root@master ~]# salt -N nodegroups test.ping
minion-02:
True
minion-01:
True
#組需要在master中預先定義
- 復合匹配
salt -C 'G@os:MacOS or L@Minion1'
- Pillar匹配
salt -I 'key:value' test.ping
- CIDR匹配
salt -S '192.168.1.0/24' test.ping
在top文件中匹配 grains
'node_type:web':
- match: grain #沒有s
- webserver
top文件中使用jinja
{% set self = grains['node_type'] %}
- match: grain
- {{ self }}
- 一次在n個minion上執(zhí)行
-b n
--batch-size n
#例:
salt '*' -b 5 test.ping
#5個5個的ping
多master
2個master并不會共享Minion keys皮迟,一個master刪除了一個key不會影響另一個
不會自動同步File_roots,所以需要手動去維護,如果用git就沒問題了
不會自動同步Pillar_Roots桑寨,所以需要手工去維護伏尼,也可以用git
Master的配置文件也是獨立的
#安裝 salt-master
#原master的密鑰cp一份到新的master
scp /etc/salt/pki/master/master* newmaster:/etc/salt/pki/master/
#啟動新的Master
#修改配置minion的配置
master:
- master1
- master2
#重啟minion
#新master接受所有的key
salt-key -L
salt-key -A
YAML
語法風格
-
空格和TAB
yaml兩個空格為縮進, TAB不要使用!
-
冒號: 和減號-
: 和- 后面要跟上一個空格在寫
-
數(shù)字解析
mode: 0644 會解析成為mode: 644 最好使用mode: (0644)
-
簡寫
vim: pkg.installed #第一個簡寫 user.present #第二個簡寫.不被支持,因為不支持雙簡寫 #建議規(guī)范書寫 vim: pkg: - installed user: - present
Jinja
Jinja 基于Python模板引擎開發(fā),saltstack默認使用yaml_jinja渲染器,渲染流程時先jinja在yaml解析.所以在開始解析yaml的時候可以使用jinja
- 區(qū)分模板文件
在salt中,files和templates都使用file這個state模塊.那么如何區(qū)分模板是什么文件呢.
- templates: jinja
file.managed:
- name: /tmp/test
- source: salt://tmp/test
- template: jinja
- defaults:
Server: {{ pillar['.....'] }}
- jinja中使用grains
{{ grains['os'] }}
- jinja中使用執(zhí)行模塊
{{ salt['network.hw_addr']('eth0') }}
- jinja中使用Pillar
{{ pillar['apache']['PORT'] }}
Jinja的邏輯關(guān)系
{% if grains['os'] == 'RedHat' %}
apache: httpd
{% elif grains['os'] == 'Debian' %}
apache: apache2
{% endif %}
更多使用自行研究
salt常用模塊和API
查看支持的所有modules
[root/] ]$salt 'minion-01' sys.list_modules
minion-01:
- acl
...
salt.client調(diào)用API舉例
[root/] ]$cd /usr/lib/python2.7/site-packages/salt/modules/
模塊path
API調(diào)用示例
[root/] ]$cat test.py
#!/usr/bin/python
import salt.client
client = salt.client.LocalClient()
res = client.cmd('*','test.ping')
print res
[root/] ]$./test.py
{'minion-02': True, 'minion-01': True}
##解釋一下
#當我們調(diào)用salt.client.LocalClient的時候,其實就等于我們執(zhí)行了 salt '*' test.ping
API調(diào)用:
client.cmd('*','file.remove',['/tmp/foo'])
salt <target> sys.doc module
可以查看模塊支持那些命令
Archive
實現(xiàn)對系統(tǒng)曾經(jīng)的壓縮包調(diào)用支持gzip,gunzip.rar,tar,unrar,unzip等
#采用gunzip解壓sourcefile.txt.gz包
salt '*' archive.gunzip sourcefile.txt.gz
#采用gzip壓縮sourcefile.txt文件
salt '*' archive.gzip sourcefile.txt
API調(diào)用:
client.cmd('*','archive.gunzip',['sourcefile.txt.gz'])
cmd
實現(xiàn)對遠程命令的調(diào)用執(zhí)行,(默認具備root權(quán)限!謹慎使用)
#獲取所欲被控主機的內(nèi)存使用情況
salt '*' cmd.run 'free -m'
#在wx主機上運行test.py腳本,其中script/test.py存放在file_roots指定的目錄(默認是在/srv/salt,自定義在/etc/salt/master文件中定義)尉尾,
#該命令會做2個動作:首先同步test.py到minion的cache目錄爆阶;起床運行該腳本
salt 'minion-01' cmd.script salt://script/test.py
API調(diào)用:
client.cmd('*','cmd.run',['free -m'])
cp
實現(xiàn)遠程文件目錄的復制,以及下載URL文件等操作
#將被控主機的/etc/hosts文件復制到被控主機本地的salt cache目錄(/var/cache/salt/minion/localfiles/)
salt '*' cp.cache_local_file /etc/hosts
#將主控端file_roots指定位置下的目錄復制到被控主機/minion/目錄下
salt '*' cp.get_dir salt://script/ /minion/
#將主控端file_roots指定位置下的文件復制到被控主機/minion/test.py文件(file為文件名)
salt '*' cp.get_dir salt://script/test.py /minion/test.py
#下載URL內(nèi)容到被控主機指定位置(/tmp/index.html)
salt '*' cp.get_url http://www.slashdot.ort /tmp/index.html
API調(diào)用:
client.cmd('*','cp.get_file',['salt://script/test.py','/minion/test.py'])
cron
實現(xiàn)對minion的crontab控制
#查看指定被控主機、root用戶的crontab操作
salt 'minion-01' cron.raw_cron root
#為指定被控主機沙咏、root用戶添加/usr/local/weekly任務zuoye
salt 'minion-01' cron.set_job root '*' '*' '*' '*' 1 /usr/local/weekly
#刪除指定被控主機辨图、root用戶crontab的/usr/local/weekly任務zuoye
salt 'minion-01' cron.rm_job root /usr/local/weekly
API調(diào)用:
client.cmd('wx','cron.set_job',['root','*','*','*','*',1,'/usr/local/weekly'])
file
對minion的文件操作,包括文件讀寫,權(quán)限,查找校驗
#校驗所有被控主機/etc/fstab文件的md5值是否為xxxxxxxxxxxxx,一致則返回True值
salt '*' file.check_hash /etc/fstab md5=xxxxxxxxxxxxxxxxxxxxx
#校驗所有被控主機文件的加密信息,支持md5肢藐、sha1故河、sha224、shs256吆豹、sha384鱼的、sha512加密算法
salt '*' file.get_sum /etc/passwd md5
#修改所有被控主機/etc/passwd文件的屬組、用戶權(quán)限痘煤、等價于chown root:root /etc/passwd
salt '*' file.chown /etc/passwd root root
#復制所有被控主機/path/to/src文件到本地的/path/to/dst文件
salt '*' file.copy /path/to/src /path/to/dst
#檢查所有被控主機/etc目錄是否存在凑阶,存在則返回True,檢查文件是否存在使用file.file_exists方法
salt '*' file.directory_exists /etc
#獲取所有被控主機/etc/passwd的stats信息
salt '*' file.stats /etc/passwd
#獲取所有被控主機/etc/passwd的權(quán)限mode,如755衷快,644
salt '*' file.get_mode /etc/passwd
#修改所有被控主機/etc/passwd的權(quán)限mode為0644
salt '*' file.set_mode /etc/passwd 0644
#在所有被控主機創(chuàng)建/opt/test目錄
salt '*' file.mkdir /opt/test
#將所有被控主機/etc/httpd/httpd.conf文件的LogLevel參數(shù)的warn值修改為info
salt '*' file.sed /etc/httpd/httpd.conf 'LogLevel warn' 'LogLevel info'
#給所有被控主機的/tmp/test/test.conf文件追加內(nèi)容‘maxclient 100’
salt '*' file.append /tmp/test/test.conf 'maxclient 100'
#刪除所有被控主機的/tmp/foo文件
salt '*' file.remove /tmp/foo
network
返回minion的主機信息
#在指定被控主機獲取dig宙橱、ping、traceroute目錄域名信息
salt 'minion-01' network.dig www.qq.com
salt 'minion-01' network.ping www.qq.com
salt 'minion-01' network.traceroute www.qq.com
#獲取指定被控主機的mac地址
salt 'minion-01' network.hwaddr eth0
#檢測指定被控主機是否屬于10.0.0.0/16子網(wǎng)范圍蘸拔,屬于則返回True
salt 'minion-01' network.in_subnet 10.0.0.0/16
#獲取指定被控主機的網(wǎng)卡配置信息
salt 'minion-01' network.interfaces
#獲取指定被控主機的IP地址配置信息
salt 'minion-01' network.ip_addrs
#獲取指定被控主機的子網(wǎng)信息
salt 'minion-01' network.subnets
API調(diào)用:
client.cmd('minion-01','network.ip_addrs')
pkg
minion的程序包管理,如yum, apt-get等
#為所有被控主機安裝PHP環(huán)境师郑,根據(jù)不同系統(tǒng)發(fā)行版調(diào)用不同安裝工具進行部署,如redhat平臺的yum调窍,等價于yum -y install php
salt '*' pkg.install php
#卸載所有被控主機的PHP環(huán)境
salt '*' pkg.remove php
#升級所有被控主機的軟件包
salt '*' pkg.upgrade
API調(diào)用:
client.cmd('*','pkg.remove',['php'])
status
salt '*' status.version
API
import salt.client
client = salt.client.LocalClient()
client.cmd('*','status.uptime')
system
用來日常操作計算機
system.halt #停止正在運行的系統(tǒng)
system.init 3 #切換到字符界面呕乎,5是圖形界面
system.poweroff
system.reboot
system.shutdown
systemd(service)
service.available sshd #查看服務是否可用
service.disable <service name> #設置開機啟動的服務
service.enable <service name>
service.disabled <service name> #查看服務是不是開機啟動
service.enabled <service name>
service.get_disabled #返回所有關(guān)閉的服務
service.get_enabled #返回所有開啟的服務
service.get_all #返回所有服務
service.reload <service name> #重新載入指定的服務
service.restart <service name> #重啟服務
service.start <service name>
service.stop <service name>
service.status <service name>
service.force_reload <service name> #強制載入指定的服務
使用
[root@mail python]# salt '*' service.available sshdmonitor: True
api調(diào)用:
>>> client.cmd('*','service.available',['sshd']){'monitor': True}
grains
服務器的一些靜態(tài)信息,強調(diào)的是靜態(tài)陨晶,就是不會變的東西猬仁,比如說os是centos,不會變化先誉,除非重新安裝系統(tǒng)
grains的使用
#查詢所有g(shù)rains信息
[root@master salt]# salt 'minion-01' grains.items
minion-01:
----------
SSDs:
biosreleasedate:
09/21/2015
biosversion:
6.00
cpu_flags:
- fpu
- vme
- de
.....
#查詢grains指定項
[root@master salt]# salt '*' grains.item os
minion-02:
----------
os:
CentOS
minion-01:
----------
os:
CentOS
[root@master salt]#
[root@master salt]# salt -G 'os:CentOS' test.ping
minion-01:
True
#對系統(tǒng)是CentOS的服務器進行ping測試操作
#os:CentOS ; 就是對應上面grains.items顯示出來的os值是CentOs的對象進行匹配
#對cpu架構(gòu)是x86_64的服務器顯示CPU的個數(shù)
salt -G 'cpuarch:x86_64' grains.item num_cpus
#對字典值的對象進行匹配
salt -G 'ip_interfaces:eno16777728:192.168.2.*' test.ping
在SLS中用grains
# 在xxx.sls中使用grains
'os:CentOS':
- match: grain
- webserver
自定義grains(兩種方法)
1 . minion端修改 重啟生效
修改配置文件 /etc/salt/minion 或者寫在/etc/salt/grains中
打開 default_include: minion.d/*.conf 或者直接添加此命令
在minion端的/etc/salt/minion.d/ 目錄下新建并編輯.conf后綴文件
grains: #如果是/etc/salt/grains中,不需此行
roles:
- webserver
sex: boy #名字:值
age: #名字:多個值
- 33
- 44
# 重啟生效
[root@master ~]# salt 'minion-01' grains.item age
minion-01:
----------
age:
- 33
- 44
[root@master ~]#
**2 . minion端修改 ** 同步之后生效
base目錄(在/etc/salt/master中配置的file_roots項湿刽,默認在/srv/salt)下生成_grains 目錄,新建文件,用python來寫
編寫文件,需要返回一個字典
vim test1.py
def hello(): ##函數(shù)名字無所謂,應該是所有函數(shù)都會運行
agrain = {}
agrain['hello'] = 'lzl'
return agrain ##返回這個字典
========================
#!/usr/bin/python
# -*- coding:utf-8 -*-
import os
def file():
grains={}#初始化一個字典褐耳,
file = os.popen('ulimit -n').read()
grains['my_file']=file
return grains
#注意文件賦予權(quán)限
chmod a+x .py
#同步到各個minion中去
salt '*' saltutil.sync_all
#查看
[root/srv/salt/_grains] ]$salt 'minion-01' grains.item hello
minion-01:
----------
hello:
lzl
pillar
Pillar在salt中是非常重要的組成部分诈闺,利用它可以完成很強大的功能,它可以指定一些信息到指定的minion上铃芦,不像grains一樣是分發(fā)到所有Minion上的雅镊,它保存的數(shù)據(jù)可以是動態(tài)的,Pillar以sls來寫的襟雷,格式是鍵值
適用
1.比較敏感的數(shù)據(jù),比如密碼仁烹,key等
2.特殊數(shù)據(jù)到特定Minion上
3.動態(tài)的內(nèi)容
4.其他數(shù)據(jù)類型
pillar基本使用
查看所有
salt '*' pillar.items
查看某個
salt '*' pillar.item KEY
#可以取到更小粒度的
salt '*' pillar.get <key>:<key>
編寫pillar
指定pillar_roots
默認是/srv/pillar/(可通過修改master配置文件修改),建立目錄
top.sls
base: #指定環(huán)境
'*': #target
- test1 #引用test1.sls 或者test1/init.sls
#通過分組名匹配耸弄,
base:
group1:
- match: nodegroup #必須要有 - match: nodegroup
- webserver
#通過grain模塊匹配的示例
base:
'os:CentOS':
- match: grain #必須要有- match: grain
- webserver
test1.sls
name: test1
user: lzl
刷新 pillar數(shù)據(jù)
salt '*' saltutil.refresh_pillar
查看結(jié)果
[root/srv/pillar] ]$salt 'minion-01' pillar.items
minion-01:
----------
name:
test1
user:
lzl
[root/srv/pillar] ]$
在state中通過jinja使用pillar
默認state文件位置/src/salt/
user.sls
{% for user, uid in pillar.get('users', {}).items() %}
##pillar.get('users',{})可用pillar['users']代替,前者在沒有得到值的情況下卓缰,賦默認值
{{user}}:
user.present:
- uid: {{uid}}
{% endfor %}
jinja配合grains 指定pillar數(shù)據(jù)
{% if grains['os_family'] == 'RedHat' %}
apache: httpd
{% elif grains['os'] == 'CentOS' %}
apache: httpd
vim: vim
{% elif grains['os'] == 'Arch' %}
apache: apache
vim: vim
{% endif %}
使用salt state
它的核心是寫sls(SaLt State file)文件,sls文件默認格式是YAML格式计呈,并默認使用jinja模板,jinja是根據(jù)django的模板語言發(fā)展而來的語言征唬,簡單并強大捌显,支持for if 等循環(huán)判斷。salt state主要用來描述系統(tǒng)总寒,軟性扶歪,服務,配置文件的狀態(tài)摄闸,常常被稱為配置管理击罪!
通常state,pillar,top file會用sls文件來編寫贪薪。state文件默認是放在/srv/salt中媳禁,它與你的master配置文件中的file_roots設置有關(guān)
簡單的state文件配置&介紹
#/srv/salt/apahce.sls
apache: ##state ID,全文件唯一,如果模塊沒跟-name默認用的ID作為-name
pkg: ##模塊
#- name: apache ##函數(shù)參數(shù)画切,可以省略
- installed ##函數(shù)
service: ##模塊
- running ##函數(shù)
#- name: apache ##函數(shù)參數(shù)竣稽,這個是省略的,也可以寫上
- require: ##依賴系統(tǒng)
- pkg: apache ##表示依賴id為apache的pkg狀態(tài)
#聲明一個叫apache的狀態(tài)id,該id可以隨意霍弹,最好能表示一定意思
#pkg代表的是pkg模塊
#installed是pkg模塊下的一個函數(shù)毫别,描述的是狀態(tài),該函數(shù)表示apache是否部署典格,返回值為True或者False岛宦,為真時,表示狀態(tài)OK耍缴,否則會去滿足該狀態(tài)(下載安裝apache)砾肺,如果滿足不了會提示error,在該模塊上面省略了參數(shù)-name: apache,因為ID為apache,這些參數(shù)是模塊函數(shù)需要的(可以去查看源碼)
#service是指的service模塊
#這個模塊下主要是描述service狀態(tài)的函數(shù),running狀態(tài)函數(shù)表示apache在運行防嗡,省略-name不在表述变汪,-require表示依賴系統(tǒng),依賴系統(tǒng)是state system的重要組成部分蚁趁,在該處描述了apache服務的運行需要依賴apache軟件的部署裙盾,這里就要牽涉到sls文件的執(zhí)行,sls文件在salt中執(zhí)行時無序(如果沒有指定順序,后面會講到order)番官,假如先執(zhí)行了service這個狀態(tài)庐完,它發(fā)現(xiàn)依賴pkg包的安裝,會去先驗證pkg的狀態(tài)有沒有滿足徘熔,如果沒有依賴關(guān)系的話门躯,我們可以想象,如果沒有安裝apache近顷,apache 的service肯定運行會失敗的生音,我們來看看怎么執(zhí)行這個sls文件:
salt '*' state.sls apache
#在命令行里這樣執(zhí)行宁否,.sls不寫窒升,如果在目錄下,將目錄與文件用’.’隔開慕匠,
#如: httpd/apache.sls –> httpd.apache
#或者
salt '*' state.highstate
#前提是存在top.sls 去指定minion運行的是哪個文件
#top.sls
base:
'*':
- webserver
state.sls默認的運行環(huán)境是base環(huán)境饱须,但是它并不讀取top.sls(top.sls定義了運行環(huán)境以及需要運行的sls)
state.sls也可以指定讀取哪個環(huán)境:state.sls salt_env='prod' xxxx.sls,這個xxxx.sls可以不在top.sls中記錄台谊。
state.highstate: 這個是全局的所有環(huán)境蓉媳,以及所有狀態(tài)都生效。它會讀取每一個環(huán)境的top.sls锅铅,并且對所有sls都生效酪呻。不在top.sls文件里面記錄的sls則不會被執(zhí)行;
閱讀后寫的版本
webserver:
pkg:
- name: httpd
- installed
service:
- name: httpd
- running
- reqire:
-pkg: httpd
[root/srv/salt] ]$salt 'minion-02' state.sls webserver
minion-02:
----------
ID: webserver
Function: pkg.installed
Name: httpd
Result: True
Comment: The following packages were installed/updated: httpd
Started: 18:24:07.033564
Duration: 65091.443 ms
Changes:
----------
httpd:
----------
new:
2.4.6-45.el7.centos
old:
httpd-tools:
----------
new:
2.4.6-45.el7.centos
old:
mailcap:
----------
new:
2.1.41-2.el7
old:
----------
ID: webserver
Function: service.running
Name: httpd
Result: True
Comment: Started Service httpd
Started: 18:25:12.142495
Duration: 5599.171 ms
Changes:
----------
httpd:
True
Summary
------------
Succeeded: 2 (changed=2)
Failed: 0
------------
Total states run: 2
[root/srv/salt] ]$
較復雜的state
/srv/salt/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/init.sls 意思是當執(zhí)行 salt '*' state.sls ssh的時候其實就是執(zhí)行init.sls
#第一行:文件名,全文件唯一,如果pkg等模塊沒跟- name 包名, 默認用的ID作為-name
#第二行: 簡寫,意思pkg下的installed函數(shù)
#第三行: ID 告訴minion下載的文件應該放哪里!
#第四行:簡寫
#第八行:source是告訴minion從哪里下載源文件!
#salt://ssh/ssh_config其實就是/srv/salt/ssh/ssh_config 前面/srv/salt這個路徑和file_roots的配置有關(guān)
/srv/salt/ssh/server.sls
include:
- ssh
#include表示包含意思盐须,就是把ssh/init.sls直接包含進來
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
此時的目錄結(jié)構(gòu)應該是
├── ssh
│ ├── banner
│ ├── init.sls
│ ├── server.sls
│ ├── ssh_config
│ └── sshd_config
關(guān)于include古官網(wǎng)的demo
include:
- ssh.server
extend:
/etc/ssh/banner:
file:
- source: salt://ssh/custom-banner
#包含ssh/server.sls,擴展/etc/ssh/banner玩荠,重新其source而其它的如user,group等不變,與include一致贼邓。
include:
- apache
extend:
apache:
service:
- watch:
- pkg: mod_python
#把apache.sls包含進來阶冈,想apache-service是追加了依賴關(guān)系(watch也是依賴系統(tǒng)的函數(shù)).
關(guān)于渲染器 render system
salt默認是用的yaml_jinja渲染器處理ss文件,會優(yōu)先使用jinjia處理,然后傳給yaml處理然后生成salt需要的python數(shù)據(jù)類型.
apache/init.sls
apache:
pkg:installed:
{% if grains['os'] == 'CentoOS' %}
- name: httpd
{% endif %}
service.running:
{% if grains['os'] == 'CentoOS' %}
- name: httpd
{% endif %}
- watch:
- pkg: apache
#簡單的例子,使用jinja結(jié)合grains進行判斷
user/init.sls
{% set users = ['jerry','tom','gaga'] %}
{% for user in users %}
{{ user }}:
user.present:
- shell: /bin/bash
- home: /home/{{ user }}
{% endfor %}
---------------------------
{% 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渲染器
純python寫的sls文件.如果使用其他的渲染器,需要在文件開頭聲明,!py就是聲明用的py渲染器,
py中可用的變量有salt,grains,pillar,opts,env,sls,前三個分別對應jinja里的salt,grains,pillar,opts是minion的配置文件的字典,env對應的是環(huán)境如base,sls對應的是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'}]}}
#注意的是return的數(shù)據(jù)結(jié)構(gòu){ID: {module: [func, arg1,arg2,...,]}} 或 {ID: {module.func: [arg1,arg2,..,]}} 塑径。表示的內(nèi)容與“示例女坑;salt字典”表達的相同
state的執(zhí)行順序
stata執(zhí)行,也就是.sls文件的執(zhí)行是無序的.為了保證每次的順序是一致的,就加入了state order ,
先了解下高級數(shù)據(jù)(High Data)和低級數(shù)據(jù)(Low Data).
高級數(shù)據(jù)就是指編寫的sls文件的數(shù)據(jù)
低級數(shù)據(jù)就是經(jīng)過render和parser編譯過的數(shù)據(jù)
[root~] ]$salt 'minion-01' state.show_highstate
minion-01:
----------
webserver:
----------
__env__:
base
__sls__:
webserver
pkg:
|_
----------
name:
httpd
- installed
|_
----------
order:
10000
service:
|_
----------
name:
httpd
- running
|_
----------
-pkg:
httpd
reqire:
None
|_
----------
order:
10001
[root~] ]$salt 'minion-01' state.show_lowstate
minion-01:
|_
----------
__env__:
base
__id__:
webserver
__sls__:
webserver
fun:
installed
name:
httpd
order:
10000
state:
pkg
|_
----------
-pkg:
httpd
__env__:
base
__id__:
webserver
__sls__:
webserver
fun:
running
name:
httpd
order:
10001
reqire:
None
state:
service
[root~] ]$
查看可知,里面有個order,這個是默認salt 會自動設置,從10000開始.可通過修改master
state_auto_order: False
來關(guān)閉
order的設定
- include
被include的文件Order靠前,先執(zhí)行
- 手動定義order
httpd:
pkg:
- installed
- order: 1
#order的值越小,優(yōu)先級越高.但是-1 是最后!
- 依賴關(guān)系系統(tǒng)
就是前面使用過的 - require
依賴關(guān)系系統(tǒng) requisite system
我們已經(jīng)使用過依賴關(guān)系系統(tǒng)了,就是定義狀態(tài)和狀態(tài)之間的依賴關(guān)系,常用的函數(shù)有
require
和watch
以及他們的變種require_in
和watch-in
四者有何區(qū)別?
require,watch是指依賴,require_in,watch_in是指被依賴
watch 常用于service,而且當依賴條件發(fā)生變化的時候會執(zhí)行一些動作
/etc/httpd/httpd.conf:
file:
- managed
- source: salt://httpd/httpd.conf
pkg.installed
service:
- running
- require:
- pkg: httpd
- watch:
- file://etc/httpd/httpd.conf #當httpd.conf改變時统舀,重啟httpd服務
============================
/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多環(huán)境
針對不同的環(huán)境,應用不同state的file,比如開發(fā),測試,生產(chǎn)等.
通過修改master對不同的環(huán)境應用不通過的目錄
#官方demo
Example:
file_roots:
base:
- /srv/salt/
dev:
- /srv/salt/dev/services
- /srv/salt/dev/states
prod:
- /srv/salt/prod/services
- /srv/salt/prod/states
#file_roots 配置salt配置的存放目錄, 其中base環(huán)境是必要的, 指定top.sls存放的位置.
#默認沒指定環(huán)境時則從base目錄獲取文件
#其它則是一些自定義的, 可以通過環(huán)境變量指定.
#這樣可以邏輯上隔離一些環(huán)境配置.
#每一個環(huán)境都可以定義多個目錄, 優(yōu)先級關(guān)系由定義目錄的順序決定.
file_roots:
base:
- /srv/salt/foo
- /srv/salt/bar
#如果尋找 salt://file.sls, 如果都存在/srv/salt/foo/file.sls和/srv/salt/bar/file.sls, 則使用第一個找到的.
另一個例子
file_roots:
base:
- /srv/salt/prod
qa:
- /srv/salt/qa
- /srv/salt/prod
dev:
- /srv/salt/dev
- /srv/salt/qa
- /srv/salt/prod
#/srv/salt/prod 里的配置是在三種環(huán)境下都可以, /srv/salt/qa 只在qa和dev環(huán)境下可用, /srv/salt/dev則只在dev環(huán)境下可用.
簡答你的實施案例
#master配置
file_roots:
base:
- /home/base/
dev:
- /home/dev/
- /home/base/
#base環(huán)境
#/home/base
├── envtest.sls
└── top.sls
#cat /home/base/envtest.sls
envtest:
cmd.run:
- name: "echo '[base] env'"
#dev環(huán)境
#/home/dev/
├── mytest.sls
└── top.sls
#cat /home/dev/mytest.sls
envtest:
cmd.run:
- name: "echo '[dev] env'"
##執(zhí)行效果如下,如果不添加環(huán)境變量,則提示找不到文件
[root/srv/salt/dev] ]$salt 'minion-01' state.sls mytest test=True
minion-01:
Data failed to compile:
----------
No matching sls found for 'mytest' in env 'base'
ERROR: Minions returned with non-zero exit code
#加上環(huán)境變量執(zhí)行
[root/srv/salt/dev] ]$salt 'minion-01' state.sls mytest saltenv='dev' test=True
minion-01:
----------
ID: mytest
Function: cmd.run
Name: echo dev-env
Result: None
Comment: Command "echo dev-env" would have been executed
Started: 23:54:46.298421
Duration: 0.422 ms
Changes:
Summary
------------
Succeeded: 1 (unchanged=1)
Failed: 0
------------
Total states run: 1
[root/srv/salt/dev] ]$
salt schedule(salt中的crontab)
周期性的執(zhí)行一些函數(shù),需要注意的是: 在minion上執(zhí)行salt可執(zhí)行模塊里的函數(shù),在master執(zhí)行的是runner模塊的函數(shù).
共有三種方式:master minion pillar
- master端
- minion端
- pillar
一般而言,尤其是在minion端配置,基本不會用到的,主要還是一pillar為主
修改top.sls
#添加
- schedule
/srv/pillar/schedule.sls
schedule:
test-job:
function: cmd.run
seconds: 10
args:
- 'date >> /date.log'
#沒隔10S 在/目錄的date.log文件中記錄一條時間
salt "*" saltutil.refresh_pillar
#刷新pillar到minion
#回到minion 可以查看到
[root@minion-01 /]# ls
bin boot date.log dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@minion-01 /]# cat date.log
Fri Mar 24 02:27:40 CST 2017
Fri Mar 24 02:27:50 CST 2017
Fri Mar 24 02:28:00 CST 2017
....
salt ssh
salt-ssh 是 0.17.0 新出現(xiàn)的一個功能.對于有些不能安裝minion的機器,ssh不失為一種好的選擇但是SSH并不能取代minion,salt的有些功能不支持ssh.而且走的是SSH 并不是ZeroMQ,所以速度會有所影響
#首先安裝salt-ssh.
yum -y install salt-ssh
[root~] ]$cat /etc/salt/roster #roster文件名和路徑!
minion-01:
host: 192.168.247.153
user: root
passwd: centos
minion-02:
host: 192.168.247.154
user: root
passwd: centos
sudo: True
#如果不給passwd的話,執(zhí)行salt-ssh會提示輸入密碼
#普通用戶給sudo權(quán)限
#第一次使用記得加參數(shù) -i 否則報錯如下
[root~] ]$salt-ssh 'minion-01' test.ping
minion-01:
----------
retcode:
254
stderr:
stdout:
The host key needs to be accepted, to auto accept run salt-ssh with the -i flag:
The authenticity of host '192.168.247.153 (192.168.247.153)' can't be established.
ECDSA key fingerprint is 16:f6:f5:49:24:9c:91:da:d7:02:58:a2:14:08:e4:15.
Are you sure you want to continue connecting (yes/no)?
#第一次運行 添加-i參數(shù)
[root~] ]$salt-ssh 'minion-01' test.ping -i
minion-01:
True
[root~] ]$salt-ssh 'minion-01' test.ping
minion-01:
True
[root~] ]$
Returners
略
擴展salt
略