saltstack (http://www.saltstack.com) 是一個服務器基礎架構集中化管理平臺,開始於2011年的一個項目,具備配置和管理、遠程執行、監控等功能,一般可以理解成簡化版puppet(http://puppetlabs.com)和加強版的func(https://fedorahosted.org/func)。saltstack基於Python語言實現,結合輕量級消息隊列(ZeroMQ)與Python第三方模塊(Pyzmq、PyCrypto、Pyjinja2、python-msgpack和PyYAML)等構建。Saltstack具備如下特點。
1、部署簡單、方便
2、支持大部分UNIX/Linux及Windows
3、主從集中化管理
4、配置簡單、功能強大、擴張性強
5、主控端(master)和被控端(minion)基於證書認證,安全可靠。
6、支持API及自定義模塊、可通過Python輕鬆擴展。
通過部署Saltstack環境 我們可以在成千上萬臺服務器上做到批量執行名命令,根據不同的業務特性進行配置集中化管理、分發文件、採集服務器數據、操作系統基礎及軟件包管理等。因此 Saltstack是運維人員提高工作效率、規範業務配置與操作的利器。目前Saltstack已經趨向成熟。用戶羣及社區活躍度都不錯,同事官方也開放了不少子項目,具體可訪問https://github.com/saltstack 獲得。
一 :Saltstack的安裝
Saltstack的不同角色服務安裝非常簡單,建議採用yum源方式來實現部署。
1.業務環境說明:
爲了方便理解,通過虛擬化環境部署了兩組業務功能服務器進行演示。操作系統版本爲CentOS release 6.4 自帶Python2.6.6 相關服務器信息如下:(CPU核數及Nginx根目錄的差異化是爲方便生成動態配置的要求。)。
角色 | ID | IP | 組名 | CPU核數 | Nginx根目錄 |
Master | TEST-ID | 192.168.137.7 | - | - | - |
minion | NODE1 | 192.168.137.8 | webserver | 2 | /www |
minion | NODE2 | 192.168.137.9 | webserver | 2 | /data |
minion | NODE3 | 192.168.137.10 | web2group | 2 | /www |
minion | NODE4 | 192.168.137.11 | web2group | 2 | /www |
2. 安裝EPEL
由於目前RHEL官網yum源還沒有Saltstack的安裝包支持,因此現安裝EPEL作爲部署Saltstack的默認yum源。安裝過程不在詳述。
3.開始安裝。
主控端安裝。
yum install salt-master -y chkconfig salt-master on service salt-master start
被控端安裝
yum install salt-minion -y chkconfig salt-minion on service salt-minion start
4. Saltstack防火牆配置
在主控端添加TCP 4505 4506的規則,而在被控端無需配置防火牆,原理是被控直接與主控的zeromq建立長連接,接受廣播到的任務信息並執行,具體操作是添加兩條iptables 規則:
iptables -A INPUT -m state --state new -m tcp -p tcp --dport 4505 -j ACCEPT iptables -A INPUT -m state --state new -m tcp -p tcp --dport 4506 -j ACCEPT
5. 更新Saltstack配置及安裝測試
Saltstack分兩種角色,一種是master 主控端 另一種是minion 被控端 安裝完畢後需要對兩種角色的配置文件進行修改,具體如下:
主控端配置:
【/etc/salt/master】
#綁定master通信IP interface: 192.168.137.7 #自動認證,避免手動運行salt-key來確認證書信息 auto_accept: True #指定Saltstack文件根目錄位置 file_roots: base: - /srv/salt
重啓Saltstack salt-master服務器使配置生效。具體如下:
service salt-master restart
被控端配置:
【/etc/salt/minion】
#指定master主機IP master: 192.168.137.7 #修改被控端主機識別ID,建議使用操作系統名來配置 id: NODE1
重啓Saltstack salt-minion服務器使配置生效。具體如下:
service salt-minion restart
測試安裝結果。
通過test模塊的ping方法 可以確認指定被控端設備與主控端是否建立信任關係,連通性是否正常,探測所有被控端採用 '*' 來代替ID 即可 具體如下:
[root@localhost ~]# salt 'NODE1' test.ping NODE1: True [root@localhost ~]# salt '*' test.ping NODE1: True NODE2: True [root@localhost ~]#
當/etc/salt/master沒有配置auto_accept: True時,需要通過salt-key命令來進行證書認證,具體操作如下:
salt-key -L 顯示已經或者未認證的被控端ID,Accepted Keys爲已認證 Unaccepted Keys 爲未認證。
salt-key -D 刪除所有認證主機id證書
salt-key -d id, 刪除單個id證書
salt-key -A 接受所有id證書請求
salt-key -a id 接受單個id證書請求。
二:利用Saltstack遠程執行命令
命令格式:salt '<操作目標>' <方法> [參數]
示例:查看被控主機的內容使用情況
salt '*' cmd.run 'free -m'
[root@localhost ~]# salt '*' cmd.run 'free -m' NODE1: total used free shared buffers cached Mem: 1989 678 1311 0 74 276 -/+ buffers/cache: 327 1662 Swap: 2015 0 2015 NODE2: total used free shared buffers cached Mem: 1989 674 1315 0 74 276 -/+ buffers/cache: 323 1666 Swap: 2015 0 2015 [root@localhost ~]#
其中針對<操作目標>,Saltstack提供了多種方法對被控端主機(id)進行過濾。下面列舉常用的具體參數。
-E,--pcre,通過正則表達式進行匹配。示例:測試web字符開頭的主機ID名是否連通 命令:
salt -E '^WEB.*' test.ping 運行結果如下: [root@localhost ~]# salt -E '^web.*' test.ping web2: True web1: True [root@localhost ~]#
-L,--list 以主機id名列表的形式進行過濾,格式與Python列表相似。即不同主機id名稱使用逗號分隔。示例: 獲取主機id名爲web1、web2;獲取完整的操作系統發行版名稱 命令如下:
[root@localhost ~]# salt -L 'web1,web2' grains.item osfullname web1: ---------- osfullname: CentOS web2: ---------- osfullname: CentOS [root@localhost ~]#
-G,--grain 根據被控主機的grains(後面詳述)信息匹配過濾格式爲:
'<grainvalue>:<glob expression>' 例如:過濾內核爲Linux的主機可以寫成'kernel:Linux',如果同時需要正則表達式的支持可切換成--grain-pcre參數來執行。示例:獲取主機發行版本號爲6.8的Python版本號,命令:
[root@localhost ~]# salt -G 'osrelease:6.8' cmd.run 'python -V' web1: Python 2.6.6 web2: Python 2.6.6 [root@localhost ~]#
-I,--pillar,根據被控主機的pillar(後面詳述)信息進行匹配過濾,格式爲"對象名稱:對象值" 例如 過濾所有具備'apache:httpd' pillar值的主機。示例:探測具有"nginx:root: /data"信息的主機連通性 如下:
salt -I 'nginx:root:/data' test.ping
.......... ........... ............
其中pillar屬性配置文件如下:
nginx: root: /data
-N,--nodegroup 根據主控端master配置文件中的分組名稱進行過濾(主機信息支持正則表達式、grain、條件運算符等)通常根據業務類型劃分,不通業務具備相同的特點,包括部署環境,應用平臺、配置文件等。舉例分組配置信息如下:
【/etc/salt/master】
nodegroups: web1group: 'L@web1,web2' webserver: 'L@web1,web2'
其中 ,L@表示後面的主機id格式爲列表,即主機id以逗號分隔;G@表示以grain格式描述, S@表示以IP子網或者地址格式描述。
示例:探測webserver被控主機的連通性,如下:
[root@localhost ~]# salt -N webserver test.ping web2: True web1: True [root@localhost ~]#
-C,--compound,根據條件運算符not、and、or去匹配不通規則的主機信息,示例 探測以we開頭並且操作系統版本爲CentOS的主機連通性。如下:
[root@localhost ~]# salt -C 'E@^we.* and G@os:CentOS' test.ping web2: True web1: True [root@localhost ~]#
其中,not語句不能作爲一個條件執行,不過可以通過以下方法來規避,示例:探測非SN開頭的主機連通性,命令如下:
[root@localhost ~]# salt -C '* and not E@^SN.*' test.ping web2: True web1: True [root@localhost ~]#
-S,--ipcidr,根據被控主機的IP地址或IP子網進行匹配。示例:
[root@localhost ~]# salt -S 192.168.0.0/16 test.ping web1: True web2: True [root@localhost ~]# salt -S 192.168.137.9 test.ping web2: True [root@localhost ~]#
三:Saltstack常用模塊及API
Saltstack提供了非常豐富的功能模塊,涉及操作系統的基礎功能,常用工具支持等,更多模塊信息見官網模塊介紹http://docs.saltstack.com/ref/modules/all/index.html。當然 也可以通過sys模塊列出當前版本支持的模塊 如下:
[root@localhost /]# salt 'web1' sys.list_modules web1: - acl - aliases - alternatives - apache - archive - artifactory - at - blockdev - bridge - btrfs - buildout - cloud - cmd - composer - config - container_resource - cp - cron - data - defaults - devmap - dig - disk - django - dnsmasq - dnsutil - drbd - elasticsearch - environ - etcd - event - extfs - file - gem - genesis - git - grains - group - grub - hashutil - hg - hipchat - hosts - http - img - incron - ini - introspect - ip - iptables - jboss7 - jboss7_cli - key - kmod - locale - locate - logrotate - lowpkg - lvm - match - mine - modjk - mount - network - nginx - openstack_config - pagerduty - partition - pillar - pip - pkg - pkg_resource - postfix - ps - publish - pyenv - quota - raid - random - random_org - rbenv - ret - rsync - runit - rvm - s3 - saltutil - schedule - scsi - sdb - seed - serverdensity_device - service - shadow - slack - smtp - sqlite3 - ssh - state - status - supervisord - svn - sys - sysctl - syslog_ng - system - test - timezone - user - vbox_guest - virtualenv - webutil - xfs [root@localhost /]#
接下來抽取常見的模塊進行介紹,同時也會列舉模塊的API使用方法。API的原理是通過調用master client模塊,實例化一個LocalClient對象,再調用cmd()方法來實現的,一下是API實現的test.ping的示例:
import salt.client client = salt.client.LocalClient() ret = client.cmd('web1','test.ping') print ret
結果以一個標準的Python字典形式的字符串返回,可以通過eval()函數轉換成Python的字典類型,方便後續的業務邏輯處理,程序運行結果如下
{'WEB1': True}
【1 Archive模塊】
功能:實現系統層面的壓縮包調用,支持gunzip gzip rar tar unrar unzip 等
示例:
採用gunzip解壓/tmp/sourcefile.txt.gz包
salt '*' archive.gunzip /tmp/sourcefile.txt.gz
採用gzip壓縮/tmp/sourcefile.txt文件
salt '*' archive.gzip /tmp/sourcefile.txt #運行結果如下: [root@localhost ~]# salt 'web1' archive.gzip /etc/nginx/nginx.conf web1: [root@localhost ~]# #web1節點的/etc/nginx/目錄如下: [root@web1 nginx]# ls conf.d koi-utf mime.types nginx.conf.gz scgi_params win-utf fastcgi_params koi-win modules nginx.conf.rpmsave uwsgi_params [root@web1 nginx]#
API調用:
client.cmd('*','archive.gunzip',['/tmp/sourcefile.txt.gz'])
【2 cmd模塊】
功能:實現遠程的命令調用執行 默認具備root操作權限,使用時需要評估風險
示例:
獲取所有被控主機的內存使用情況
salt '*' cmd.run "free -m" #執行結果如下: [root@localhost ~]# salt '*' cmd.run "df -H" web2: Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg_serv-lv_root 19G 12G 6.0G 66% / tmpfs 1.1G 13k 1.1G 1% /dev/shm /dev/sda1 500M 84M 386M 18% /boot web1: Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg_serv-lv_root 19G 12G 6.0G 66% / tmpfs 1.1G 13k 1.1G 1% /dev/shm /dev/sda1 500M 84M 386M 18% /boot [root@localhost ~]#
在web1主機運行test.sh腳本,其中script/test.sh存放在file_roots指定的目錄,該命令會做兩個動作,首先同步test.sh到minion的cache目錄(如同步到/var/cache/salt/minion/files/base/script/test.sh);運行腳本:
salt 'web1' cmd.script salt://script/test.sh #創建 /srv/salt 目錄,把調試好的 shell 腳本 test.sh 放到 /srv/salt 目錄下 #執行結果如下: [root@localhost ~]# salt '*' cmd.script salt://test.sh web1: ---------- pid: 21592 retcode: 0 stderr: stdout: OK........................... web2: ---------- pid: 2663 retcode: 0 stderr: stdout: OK........................... [root@localhost ~]#
API調用
client.cmd('web1','cmd.run',['free -m'])
【3 cp模塊】
功能:實現遠程文件、目錄的複製、以及下載URL文件等操作
示例:
將指定被控主機的/etc/hosts文件複製到被控主機本地的salt cache目錄(/var/cache/salt/minion/localfiles)
salt '*' cp.cache_local_file /etc/hosts
將主服務器file_roots指定位置下的目錄複製到被控機
salt '*' cp.get_dir salt://path/to/dir /minion/dest #本例複製一個名爲nali的目錄,先將目錄複製到/srv/salt目錄下: #執行結果如下: [root@localhost ~]# salt '*' cp.get_dir salt://nali /etc web2: - /etc/nali/INSTALL - /etc/nali/LICENSE - /etc/nali/Makefile - /etc/nali/README - /etc/nali/bin/nali - /etc/nali/bin/nali-dig - /etc/nali/bin/nali-nslookup - /etc/nali/bin/nali-ping - /etc/nali/bin/nali-tracepath - /etc/nali/bin/nali-traceroute - /etc/nali/bin/nali-update - /etc/nali/bin/qqwrynali - /etc/nali/config.h - /etc/nali/config.mak - /etc/nali/configure - /etc/nali/libqqwry/qqwry.c - /etc/nali/libqqwry/qqwry.h - /etc/nali/nali.c - /etc/nali/share/QQWry.Dat - /etc/nali/share/nali.pl - /etc/nali/share/nali.sh web1: - /etc/nali/INSTALL - /etc/nali/LICENSE - /etc/nali/Makefile - /etc/nali/README - /etc/nali/bin/nali - /etc/nali/bin/nali-dig - /etc/nali/bin/nali-nslookup - /etc/nali/bin/nali-ping - /etc/nali/bin/nali-tracepath - /etc/nali/bin/nali-traceroute - /etc/nali/bin/nali-update - /etc/nali/bin/qqwrynali - /etc/nali/config.h - /etc/nali/config.mak - /etc/nali/configure - /etc/nali/libqqwry/qqwry.c - /etc/nali/libqqwry/qqwry.h - /etc/nali/nali.c - /etc/nali/share/QQWry.Dat - /etc/nali/share/nali.pl - /etc/nali/share/nali.sh [root@localhost ~]#
將主服務器file_roots指定位置下的文件複製到被控機
salt '*' cp.get_file salt://path/to/file /mini/dest #文件和目錄同理。
下載URL內容到被控機指定位置
salt '*' cp.get_url http://www.salshdot.org /tmp/index.html #執行結果如下: [root@localhost ~]# salt '*' cp.get_url http://www.baidu.com /tmp/index.html web2: /tmp/index.html web1: /tmp/index.html [root@localhost ~]#
API調用
client.cmd('*','cp.get_file',[' salt://path/to/file ',' /minion/dest'])
【4 cron模塊】
功能:實現被控主機的crontab清單.
示例:
查看指定被控主機 root用戶的crontab清單
salt 'web1' cron.raw_cron root #執行結果如下: [root@localhost ~]# salt 'web1' cron.raw_cron root web1: #Ansible: test_check * 5,2 * * * ls -l > /root/ll.txt #Ansible: test_checks * 5 * * * ls -l > /root/ll.txt [root@localhost ~]#
爲指定被控主機 root用戶添加/usr/local/weekly任務作業
salt 'web1' cron.set_job root '*' '*' '*' '*' 1 /usr/local/weekly #運行結果如下: [root@localhost ~]# salt 'web1' cron.set_job root '*/5' '*' '*' '*' '*' "/bin/bash /etc/viewcpu.sh" viewcpu web1: new [root@localhost ~]# # web1任務如下: [root@web1 ~]# crontab -l # Lines below here are managed by Salt, do not edit # viewcpu */5 * * * * /bin/bash /etc/viewcpu.sh [root@web1 ~]#
刪除指定的被控主機 root用戶crontab的/usr/local/weekly任務作業
salt 'web1' cron.rm_job root /usr/local/weekly #執行結果如下: [root@localhost ~]# salt 'web1' cron.rm_job root "/bin/bash /etc/viewcpu.sh" web1: removed [root@localhost ~]#
API調用
client.cmd('web1','cron.set_job',['root','*','*','*','*' 1,'/usr/local/weekly'])
【5 dnsutil模塊】
功能:實現被控主機通用DNS相關操作
示例
添加指定被控主機hosts的主機配置項
salt '*' dnsutil.hosts_append /etc/hosts 127.0.0.1 ad1.yuk.com,ad2.yuk.com #運行結果如下: [root@localhost ~]# salt '*' dnsutil.hosts_append /etc/hosts 127.0.0.1 www.a.com web1: The following line was added to /etc/hosts: 127.0.0.1 www.a.com web2: The following line was added to /etc/hosts: 127.0.0.1 www.a.com [root@localhost ~]#
刪除指定被控主機hosts的主機配置項
salt '*' dnsutil.hosts_remove /etc/hosts ad1.yuk.com #運行結果如下: [root@localhost ~]# salt '*' dnsutil.hosts_remove /etc/hosts www.a.com web2: None web1: None [root@localhost ~]#
API調用
client.cmd('*','dnsutil.hosts_append',['/etc/hosts','127.0.0.1','ad1.yuk.com'])
【6 file模塊】
功能:被控主機文件常見操作,包括文件讀寫、權限、查找、效驗等。
示例:
效驗所有被控主機/etc/fstab文件的MD5是否爲XXXXXXXXXXXXXXXXXX,一致則返回True
salt '*' file.check_hash /etc/fstab md5=XXXXXXXXXXXXXXXXXXXXXX
效驗所有被控主機文件的加密信息支持MD5 sha1 sha224 sha256 sha384 sha512如下:
salt '*' file.get_sum /etc/passwd md5
修改所後被控主機/etc/passwd文件的屬組、用戶權限、等價於 chown root:root /etc/passwd
salt '*' file.chown /etc/passwd root root
複製所有被控主機本地/path/to/src 文件到本地的
salt '*' file.copy /path/to/src /path/to/dest #運行結果如下: [root@localhost ~]# salt '*' file.copy /etc/fstab /tmp/fstab web1: True web2: True [root@localhost ~]#
檢查所有被控主機/etc目錄是否存在,存在則返回True,檢查文件是否存在使用file.file_exists方法
salt '*' file.directory_exists /etc #執行結果如下: [root@localhost ~]# salt '*' file.directory_exists /etc web1: True web2: True [root@localhost ~]#
獲取所有被控主機/etc/passwd的stats信息
salt '*' file.stats /etc/passwd #運行結果如下: [root@localhost ~]# salt 'web1' file.stats /etc/passwd web1: ---------- atime: 1469920681.98 ctime: 1469920663.82 gid: 0 group: root inode: 677190 mode: 0644 mtime: 1469461866.61 size: 1253 target: /etc/passwd type: file uid: 0 user: root [root@localhost ~]#
獲取所有被控主機 /etc/passwd的權限mode,如 755 644
salt '*' file.get_mode /etc/passwd #運行結果如下: [root@localhost ~]# salt '*' file.get_mode /etc/passwd web1: 0644 web2: 0644 [root@localhost ~]#
修改所有被控主機/etc/passwd的權限爲0644
salt '*' file.set_mode /etc/passwd 0644
在所有被控主機創建/opt/test目錄
salt '*' file.mkdir /opt/test #執行結果如下: [root@localhost ~]# salt '*' file.mkdir /opt/testfile web2: None web1: None [root@localhost ~]#
將所有被控主機/etc/httpd/httpd.conf文件的LogLevel參數的warn值修改爲info
salt '*' file.sed /etc/httpd/httpd.conf 'LogLevel warn' 'LogLevel info'
給所有被控主機的/tmp/test/test.conf文件追加內容"Maxclient 100"
salt '*' file.append /tmp/test/test.conf "maxclient 100"
刪除所有被控主機的/tmp/foo文件
salt '*' file.remove /tmp/foo #執行結果如下: [root@localhost ~]# salt '*' file.remove /opt/test web1: True web2: True [root@localhost ~]#
API調用
client.cmd('*', 'file.remove ',['/tmp/foo'])
【7 iptables模塊】
功能:被控主機iptables支持
示例:
在所有被控制端主機追加(append)、插入(insert)iptables模塊,其中INPUT爲輸入鏈,
salt '*' iptables.append filter INPUT rule='-m state --state RELATED,ESTABLISHE -j ACCEPT' salt '*' iptables.insert filter INPUT position=3 rule='-m state --state RELATED,ESTABLISHED -j ACCEPT' 運行結果如下: [root@localhost ~]# salt '*' iptables.append filter INPUT rule='-m state --state RELATED,ESTABLISHE -j ACCEPT' web2: True web1: True [root@localhost ~]#
在所有被控端主機刪除指定鏈編號爲3(position=3)或指定存在的規則
salt '*' iptables.delete filter INPUT position=3 salt '*' iptables.delete filter INPUT rule='-m state --state RELATED,ESTABLISHED -j ACCETP'
保存所有被控端主機規則到本硬盤(/etc/sysconfig/iptables)
salt '*' iptables.save /etc/sysconfig/iptables #運行結果如下: [root@localhost ~]# salt '*' iptables.save /etc/sysconfig/iptables web2: Wrote 1 lines to "/etc/sysconfig/iptables" web1: Wrote 1 lines to "/etc/sysconfig/iptables" [root@localhost ~]#
API調用:
client.cmd('web1','iptables.append',['filter','INPUT','rule=\'-p tcp --sport 80 -j ACCEPT\''])
【8 network模塊】
功能:返回被控主機網絡信息
示例:
在指定被控主機'web'獲取dig、ping 、traceroute 目錄域名信息
salt 'web1' network.dig www.qq.com salt 'web1' network.ping www.qq.com salt 'web1' network.traceroute #運行結果如下: [root@localhost ~]# salt 'web1' network.dig www.qq.com web1: ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.47.rc1.el6 <<>> www.qq.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4973 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;www.qq.com. IN A ;; ANSWER SECTION: www.qq.com. 164 IN A 59.37.96.63 www.qq.com. 164 IN A 14.17.32.211 www.qq.com. 164 IN A 14.17.42.40 ;; Query time: 27 msec ;; SERVER: 114.114.114.114#53(114.114.114.114) ;; WHEN: Sun Jul 31 07:30:06 2016 ;; MSG SIZE rcvd: 76 [root@localhost ~]# salt 'web1' network.ping www.qq.com web1: PING www.qq.com (14.17.42.40) 56(84) bytes of data. 64 bytes from 14.17.42.40: icmp_seq=1 ttl=53 time=3.94 ms 64 bytes from 14.17.42.40: icmp_seq=2 ttl=53 time=4.06 ms 64 bytes from 14.17.42.40: icmp_seq=3 ttl=53 time=7.13 ms 64 bytes from 14.17.42.40: icmp_seq=4 ttl=53 time=4.76 ms --- www.qq.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3011ms rtt min/avg/max/mdev = 3.941/4.976/7.132/1.284 ms
獲取指定被控主機'web1'的MAC地址
salt 'web1' network.hwaddr eth1 #運行結果如下: [root@localhost ~]# salt 'web1' network.hwaddr eth1 web1: 00:0c:29:7a:59:6d
檢查指定被控主機'web1'是否屬於10.0.0.0/16子網範圍 屬於則返回True
salt 'web1' network.in_subnet 10.0.0.0/16 #執行結果如下: [root@localhost ~]# salt 'web1' network.in_subnet 10.0.0.0/16 web1: False [root@localhost ~]# salt 'web1' network.in_subnet 192.168.0.0/16 web1: True
獲取指定被控主機'web1'的網卡配置信息
salt 'web1' network.interfaces #執行結果如下: [root@localhost ~]# salt 'web1' network.interfaces web1: ---------- eth1: ---------- hwaddr: 00:0c:29:7a:59:6d inet: |_ ---------- address: 192.168.137.8 broadcast: 192.168.137.255 label: eth1 netmask: 255.255.255.0 inet6: |_ ---------- address: fe80::20c:29ff:fe7a:596d prefixlen: 64 scope: link up: True lo: ---------- hwaddr: 00:00:00:00:00:00 inet: |_ ---------- address: 127.0.0.1 broadcast: None label: lo netmask: 255.0.0.0 inet6: |_ ---------- address: ::1 prefixlen: 128 scope: host up: True [root@localhost ~]#
獲取指定被控主機'web1' 的IP地址配置信息
salt 'web1' network.ip_addrs #運行結果如下: [root@localhost ~]# salt 'web1' network.ip_addrs web1: - 192.168.137.8 [root@localhost ~]#
獲取指定別空主機'web1'的子網信息
salt 'web1' network.subnets #運行結果如下: [root@localhost ~]# salt 'web1' network.subnets web1: - 192.168.137.0/24
API調用
client.cmd('web1','network.ip_addrs')
【9 pkg包管理模塊】
功能:被控主機程序包管理如 yum.apt-get等。
示例:
爲所有被控主機安裝PHP環境,根據不同系統發行版調用不同安裝工具進行部署,如REDHAT平臺的yum,等價於yum -y install php
salt '*' pkg.install php #運行結果如下: [root@weizhongke ~]# salt '*' pkg.install gd-devel web1: ---------- fontconfig-devel: ---------- new: 2.8.0-5.el6 old: freetype-devel: ---------- new: 2.3.11-17.el6 old: gd-devel: ---------- new: 2.0.35-11.el6 old: libX11-devel: ---------- new: 1.6.3-2.el6 old: libXau-devel: ---------- new: 1.0.6-4.el6 old: libXpm-devel: ---------- new: 3.5.10-2.el6 old: libjpeg-turbo-devel: ---------- new: 1.2.1-3.el6_5 old: libpng-devel: ---------- new: 2:1.2.49-2.el6_7 old: libxcb-devel: ---------- new: 1.11-2.el6 old: xorg-x11-proto-devel: ---------- new: 7.7-13.el6 old: ...........................
卸載所有被控主機的PHP環境
salt '*' pkg.remove php #運行結果如下: [root@localhost ~]# salt '*' pkg.remove php web2: ---------- web1: ----------
升級所有被控主機的軟件包
salt '*' pkg.upgrade
API調用
client.cmd('*','pkg.remove',['php'])
【10 Service服務模塊】
功能:被控主機程序包服務管理
示例:
開啓(enable)、禁用(disable) nginx開機自啓動服務
salt '*' service.enable nginx salt '*' service.disable nginx
針對nginx服務的reload、restart、start、stop、status操作
salt '*' service.reload nginx salt '*' service.restart nginx salt '*' service.start nginx salt '*' service.stop nginx salt '*' service.status nginx #運行結果如下: [root@localhost ~]# salt '*' service.enable httpd web1: True web2: True [root@localhost ~]# salt '*' service.disable httpd web1: True web2: True [root@localhost ~]# salt '*' service.start httpd web1: True web2: True [root@localhost ~]# salt '*' service.stop httpd web1: True web2: True [root@localhost ~]# salt '*' service.status httpd web2: False web1: False [root@localhost ~]#
API調用
client.cmd('*','service.stop',['nginx'])
【11其他模塊】
通過上面的10個模塊,基本上已經覆蓋日常運維操作.Saltstack還提供了user(系統用戶模塊)、group(系統組模塊)、partition(系統分區模塊)、puppet(puppet管理模塊)、system(系統重啓關機模塊)、timezone(時區管理模塊)、nginx(Nginx管理模塊)、mount(文件系統掛在模塊)、等等,更多內容見官網介紹:http://docs.saltstack.com/ref/modules/all/index.html#all-salt-modules。當然,我們也可以通過Python擴展功能來滿足要求。
【grains】組件
grains是Saltstack最重要的組件之一,grains的作用是收集被控主機的基本信息,這些信息通常都是一些靜態的數據,包括CPU、內核、操作系統、虛擬化等,在服務器端可以根據這些信息進行靈活定製,管理管可以利用這些信息對不通業務進行個性化配置。官網提供的用來區分不同操作系統的示例如下:(採用jinja模板)
{% if grains['os'] == 'Ubuntu' %} host: {{ grains['host'] }} {% elif grains['os'] == 'CentOS' %} host: {{ grains['fqdn'] }} {% endif %}
示例中CentOS發行版主機將被" host:{{ grains['fqdn'] }}" 匹配,以主機web1(CentOS 6.4)爲例,最終得到 " host:web1".同時,命令行的匹配操作系統發行版本爲CentOS的被控端可以通過-G 參數來過濾,如
salt -G 'os:CentOS' test.ping。
【grains常用操作命令】
匹配內核版本爲4.6.3的主機:
salt -G 'kernelrelease:4.6.3' cmd.run 'uname -a'
運行結果如下:
[root@localhost ~]# salt -G 'kernelrelease:4.6.3' cmd.run 'uname -a' web2: Linux web2 4.6.3 #1 SMP Wed Jun 29 06:29:23 CST 2016 x86_64 x86_64 x86_64 GNU/Linux web1: Linux web1 4.6.3 #1 SMP Wed Jun 29 06:29:23 CST 2016 x86_64 x86_64 x86_64 GNU/Linux # 過濾OS版本爲x86_64位的系統 [root@localhost ~]# salt -G 'osarch:x86_64' cmd.run 'uname -a' web2: Linux web2 4.6.3 #1 SMP Wed Jun 29 06:29:23 CST 2016 x86_64 x86_64 x86_64 GNU/Linux web1: Linux web1 4.6.3 #1 SMP Wed Jun 29 06:29:23 CST 2016 x86_64 x86_64 x86_64 GNU/Linux [root@localhost ~]#
獲取指定主機或者所有主機的grains信息
#運行結果如下: [root@localhost ~]# salt 'web1' grains.ls web1: - SSDs - biosreleasedate - biosversion - cpu_flags - cpu_model - cpuarch - domain - fqdn - fqdn_ip4 - fqdn_ip6 - gpus - host - hwaddr_interfaces - id - init - ip4_interfaces - ip6_interfaces - ip_interfaces - ipv4 - ipv6 - kernel - kernelrelease - locale_info - localhost - lsb_distrib_codename - lsb_distrib_id - lsb_distrib_release - machine_id - manufacturer - master - mdadm - mem_total - nodename - num_cpus - num_gpus - os - os_family - osarch - oscodename - osfinger - osfullname - osmajorrelease - osrelease - osrelease_info - path - productname - ps - pythonexecutable - pythonpath - pythonversion - saltpath - saltversion - saltversioninfo - selinux - serialnumber - server_id - shell - virtual - zmqversion [root@localhost ~]#
當然也可以獲取主機單項grains數據 如獲取操作系統發行版本,執行如下:
[root@localhost ~]# salt '*' grains.item os web2: ---------- os: CentOS web1: ---------- os: CentOS [root@localhost ~]#
獲取ID爲 "web1"的所有grains鍵和值 如下:
[root@localhost salt]# salt 'web1' grains.items web1: ---------- SSDs: biosreleasedate: 05/20/2014 biosversion: 6.00 cpu_flags: - fpu - vme - de - pse - tsc - msr - pae - mce - cx8 - apic - sep - mtrr - pge - mca - cmov - pat - pse36 - clflush - dts - mmx - fxsr - sse - sse2 - ss - syscall - nx - rdtscp - lm - constant_tsc - arch_perfmon - pebs - bts - nopl - xtopology - nonstop_tsc - aperfmperf - eagerfpu - pni - pclmulqdq - ssse3 - cx16 - pcid - sse4_1 - sse4_2 - x2apic - popcnt - tsc_deadline_timer - aes - xsave - avx - f16c - rdrand - hypervisor - lahf_lm - epb - fsgsbase - tsc_adjust - smep - dtherm - ida - arat - pln - pts cpu_model: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz cpuarch: x86_64 domain: gov.cn fqdn: web1.gov.cn fqdn_ip4: - 192.168.137.8 fqdn_ip6: gpus: |_ ---------- model: SVGA II Adapter vendor: unknown host: web1 hwaddr_interfaces: ---------- eth1: 00:0c:29:7a:59:6d lo: 00:00:00:00:00:00 id: web1 init: upstart ip4_interfaces: ---------- eth1: - 192.168.137.8 lo: - 127.0.0.1 ip6_interfaces: ---------- eth1: - fe80::20c:29ff:fe7a:596d lo: - ::1 ip_interfaces: ---------- eth1: - 192.168.137.8 - fe80::20c:29ff:fe7a:596d lo: - 127.0.0.1 - ::1 ipv4: - 127.0.0.1 - 192.168.137.8 ipv6: - ::1 - fe80::20c:29ff:fe7a:596d kernel: Linux kernelrelease: 4.6.3 locale_info: ---------- defaultencoding: UTF8 defaultlanguage: en_US detectedencoding: UTF-8 localhost: web1 lsb_distrib_codename: Final lsb_distrib_id: CentOS lsb_distrib_release: 6.8 machine_id: 64583632c20bdf7e7fce37f80000001f manufacturer: VMware, Inc. master: 192.168.137.7 mdadm: mem_total: 1989 nodename: web1 num_cpus: 1 num_gpus: 1 os: CentOS os_family: RedHat osarch: x86_64 oscodename: Final osfinger: CentOS-6 osfullname: CentOS osmajorrelease: 6 osrelease: 6.8 osrelease_info: - 6 - 8 path: /sbin:/usr/sbin:/bin:/usr/bin productname: VMware Virtual Platform ps: ps -efH pythonexecutable: /usr/bin/python2.6 pythonpath: - /usr/bin - /usr/lib64/python26.zip - /usr/lib64/python2.6 - /usr/lib64/python2.6/plat-linux2 - /usr/lib64/python2.6/lib-tk - /usr/lib64/python2.6/lib-old - /usr/lib64/python2.6/lib-dynload - /usr/lib64/python2.6/site-packages - /usr/lib64/python2.6/site-packages/gtk-2.0 - /usr/lib/python2.6/site-packages - /usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info pythonversion: - 2 - 6 - 6 - final - 0 saltpath: /usr/lib/python2.6/site-packages/salt saltversion: 2015.5.10 saltversioninfo: - 2015 - 5 - 10 - 0 selinux: ---------- enabled: False enforced: Disabled serialnumber: VMware-56 4d f6 e1 93 65 b0 56-00 55 6f 82 99 7a 59 6d server_id:grains: 967878355 shell: /bin/sh virtual: VMware zmqversion: 3.2.5 [root@localhost salt]#
【定義grains數據】
定義grains數據的方法有兩種,其中一種爲在被控主機定製配置文件,另一種是通過主控端擴展模塊API實現,區別是模塊更領廓,可以通過Python編程動態定義,而且配置文件只合適相對固定的鍵值 下面說明
1 被控端主機定製grains數據
SSH登錄一臺被控主機,如 "web1",配置文件定製的路徑爲/etc/salt/minion,參數爲default_include:minion.d/*.conf
[/etc/salt/minion.d/hostinfo.conf]
grains: roles: - webserver - memcache deployment: datacenter4 cabinet: 13
重啓被控主機salt-minion服務,使其生效:service salt-minion restart。驗證結果在主控端主機運行
salt 'web1' grains.item roles deployment cabinet
[root@localhost salt]# salt 'web1' grains.item roles deployment cabine web1: ---------- cabine: deployment: datacenter4 roles: - webserver - memcache [root@localhost salt]#
【2 主控端擴展模塊定製grains數據】
首先在主控端編寫Python代碼 然後將改Python文件同步到被控主機,最後刷新生效 在主控端base目錄(/srv/salt)下生成_grains目錄,執行 install -d /srv/salt/_grains開始編寫代碼,實現獲取被控主機系統允許最大打開文件數(ulimit -n)的grains數據
【/srv/salt/_grains/grains_openfile.py】
import os,sys,commands def Grains_openfile(): """ return os max open file of grains value """ grains = {} #init default value _open_file=65536 try: getulimit=commands.getstatusoutput('source /etc/profile;ulimit -n') except Exception,e: pass if getulimit[0]==0: _open_file=int(getulimit[1]) grains['max_open_file'] = _open_file return grains
代碼說明如下:
grains_openfile() 定義一個獲取最大打開文件數的函數,名稱沒有要求 符合Python的函數規則即可
grains = {} 初始化一個grains字典、變量名一定要用grains 一般Saltstack識別;
grains['max_open_file'] = _open_file 將獲取的Linux ulimit -n的結果值賦予grains['max_open_file'],其中 "max_open_file"就是grains的項 ,_open_file就是grains的值。
最後同步模塊到指定被控端主機並刷新生效,因爲grains比較合適採集靜態的數據,比如硬件、內核信息等。當有動態類的功能需求時,需要提行刷新,具體如下:
同步模塊 salt 'web1' saltutil.sync_all,看看web1主機上發生了什麼?文件已經同步到minion cache目錄中,如下:
/var/cache/salt/minion/extmods/grains/grains_openfile.py /var/cache/salt/minion/files/base/_grains/grains_openfile.py
/var/cache/salt/minion/extmods/grains 爲擴展模塊文件最終存放位置,刷新魔窟後將在同路徑下生成字節碼pyc /var/cache/salt/minion/files/base/_grains 爲臨時存放目錄。
刷新模塊 salt 'web1' sys.reload_modules, 再看看主機發生了什麼變化?在/var/cache/salt/minion/extmods/grains位置多了一個編譯後的字節碼文件 grains_openfile.pyc文件,爲Python可執行的格式
/var/cache/salt/minion/extmods/grains/grains_openfile.py /var/cache/salt/minion/extmods/grains/grains_openfile.pyc /var/cache/salt/minion/files/base/_grains/grains_openfile.py
效驗結果爲可以在主控端查看grains信息,執行 salt 'web1' grains.item max_open_file,結果顯示 "max_open_file:65535" 這個就是前面定製的主機grains信息。
web1: max_open_file: 65535
【pillar組件】
pillar也是Saltstack最重要的組件之一,其租用是定義與被控端主機相關的任何數據,定義好的數據可以被其他組件使用,如模板、API等。在pillar中定義的數據與不同業務特性的被控主機相關聯,這樣不同的被控主機只能看到自己匹配的數據,因此pillar安全性很高,使用一些比較敏感的數據,這也是區別於grains最關鍵的一點,如果定義不同業務組主機的用戶id、組id、讀寫權限、程序包等信息,定義的規範是採用Python字典形式,即 鍵/值,最上層的鍵一般爲主機的id或組名稱。下面詳細描述如何進行pillar的定義和使用。
【pillar的定義】
主配置文件定義
Saltstack默認將主控端配置文件中的所有數據都定義到pillar中,而且對所有被控主機開發,可以通過修改/etc/salt/master配置中的pillar_opts:True 或者 false 來定義是否開啓或禁用這項功能,修改後執行
salt '*' pillar.data 來觀察效果。如下代碼 爲pillar_opts:True 的返回結果,以主機web1 爲例。執行如下:
[root@localhost salt]# salt 'web1' pillar.data web1: ---------- master: ---------- __role: master auth_mode: 1 auto_accept: True cache_sreqs: True cachedir: /var/cache/salt/master cli_summary: False client_acl: ---------- client_acl_blacklist: ---------- cluster_masters: cluster_mode: paranoid con_cache: False conf_file: /etc/salt/master config_dir: /etc/salt cython_enable: False daemon: True default_include: master.d/*.conf enable_gpu_grains: False enforce_mine_cache: False enumerate_proxy_minions: False environment: None event_return: event_return_blacklist: event_return_queue: 0 event_return_whitelist: ext_job_cache: ext_pillar: extension_modules: /var/cache/salt/extmods external_auth: ---------- .................省略......................
【SLS文件定義】
pillar支持在sls文件中定義數據,格式須符合YAML規範,與Saltstack的state組件十分相似,容易混淆,兩者文件的配置格式、入口文件top.sls都是一致的。下面詳細介紹pillar使用sls定義的配置過程。
定義pillar的主目錄
修改主控配置文件/etc/salt/master的pillar_roots參數,定義pillar的主目錄,格式如下:
pillar_roots: base: - /srv/pillar
同時創建pillar目錄,執行命令:install -d /srv/pillar
2.定義入口文件top.sls
入口文件的租用一般是定義pillar的數據覆蓋被控主機的有效域範圍,"*" 代表任意主機,其中包括了一個data.sls文件,具體如下:
【/srv/pillar/top.sls】 base: '*': - data 【/srv/pillar/data.sls】 appname: website flow: maxconn: 30000 maxmem: 6G
3.效驗pillar
通過查看"web1"主機的pillar數據,可以看到了多出data.sls數據項,原因是我們定義top.sls時適用"*"覆蓋了所有主機,這樣當查看web1的pillar數據時可以看到我們定義的數據。如果結果不符合預期,可嘗試刷新被控主機的pillar數據,運行 salt '*' saltutil.refresh_pillar
[root@localhost pillar]# salt 'web1' pillar.data appname flow web1: ---------- appname: website flow: ---------- maxconn: 30000 maxmem: 6G [root@localhost pillar]#
【pillar的使用】
完成pillar配置後,接下來介紹使用方法。我們可以在state、模塊文件中引用,模板格式爲:
"{{ pillar 變量}}",例如:
{{ pillar['appname'] }} #一級字典 {{ pillar['flow']['maxconn'] }} #二級字典 {{ salt['pillar.get']('flow:maxconn',{}) }}
Python API格式如下:
pillar['flow']['maxconn'] pillar.get('flow:appname', {})
操作目標主機,通過-I 選項是使用pillar來匹配被控主機:
#salt -I 'appname:website' test.ping web1: True web2: True
2 .結合grains處理數據的差異性
首先通過結合grains的id信息來區分不同的id的maxcpu的值,其次進行引用觀察的信息,延伸pillar的例子,將data.sls修改成如下形狀,其中 " if....else....endfi"爲jinja2的模塊語法,更多信息請訪問jinja2的官方語法介紹。http://jinja.pocoo.org/docs/template/。
appname: website flow: maxconn: 30000 maxmem: 6G {% if grains['id'] == 'web1' %} maxcpu: 8 {% else %} maxcpu: 4 {% endif %}
通過查看被控主機的pillar數據,可以看到maxcpu的差異。 如下代碼
[root@localhost pillar]# salt '*' pillar.data appname flow web2: ---------- appname: website flow: ---------- maxconn: 30000 maxcpu: 8 maxmem: 6G web1: ---------- appname: website flow: ---------- maxconn: 30000 maxcpu: 16 maxmem: 6G [root@localhost pillar]#
State介紹
state是Saltstack最核心的功能,通過預先定製好的sls(salt state file)文件對對被控主機進行狀態管理,支持包括程序包(pkg)、文件(file)、網絡配置(network)、系統服務(service)、系統用戶(user)等,更多狀態對象見http://docs.saltstack.com/ref/states/all/index.html。
【1 state的定義】
state的定義時通過sls文件進行描述的,支持YAML語法,定義的規則如下:
$ID:
$State:
- $state: states
其中:
$ID : 定義state的名稱,通常採用與描述的對象保持一致的方法,如Apache,nginx等
$State:須管理對象的類型,詳見http://docs.saltstack.com/ref/states/all/index.html;
$state:states 定製對象的狀態。
官網提供的示例如下:
1 apache: 2 pkg: 3 - installed 4 service: 5 - running 6 - require: 7 - pkg: apache
上述代碼檢查Apache軟件包是否已經安裝狀態,如果未安裝,將通過yum或apt進行安裝;檢查服務Apache的進程是否處於運行狀態。下面進行進行說明:
第1行用戶定義state的名稱,此示例爲Apache,當然也可以取其他相關的名稱。
第2和4行表示state聲明的開始,使用pkg和service這兩個狀態對象。pkg使用系統本地的軟件包管理器(yum或apt)管理將要安裝的軟件,service管理系統守護進程。
第3和5行是要執行的方法,這些方法定義了Apache軟件包和服務目標狀態,此示例要求軟件包應當處於已安裝狀態,服務器必須運行,如未安裝將會被安裝並啓動。
第6行是關鍵字require,它確保了Apache服務只有在成功安裝軟件包後纔會啓動。
注意: require:在運行此state前,先運行依賴的state關係檢查,可以配置多個state依賴對象;watch: 在檢查某個state發生變化時運行此模塊。
【2 state的使用】
state的入口文件與pillar一樣,文件名都是top.sls,但state要求sls文件必須放在Saltstack base定義的目錄下,默認爲/src/salt。state描述配置.sls支持jinjia模板、grains及pillar引用等,在state的邏輯層次定義完成後,再通過salt '*' state.highstate 執行生效。下面擴展定義的範例,結合grains 與pillar 實現一個根據不同操作系統類型部署Apache環境的任務。
1 定義pillar
【/srv/pillar/top.sls】
base: '*': - apache
在top.sls中引用二級配置有兩種方式:一種是直接引用,如本示例中直接引用apache.sls 另外一種是創建Apache目錄,在引用目錄中的init.sls文件,兩者效果是一樣的。爲了規範期間,建議採用二級配置形式,同理 state的top.sls也採用如此方式。
mkdir /srv/pillar/apache #[/srv/pillar/apache/init.sls] pkgs: {% if grains['os_family'] == 'Debian' %} apache:apache2 {% elif grains['os_family'] == 'RedHat' %} apache:httpd {% elif grains['os'] == 'Arch' %} apache:apache {% endif %}
測試pillar數據,執行salt '*' pillar.data pkgs 結果返回一下信息,說明配置已生效。
web1: ---------- pkgs: ---------- apache: httpd
定義state
【/srv/salt/top.sls】
base: '*': - apache
【/srv/salt/apcahe/init.sls】
apache: pkg: - installed - name: {{ pillar['pkgs']['apache'] }} service.running: - name: {{ pillar['pkgs']['apache'] }} - require: - pkg: {{ pillar['pkgs']['apache'] }}
在配置中,{{ pillar['pkgs']['apahce'] }}將引用匹配到操作系統發行本版對應的pillar數據,本例的環境爲CentOS,故將匹配爲httpd,檢查目標主機是否已經安裝,沒有則進行安裝 (yum -y install httpd) 同時檢查Apache服務是否已經啓動,沒有則啓動(/etc/init.d/httpd start)
3 執行state及返回結果信息 如下代碼 用vsftpd做了示例
[root@localhost pillar]# salt '*' state.highstate web1: ---------- ID: vsftpd Function: pkg.installed Name: vsftpd Result: True Comment: The following packages were installed/updated: vsftpd Started: 22:47:51.599478 Duration: 16282.604 ms Changes: ---------- vsftpd: ---------- new: 2.2.2-21.el6 old: ---------- ID: vsftpd Function: service.running Name: vsftpd Result: True Comment: Started Service vsftpd Started: 22:48:07.892523 Duration: 275.246 ms Changes: ---------- vsftpd: True Summary ------------ Succeeded: 2 (changed=2) Failed: 0 ------------ Total states run: 2 web2: ---------- ID: vsftpd Function: pkg.installed Name: vsftpd Result: True Comment: The following packages were installed/updated: vsftpd Started: 22:47:50.835836 Duration: 19862.871 ms Changes: ---------- vsftpd: ---------- new: 2.2.2-21.el6 old: ---------- ID: vsftpd Function: service.running Name: vsftpd Result: True Comment: Started Service vsftpd Started: 22:48:10.701113 Duration: 126.012 ms Changes: ---------- vsftpd: True Summary ------------ Succeeded: 2 (changed=2) Failed: 0 ------------ Total states run: 2 [root@localhost pillar]#