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]#
转载于:https://blog.51cto.com/flyingzf/1832447