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根目录
MasterTEST-ID192.168.137.7---
minionNODE1192.168.137.8webserver2/www
minionNODE2192.168.137.9webserver2/data
minionNODE3192.168.137.10web2group2/www
minionNODE4192.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 即可 具体如下:

[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的定义】

  1. 主配置文件定义

   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定义的配置过程。

  1. 定义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', {})
  1. 操作目标主机,通过-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]#