Saltstack 简单入门
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>角色ID IP组名CPU核数Nginx根目录MasterTEST-ID192.168.137.7---minionNODE1192.168.137.8webserver2/wwwminionNODE2192.168.137.9webserver2/dataminionNODE3192.168.137.10web2group2/wwwminionNODE4192.168.137.11web2group2/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 即可 具体如下:
# salt 'NODE1' test.ping
NODE1:
True
# salt '*' test.ping
NODE1:
True
NODE2:
True
#
当/etc/salt/master没有配置auto_accept: True时,需要通过salt-key命令来进行证书认证,具体操作如下:
salt-key -L显示已经或者未认证的被控端ID,Accepted Keys为已认证 Unaccepted Keys 为未认证。
salt-key -D 删除所有认证主机id证书
salt-key -d> salt-key -A 接受所有id证书请求
salt-key -a> 二:利用Saltstack远程执行命令
命令格式:salt '<操作目标>' <方法> [参数]
示例:查看被控主机的内容使用情况
salt '*' cmd.run 'free -m'
# 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
#
其中针对<操作目标>,Saltstack提供了多种方法对被控端主机(id)进行过滤。下面列举常用的具体参数。
-E,--pcre,通过正则表达式进行匹配。示例:测试web字符开头的主机ID名是否连通 命令:
salt -E '^WEB.*' test.ping 运行结果如下:
# salt -E '^web.*' test.ping
web2:
True
web1:
True
#
-L,--list以主机id名列表的形式进行过滤,格式与Python列表相似。即不同主机id名称使用逗号分隔。示例: 获取主机id名为web1、web2;获取完整的操作系统发行版名称 命令如下:
# salt -L 'web1,web2' grains.item osfullname
web1:
----------
osfullname:
CentOS
web2:
----------
osfullname:
CentOS
#
-G,--grain根据被控主机的grains(后面详述)信息匹配过滤格式为:
'<grainvalue>:<glob expression>' 例如:过滤内核为Linux的主机可以写成'kernel:Linux',如果同时需要正则表达式的支持可切换成--grain-pcre参数来执行。示例:获取主机发行版本号为6.8的Python版本号,命令:
# salt -G 'osrelease:6.8' cmd.run 'python -V'
web1:
Python 2.6.6
web2:
Python 2.6.6
#
-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被控主机的连通性,如下:
# salt -N webserver test.ping
web2:
True
web1:
True
#
-C,--compound,根据条件运算符not、and、or去匹配不通规则的主机信息,示例 探测以we开头并且操作系统版本为CentOS的主机连通性。如下:
# salt -C 'E@^we.* and G@os:CentOS' test.ping
web2:
True
web1:
True
#
其中,not语句不能作为一个条件执行,不过可以通过以下方法来规避,示例:探测非SN开头的主机连通性,命令如下:
# salt -C '* and not E@^SN.*' test.ping
web2:
True
web1:
True
#
-S,--ipcidr,根据被控主机的IP地址或IP子网进行匹配。示例:
# salt -S 192.168.0.0/16 test.ping
web1:
True
web2:
True
# salt -S 192.168.137.9 test.ping
web2:
True
#
三:Saltstack常用模块及API
Saltstack提供了非常丰富的功能模块,涉及操作系统的基础功能,常用工具支持等,更多模块信息见官网模块介绍http://docs.saltstack.com/ref/modules/all/index.html。当然 也可以通过sys模块列出当前版本支持的模块 如下:
# 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
#
接下来抽取常见的模块进行介绍,同时也会列举模块的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
#运行结果如下:
# salt 'web1' archive.gzip /etc/nginx/nginx.conf
web1:
#
#web1节点的/etc/nginx/目录如下:
# ls
conf.d koi-utfmime.typesnginx.conf.gz scgi_params win-utf
fastcgi_paramskoi-winmodules nginx.conf.rpmsaveuwsgi_params
#
API调用:
client.cmd('*','archive.gunzip',['/tmp/sourcefile.txt.gz']) 【2 cmd模块】
功能:实现远程的命令调用执行 默认具备root操作权限,使用时需要评估风险
示例:
获取所有被控主机的内存使用情况
salt '*' cmd.run "free -m"
#执行结果如下:
# salt '*' cmd.run "df -H"
web2:
Filesystem SizeUsed Avail Use% Mounted on
/dev/mapper/vg_serv-lv_root
19G 12G6.0G66% /
tmpfs 1.1G 13k1.1G 1% /dev/shm
/dev/sda1 500M 84M386M18% /boot
web1:
Filesystem SizeUsed Avail Use% Mounted on
/dev/mapper/vg_serv-lv_root
19G 12G6.0G66% /
tmpfs 1.1G 13k1.1G 1% /dev/shm
/dev/sda1 500M 84M386M18% /boot
#
在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 目录下
#执行结果如下:
# salt '*' cmd.script salt://test.sh
web1:
----------
pid:
21592
retcode:
0
stderr:
stdout:
OK...........................
web2:
----------
pid:
2663
retcode:
0
stderr:
stdout:
OK...........................
#
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目录下:
#执行结果如下:
# 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
#
将主服务器file_roots指定位置下的文件复制到被控机
salt '*' cp.get_file salt://path/to/file /mini/dest
#文件和目录同理。
下载URL内容到被控机指定位置
salt '*' cp.get_url http://www.salshdot.org /tmp/index.html
#执行结果如下:
# salt '*' cp.get_url http://www.baidu.com /tmp/index.html
web2:
/tmp/index.html
web1:
/tmp/index.html
#
API调用
client.cmd('*','cp.get_file',[' salt://path/to/file ',' /minion/dest']) 【4 cron模块】
功能:实现被控主机的crontab清单.
示例:
查看指定被控主机 root用户的crontab清单
salt 'web1' cron.raw_cron root
#执行结果如下:
# 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用户添加/usr/local/weekly任务作业
salt 'web1' cron.set_job root '*' '*' '*' '*' 1 /usr/local/weekly
#运行结果如下:
# salt 'web1' cron.set_job root '*/5' '*' '*' '*' '*' "/bin/bash /etc/viewcpu.sh" viewcpu
web1:
new
#
# web1任务如下:
# crontab -l
# Lines below here are managed by Salt, do not edit
# viewcpu
*/5 * * * * /bin/bash /etc/viewcpu.sh
#
删除指定的被控主机 root用户crontab的/usr/local/weekly任务作业
salt 'web1' cron.rm_job root /usr/local/weekly
#执行结果如下:
# salt 'web1' cron.rm_job root "/bin/bash /etc/viewcpu.sh"
web1:
removed
#
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
#运行结果如下:
# 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
#
删除指定被控主机hosts的主机配置项
salt '*' dnsutil.hosts_remove /etc/hosts ad1.yuk.com
#运行结果如下:
# salt '*' dnsutil.hosts_remove /etc/hosts www.a.com
web2:
None
web1:
None
#
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 效验所有被控主机文件的加密信息支持MD5sha1 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
#运行结果如下:
# salt '*' file.copy /etc/fstab /tmp/fstab
web1:
True
web2:
True
#
检查所有被控主机/etc目录是否存在,存在则返回True,检查文件是否存在使用file.file_exists方法
salt '*' file.directory_exists /etc
#执行结果如下:
# salt '*' file.directory_exists /etc
web1:
True
web2:
True
#
获取所有被控主机/etc/passwd的stats信息
salt '*' file.stats /etc/passwd
#运行结果如下:
# 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
#
获取所有被控主机 /etc/passwd的权限mode,如 755 644
salt '*' file.get_mode /etc/passwd
#运行结果如下:
# salt '*' file.get_mode /etc/passwd
web1:
0644
web2:
0644
#
修改所有被控主机/etc/passwd的权限为0644
salt '*' file.set_mode /etc/passwd 0644 在所有被控主机创建/opt/test目录
salt '*' file.mkdir /opt/test
#执行结果如下:
# salt '*' file.mkdir /opt/testfile
web2:
None
web1:
None
#
将所有被控主机/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
#执行结果如下:
# salt '*' file.remove /opt/test
web1:
True
web2:
True
#
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'
运行结果如下:
# salt '*' iptables.append filter INPUT rule='-m state --state RELATED,ESTABLISHE -j ACCEPT'
web2:
True
web1:
True
#
在所有被控端主机删除指定链编号为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
#运行结果如下:
# salt '*' iptables.save /etc/sysconfig/iptables
web2:
Wrote 1 lines to "/etc/sysconfig/iptables"
web1:
Wrote 1 lines to "/etc/sysconfig/iptables"
#
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
#运行结果如下:
# 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 SIZErcvd: 76
# 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
#运行结果如下:
# 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
#执行结果如下:
# salt 'web1' network.in_subnet 10.0.0.0/16
web1:
False
# salt 'web1' network.in_subnet 192.168.0.0/16
web1:
True
获取指定被控主机'web1'的网卡配置信息
salt 'web1' network.interfaces
#执行结果如下:
# 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
#
获取指定被控主机'web1' 的IP地址配置信息
salt 'web1' network.ip_addrs
#运行结果如下:
# salt 'web1' network.ip_addrs
web1:
- 192.168.137.8
#
获取指定别空主机'web1'的子网信息
salt 'web1' network.subnets
#运行结果如下:
# 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
#运行结果如下:
# 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
#运行结果如下:
# 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
#运行结果如下:
# salt '*' service.enable httpd
web1:
True
web2:
True
# salt '*' service.disable httpd
web1:
True
web2:
True
# salt '*' service.start httpd
web1:
True
web2:
True
# salt '*' service.stop httpd
web1:
True
web2:
True
# salt '*' service.status httpd
web2:
False
web1:
False
#
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'
运行结果如下:
# 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位的系统
# 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
#
获取指定主机或者所有主机的grains信息
#运行结果如下:
# 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
#
当然也可以获取主机单项grains数据 如获取操作系统发行版本,执行如下:
# salt '*' grains.item os
web2:
----------
os:
CentOS
web1:
----------
os:
CentOS
#
获取ID为 "web1"的所有grains键和值 如下:
# 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
#
【定义grains数据】
定义grains数据的方法有两种,其中一种为在被控主机定制配置文件,另一种是通过主控端扩展模块API实现,区别是模块更领廓,可以通过Python编程动态定义,而且配置文件只合适相对固定的键值 下面说明
1 被控端主机定制grains数据
SSH登录一台被控主机,如 "web1",配置文件定制的路径为/etc/salt/minion,参数为default_include:minion.d/*.conf
grains:
roles:
- webserver
- memcache
deployment: datacenter4
cabinet: 13
重启被控主机salt-minion服务,使其生效:service salt-minion restart。验证结果在主控端主机运行
salt 'web1' grains.item roles deployment cabinet
# salt 'web1' grains.item roles deployment cabine
web1:
----------
cabine:
deployment:
datacenter4
roles:
- webserver
- memcache
#
【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:
_open_file=int(getulimit)
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 为例。执行如下:
# 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
# salt 'web1' pillar.data appname flow
web1:
----------
appname:
website
flow:
----------
maxconn:
30000
maxmem:
6G
#
【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的差异。 如下代码
# 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
#
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发生变化时运行此模块。
【2state的使用】
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
#
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做了示例
# 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
#
页:
[1]