hgtvf 发表于 2015-9-16 10:06:54

saltstack基础使用简版000;

  http://opsnotes.net/2014/07/02/saltstack_config/

初识salt之saltstack配置应用以及基础用法





Contents


[*]1. 实施如下:

实施如下:

一、测试是否能管理client
使用模块cmd.run 可以查看到client的ip地址
# salt '*' cmd.run 'ip a'   
salt_client1:   
lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo   
inet6 ::1/128 scope host   
valid_lft forever preferred_lft forever   
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000   
link/ether 00:0c:29:f4:4f:0b brd ff:ff:ff:ff:ff:ff
inet 192.168.100.245/24 brd 192.168.100.255 scope global eth0
inet6 fe80::20c:29ff:fef4:4f0b/64 scope link   
valid_lft forever preferred_lft forever
#   
二、查看版本   
# salt --versions-report
Salt: 2014.1.0
Python: 2.6.6 (r266:84292, Jun 18 2012, 14:18:47)
Jinja2: unknown
M2Crypto: 0.20.2
msgpack-python: 0.1.13
msgpack-pure: Not Installed
pycrypto: 2.0.1
PyYAML: 3.09
PyZMQ: 2.2.0.1
ZMQ: 3.2.4
#

  
关于salt的命令 可以用salt -h 来查看具体用法

三、简单使用salt
salt 在语句的后面加个 -t 时间,就可以做超时控制:
# salt \* cmd.run 'sleep 3; echo ok' -t 3
salt_client1:
ok
#   
salt \*代表所有的在线客户端,离线的是无法显示出来的
使用用shell来表示salt:
# salt 'salt_client1' cmd.run 'dir'
salt_client1:
anaconda-ks.cfg             install.log.syslog
epel-release-6-8.noarch.rpmrpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
install.log
#   
用正则来查看以salt开头的所有主机的目录
# salt 'salt_*'cmd.run 'dir'
salt_client1:
anaconda-ks.cfg             install.log.syslog
epel-release-6-8.noarch.rpmrpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
install.log
#   
使用正则E来查看主机
# salt -E 'salt_client*' test.ping
salt_client1:
True
salt_client2:
True
#
使用-L 来用列表方式来表示
# salt -L 'salt_client1,salt_client2' test.ping
salt_client1:
True
salt_client2:
True
#
-N 是查看组。首先我们来添加组
修改配置文件master vim /etc/salt/master
nodegroups:
salt_group1: 'L@salt_client1,salt_client2'
salt_group2: 'salt_client1'
# /etc/rc.d/init.d/salt-master restart
Stopping salt-master daemon:                              
Starting salt-master daemon:                              
#   
等一分钟 然后在查看
-N 参数
salt_client1   这里指组名
test.ping      这里指命令
# salt -N salt_group1 test.ping
salt_client1:
True
salt_client2:
True
# salt -N salt_group2 test.ping
salt_client1:
True
#   
# salt -N salt_group1 cmd.run 'hostname'
salt_client1:
salt_client1
salt_client2:
salt_client2
#   

测试所有主机是否能连接
# salt '*' test.ping
salt_client1:
True
测试salt_client1是否能连接
# salt 'salt_client1' test.ping
salt_client1:
True
#

# salt-syndic -l debug
salt '*' -b 10 test.ping
salt -G 'os:RedHat' --batch-size 25% apache.signal restart
四、使用grains 插件
grains 是salt客户端自己收集机器的相关信息,以及特称,在服务端我们可以使用-G参数来查看
使用-G来应用salt
这个参数很强大会根据用grair来指定最新的grains z这个参数和puppet里面的facter差不多
查看帮助如下:
-G, --grain         Instead of using shell globs to evaluate the target
use a grain value to identify targets, the syntax for
the target is the grain key followed by a
globexpression: "os:Arch*"

我的系统是CentOS我就输入CentOS。
# salt -G 'os:CentOS'test.ping
salt_client1:
True
#
# salt '*' grains.item os
salt_client1:
os: CentOS
#   
# salt -G 'cpuarch:x86_64' grains.item num_cpus
salt_client1:
num_cpus: 1
salt_client2:
num_cpus: 1
#
# salt '*' grains.items    查看有多少项目参数
# salt '*' grains.ls    查看有哪些参数
# salt 'salt_client1' grains.items 查看某个机器的基本信息
salt_client1:   
biosreleasedate: 07/31/2013
biosversion: 6.00
cpu_flags: fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc up arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
cpu_model: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz
cpuarch: x86_64
defaultencoding: UTF8
defaultlanguage: en_US
domain:
external_ip:
fqdn: salt_client1
fqdn_ip4:
192.168.100.245
fqdn_ip6:
gpus:
{'model': 'SVGA II Adapter', 'vendor': 'unknown'}
host: salt_client1
hwaddr_interfaces: {'lo': '00:00:00:00:00:00', 'eth0': '00:0c:29:f4:4f:0b'}
id: salt_client1
ip_interfaces: {'lo': ['127.0.0.1'], 'eth0': ['192.168.100.245']}
ipv4:
127.0.0.1
192.168.100.245
ipv6:
kernel: Linux
kernelrelease: 2.6.32-279.el6.x86_64
localhost: salt_client1
lsb_distrib_codename: Final
lsb_distrib_id: CentOS
lsb_distrib_release: 6.3
manufacturer: VMware, Inc.
master: 192.168.100.228
mem_total: 988
nodename: salt_client1
num_cpus: 1
num_gpus: 1
os: CentOS
os_family: RedHat
osarch: x86_64
oscodename: Final
osfinger: CentOS-6
osfullname: CentOS
osmajorrelease:
6
3
osrelease: 6.3
path: /sbin:/usr/sbin:/bin:/usr/bin
productname: VMware Virtual Platform
ps: ps -efH
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/lib/python2.6/site-packages
pythonversion: 2.6.6.final.0
saltpath: /usr/lib/python2.6/site-packages/salt
saltversion: 2014.1.0
saltversioninfo:
2014
1
0
serialnumber: VMware-56 4d 4b 45 d5 06 b3 89-63 e6 be 9b 64 f4 4f 0b
server_id: 21436595
shell: /bin/bash
virtual: VMware
#
五、使用salt来同步一个第一个简单的文件
# mkdir /srv/salt/base -p
# cd /srv/salt/base
# echo "test salt first file" >> first.txt
# salt 'salt_client1' cp.get_file salt://first.txt /home/first.txt
salt_client1:
/home/first.txt
#   
在客户端查看
# pwd
/home
# cat first.txt   
test salt first file
#   

# salt-run jobs.list_jobs 最近操作文件的配置
# salt-run jobs.lookup_jid 20140317113642863799后面是返回值 配合第一个一起使用
六、使用salt来查看客户端系统相关信息
查看当前是否有任务运行
# salt-run jobs.active
{}
#
查看所有的主机名
# salt '*' cmd.run hostname
salt_client1:
salt_client1
#
查看系统
# salt '*' grains.item os
salt_client1:
os: CentOS
#
查看客户端IP地址
# salt 'salt_client1' network.interfaces
salt_client1:
----------
eth0:
----------
hwaddr:
00:0c:29:f4:4f:0b
inet:
----------
- address:
192.168.100.245
- broadcast:
192.168.100.255
- label:
eth0
- netmask:
255.255.255.0
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
up:
True
#
查看硬盘
# salt 'salt_client1' disk.usage
salt_client1:
----------
/:
----------
1K-blocks:
10321208
available:
8462124
capacity:
14%
filesystem:
/dev/sda2
used:
1334796
/boot:
----------
1K-blocks:
198337
available:
159996
capacity:
15%
filesystem:
/dev/sda1
used:
28101
/dev/shm:
----------
1K-blocks:
506352
available:
506352
capacity:
0%
filesystem:
tmpfs
used:
0
/home:
----------
1K-blocks:
10321208
available:
9642808
capacity:
2%
filesystem:
/dev/sda3
used:
154112
/media:
----------
1K-blocks:
19134336
available:
4939136
capacity:
73%
filesystem:
192.168.100.249:/opt/
used:
13223232
/mnt:
----------
1K-blocks:
19134336
available:
4939136
capacity:
73%
filesystem:
192.168.100.249:/opt/CentOS
used:
13223232
#
# salt 'salt_client1' cmd.run 'df -h'
salt_client1:
Filesystem            SizeUsed Avail Use% Mounted on
/dev/sda2             9.9G1.3G8.1G14% /
tmpfs               495M   0495M   0% /dev/shm
/dev/sda1             194M   28M157M15% /boot
/dev/sda3             9.9G151M9.2G   2% /home
192.168.100.249:/opt/CentOS
19G   13G4.8G73% /mnt
192.168.100.249:/opt/
19G   13G4.8G73% /media
#

七、使用salt来管理系统软件包
安装包
# salt 'salt_client1' pkg.install telnet
salt_client1:
----------
telnet:
----------
new:
0.17-47.el6
old:
#
查看安装的包,这里安装的包指的不是用salt安装的包 而是全部的包
# salt 'salt_client1' pkg.list_pkgs
删除刚安装的包
# salt 'salt_client1' pkg.remove telnet
salt_client1:
----------
telnet:
----------
new:
sal   
old:
0.17-47.el6
#
在客户端查看
# rpm -qa | grep telnet
telnet-0.17-47.el6.x86_64
# telnet
telnet> ^C
# rpm -qa | grep telnet
#
查看repos内容:
# salt 'salt_client1' pkg.list_repos
salt_client1:
----------
source:
----------
baseurl:
file:///mnt/CentOS6.3
enabled:
1
file:
/etc/yum.repos.d/source.repo
gpgcheck:
0
name:
source
source1:
----------
baseurl:
file:///mnt/saltstack
enabled:
1
file:
/etc/yum.repos.d/source.repo
gpgcheck:
0
name:
source1
#
如果想查看所有minion的链接情况,我们可以用如下命令来查看
# salt '*' test.ping
salt_client1:
True
# salt-run manage.status
down:
up:
- salt_client1
#
删除客户端的一个用户:
# salt 'salt_client1' webutil.userdel /etc/passwd kcc
salt_client1:
- Deleting password for user kcc
#
Space-delimited arguments to the function:
# salt \* cmd.exec_code python 'import sys; print sys.version'
salt_client2:
2.6.6 (r266:84292, Jun 18 2012, 14:18:47)

salt_client1:
2.6.6 (r266:84292, Jun 18 2012, 14:18:47)

#


http://outofmemory.cn/saltstack/salt


一、关于salt简介,安装和基本配置
  转载自: 来自:http://tech.mainwise.cn/?p=438
  说明:salt是一个异构平台基础设置管理工具(虽然我们通常只用在Linux上),使用轻量级的通讯器ZMQ,用Python写成的批量管理工具,完全开源,遵守Apache2协议,与Puppet,Chef功能类似,有一个强大的远程执行命令引擎,也有一个强大的配置管理系统,通常叫做Salt State System。

  基本原理:
  SaltStack 采用 C/S模式,server端就是salt的master,client端就是minion,minion与master之间通过ZeroMQ消息队列通信
  minion上线后先与master端联系,把自己的pub key发过去,这时master端通过salt-key -L命令就会看到minion的key,接受该minion-key后,也就是master与minion已经互信
  master可以发送任何指令让minion执行了,salt有很多可执行模块,比如说cmd模块,在安装minion的时候已经自带了,它们通常位于你的python库中,locate salt | grep /usr/ 可以看到salt自带的所有东西。
  这些模块是python写成的文件,里面会有好多函数,如cmd.run,当我们执行salt '*' cmd.run 'uptime'的时候,master下发任务匹配到的minion上去,minion执行模块函数,并返回结果。master监听4505和4506端口,4505对应的是ZMQ的PUB system,用来发送消息,4506对应的是REP system是来接受消息的。
  具体步骤如下


[*]  Salt stack的Master与Minion之间通过ZeroMq进行消息传递,使用了ZeroMq的发布-订阅模式,连接方式包括tcp,ipc

[*]  salt命令,将cmd.run ls命令从salt.client.LocalClient.cmd_cli发布到master,获取一个Jodid,根据jobid获取命令执行结果。

[*]  master接收到命令后,将要执行的命令发送给客户端minion。

[*]  minion从消息总线上接收到要处理的命令,交给minion._handle_aes处理

[*]  minion._handle_aes发起一个本地线程调用cmdmod执行ls命令。线程执行完ls后,调用minion._return_pub方法,将执行结果通过消息总线返回给master

[*]  master接收到客户端返回的结果,调用master._handle_aes方法,将结果写的文件中

[*]  salt.client.LocalClient.cmd_cli通过轮询获取Job执行结果,将结果输出到终端。

  安装:


[*]  安装epel源

#For RHEL 5:
rpm -Uvh http://mirror.pnl.gov/epel/5/i386/epel-release-5-4.noarch.rpm
#For RHEL 6:
rpm -Uvh http://ftp.linux.ncsu.edu/pub/epel/6/i386/epel-release-6-8.noarch.rpm
[*]  安装salt-master端,也就是服务端

yum -y install salt-master
[*]  安装salt-minion端,也就是client端

yum -y install salt-minion
  配置: 通常学习环境,master用默认配置就好,修改Minion配置文件/etc/salt/minion

master: master_ip或master_FQDN   ##注明master的ip或者域名
id: minion_id                      ##取一个独一无二的minion名字,以方便辨认
  启动:

service salt-master start
service salt-minion start
  master接受minion的key:

salt-key -L ##查看所有minion_key
salt-key -a 'key-name' ##接受该key
或者salt-key -A      ##接受所有key
  测试:

salt '*' test.ping   ##查看在线minion
salt '*' pkg.install ftp##所有Minion安装ftp
  说明:


[*]‘*’ 代表的是target是指在那些minion上操作
[*]‘test’ ,’pkg’是一个执行模块,所有的执行模块见http://docs.saltstack.com/ref/modules/all/index.html?highlight=full%20list%20builtin
[*]‘ping’,’install’是执行模块下面的函数,同样参加上述链接查看帮助
[*]‘ftp’ 是函数的参数(arg),有的函数需要参数,有的不需要
  帮助: salt ‘‘ sys.doc ##查看所有执行模块的doc salt ‘‘ sys.doc test ##查看test模块的帮助 salt ‘*’ sys.doc test.ping ##查看test.ping函数的帮助
  执行命令:

salt '*' cmd.run 'uptime'##在所有机器上执行命令uptime
salt '*' cmd.run '--reboot--'##这类命令很危险,请不要尝试,请想办法禁止
二、salt常用命令


[*]  salt 该命令执行salt的执行模块,通常在master端运行,也是我们最常用到的命令

salt '<target>' <function>
如: salt '*' test.ping
[*]  salt-run 该命令执行runner(salt带的或者自定义的,runner以后会讲),通常在master端执行,比如经常用到的manage

salt-run
salt-run manage.status   ##查看所有minion状态
salt-run manage.down   ##查看所有没在线minion
salt-run manged.up       ##查看所有在线minion
[*]  salt-key 密钥管理,通常在master端执行

salt-key
salt-key -L            ##查看所有minion-key
salt-key -a <key-name>   ##接受某个minion-key
salt-key -d <key-name>   ##删除某个minion-key
salt-key -A            ##接受所有的minion-key
salt-key -D            ##删除所有的minion-key
[*]  salt-call 该命令通常在minion上执行,minion自己执行可执行模块,不是通过master下发job

salt-call <function>
salt-call test.ping         ##自己执行test.ping命令
salt-call cmd.run 'ifconfig'##自己执行cmd.run函数
[*]  salt-cp 分发文件到minion上,不支持目录分发,通常在master运行

salt-cp '<target>' SOURCE DEST
salt-cp '*' testfile.html /tmp
salt-cp 'test*' index.html /tmp/a.html
[*]  salt-ssh 0.17.1版本加入的salt-ssh

[*]  salt-master master运行命令

salt-master
salt-master            ##前台运行master
salt-master -d         ##后台运行master
salt-master -l debug   ##前台debug输出
[*]  salt-minion minion运行命令

salt-minion
salt-minion            ##前台运行
salt-minion -d         ##后台运行
salt-minion -l debug   ##前台debug输出
[*]  salt-syndic syndic是salt的代理,以后会说到


三、普通用户执行salt
  普通用户执行salt两种方案:1,salt ACL 2.salt external_auth
  1.ACL
  1) 设置master配置文件

    client_acl:
    monitor:
   - test*:
    - test.*
    dev:
   - service.*
    sa:
   - .*
  2) 重启Master

service salt-master restart
  3) 目录和文件权限

chmod +r /etc/salt/master
chmod +x /var/run/salt
chmod +x /var/cache/salt
  4) 测试

# su - monitor
# salt 'test*' test.ping
# exit; su - sa
# salt '*' test.ping
# salt '*' cmd.run 'uptime'
# exit;
  2.external_auth
  1) 修改master配置文件

external_auth:
  pam: monitor: – ‘test‘: – test. sa: – .* – 2) 3)与ACL相同
  4) 测试

# salt -a pam 'test*' test.ping    ##会提示输入账号密码,所以external_auth与当前用户无关
   username: monitor
       password:
# su - monitor
# salt -a pam '*' cmd.run 'uptime'
username: sa
password:
  5) 使用Token不必每次都输入账号密码,使用external_auth每次都是需要密码的,这样多麻烦,这里引入了Token,它会保存一串字符到在当前用户家目录下.salt_token中,在有效时间内使用external_auth是不需要输入密码的,默认时间12hour,可以通过master配置文件修改

# salt -T -a pam '*' test.ping
  username: sa
  password:

#salt -a pam '*' test.ping #不会提示输入密码了
四、target
  指定你的命令或者模块应用哪写Minion上
  1.globbing 默认

salt 'test*' test.ping
  2.RE 正则

salt -E 'web1-(pro|devel)' test.ping
  3.List 列表

salt -L '127.0.0.1, test*' test.ping
  4.grains

salt -G 'os:CentOS' test.ping
#查看所有grains键/值
salt 'test*' grains.items
#查看所有grains项
salt 'test*' grains.ls
查看某个grains的值
salt 'test*' grains.item num_cpus
  在top file中匹配grains

'node_type:web':
- match: grain         #没有s
- webserver
  top file中使用jinja模板

{% set self = grains['node_type'] %}
    - match: grain
- {{ self }}
  5.nodegroups 其实就是对Minion分组
  首先在master的配置文件中对其分组,推荐写到/etc/salt/master.d/中一个独立的配置文件中,比如nodegroup.conf

vim /etc/salt/master.d/nodegroup.conf
#写到master中也是这个格式,master.d中*.conf是默认动态加载的
nodegroups:
test1: 'L@test1,test2 or test3*'
test2: ‘G@os:CenOS or test2'
salt -N test1 test.ping                #-N指定groupname
在top file中使用nodegroups
'test1':
- match: nodegroup                   ##意没s
- webserver
  6.混合指定,就是将以上的混合起来用

G Grains glob G@os:Ubuntu
E PCRE Minion ID E@web\d+\.(dev|qa|prod)\.loc
P Grains PCRE P@os:(RedHat|Fedora|CentOS)
L List of minions L@minion1.example.com,minion3.domain.com or bl*.domain.com
I Pillar glob I@pdata:foobar
S Subnet/IP address S@192.168.1.0/24 or S@192.168.1.100
R Range cluster R@%foo.bar
salt -C 'G@os:CentOS and L@127.0.0.1,192.168.1.12' test.ping
  top file 指定:

'webserver* and G:CentOS or L@127.0.0.1,test1':
   - match: compound
- webserver
  7.一次在n个minion上执行

-b n
--batch-size n
示例:
salt '*' -b 5 test.ping 5个5个的ping
五、远程批量执行
  格式:

salt '<target>' <function>
  注: function是salt带的或自己写的可执行模块里面的function,自带的所有列表http://docs.saltstack.com/ref/modules/all/index.html?highlight=full%20list%20builtin 实例:

salt '*' at.at 10.10am 'uptime'
salt '*' test.ping
六、多Master
  1.在另一台机器上安装salt-master

yum -y install salt-master
  2.将原来master上的master密钥拷贝到新的master是一份

scp /etc/salt/pki/master/master* newmaster:/etc/salt/pki/master/
  3.启动新的Master

service salt-master start
  4.修改minion配置文件/etc/salt/minion设置两个master

master:
   - master1
- master2
  5.重启minion

service salt-minion restart
  6.在新的master上接受所有key

salt-key -L
salt-key -A
  注意:
  1.2个master并不会共享Minion keys,一个master删除了一个key不会影响另一个
  2.不会自动同步File_roots,所以需要手动去维护,如果用git就没问题了
  3.不会自动同步Pillar_Roots,所以需要手工去维护,也可以用git
  4.Master的配置文件也是独立的

七、pillar
  Pillar在salt中是非常重要的组成部分,利用它可以完成很强大的功能,它可以指定一些信息到指定的minion上,不像grains一样是分发到所有Minion上的,它保存的数据可以是动态的,Pillar以sls来写的,格式是键值对
  适用情景:
  1.比较敏感的数据,比如密码,key等
  2.特殊数据到特定Minion上
  3.动态的内容
  4.其他数据类型
  查看Minion的Pillar信息

salt '*' pillar.items
  查看某个Pillar值

salt '*' pillar.item <key>      #只能看到顶级的
salt '*' pillar.get <key>:<key> #可以取到更小粒度的
  编写pillar数据
  1.指定pillar_roots,默认是/srv/pillar(可通过修改master配置文件修改),建立目录

mkdir /srv/pillar
cd /srv/pillar
  2.编辑一个pillar数据文件

vim test1.sls
name: 'salt'
users:
   hadoop: 1000
redhat: 2000
ubuntu: 2001
  3.建立top file指定minion到pillar数据文件

vim top.sls
base:
   '*':
   - test1
  4.刷新Pillar数据

salt '*' saltutil.refresh_pillar
  5.测试

salt '*' pillar.get name
salt '*' pillar.item name
  在state中通过jinja使用pillar数据

vim /srv/salt/user.sls
{% for user, uid in pillar.get(’users’, {}).items() %}##pillar.get('users',{})可用pillar['users']代替,前者在没有得到值的情况下,赋默认值
{{user}}:
   user.present:
   - uid: {{uid}}
{% endfor %}
  当然也可以不使用jinja模板

vim /srv/salt/user2.sls
{{ pillar.get('name','') }}:
user.present:
   - uid: 2002
  通过jinja模板配合grains指定pillar数据

/srv/pillar/pkg.sls
pkgs:
{% if grains[’os_family’] == ’RedHat’ %}
apache: httpd
vim: vim-enhanced
{% elif grains[’os_family’] == ’Debian’ %}
apache: apache2
vim: vim
{% elif grains[’os’] == ’Arch’ %}
apache: apache
vim: vim
{% endif %}
八、grains
  服务器的一些静态信息,这里强调的是静态,就是不会变的东西,比如说os是centos,如果不会变化,除非重新安装系统
  定义minion的grains可以写在/etc/salt/minion中格式如下

grains:
roles:
   - webserver
   - memcache
deployment: datacenter4
cabinet: 13
cab_u: 14-15
  或者写在/etc/salt/grains中,格式如下

roles:
- webserver
- memcache
deployment: datacenter4
cabinet: 13
cab_u: 14-15
  也可以在master中编写grains的模块,同步到minion中,用Python来写很简单的
  1.在/srv/salt中建立_grains目录

mkdir /srv/salt/_grains
  2.编写grains文件,需要返回一个字典

vim test1.py
def hello():                      ##函数名字无所谓,应该是所有函数都会运行
   agrain = {}
   agrain['hello'] = 'saltstack'
return agrain                   ##返回这个字典
  3.同步到各个minion中去

salt '*' saltutil.sync_grains
salt '*' saltutil.sync_all
salt '*' state.highstate
  4.验证

salt '*' grains.item hello
九、使用 salt state
  它的核心是写sls(SaLt State file)文件,sls文件默认格式是YAML格式(以后会支持XML),并默认使用jinja模板,YAML与XML类似,是一种简单的适合用来传输数据的格式,而jinja是根据django的模板语言发展而来的语言,简单并强大,支持for if 等循环判断。salt state主要用来描述系统,软性,服务,配置文件应该出于的状态,常常被称为配置管理!
  通常state,pillar,top file会用sls文件来编写。state文件默认是放在/srv/salt中,它与你的master配置文件中的file_roots设置有关
  示例: apache.sls文件内容 ##/srv/salt/apahce.sls,以后没有用绝对路径意思就是在/srv/salt下

apache:            ##state ID,全文件唯一,如果模块没跟-name默认用的ID作为-name
pkg:             ##模块
   - installed    ##函数
#- name: apache ##函数参数,可以省略
service:         ##模块
   - running      ##函数
#- name: apache ##函数参数,这个是省略的,也可以写上
   - require:   ##依赖系统
   - pkg: apache##表示依赖id为apache的pkg状态
  下面来解释上面示例的意思:
  声明一个叫apache的状态id,该id可以随意,最好能表示一定意思
  pkg代表的是pkg模块
  installed是pkg模块下的一个函数,描述的是状态,该函数表示apache是否部署,返回值为True或者False,为真时,表示状态OK,否则会去满足该状态(下载安装apache),如果满足不了会提示error,在该模块上面省略了参数-name: apache,因为ID为apache,这些参数是模块函数需要的(可以去查看源码)
  service是指的service模块,这个模块下主要是描述service状态的函数,running状态函数表示apache在运行,省略-name不在表述,-require表示依赖系统,依赖系统是state system的重要组成部分,在该处描述了apache服务的运行需要依赖apache软件的部署,这里就要牵涉到sls文件的执行,sls文件在salt中执行时无序(如果没有指定顺序,后面会讲到order),假如先执行了service这个状态,它发现依赖pkg包的安装,会去先验证pkg的状态有没有满足,如果没有依赖关系的话,我们可以想象,如果没有安装apache,apache 的service肯定运行会失败的,我们来看看怎么执行这个sls文件:

salt '*' state.sls apache   
  在命令行里这样执行就ok了,.sls不要写,如果在目录下,将目录与文件用’.’隔开,如: httpd/apache.sls –> httpd.apache
  或者

salt '*' state.highstate
  这需要我们配置top file执定哪个minion应用哪个状态文件
  top.sls内容

base:
'*':
   - apache
  下面我们继续看一些比较复杂的:
  ssh/init.sls文件内容

openssh-client:
pkg.installed
/etc/ssh/ssh_config:
file.managed:
   - user: root
- group: root
- mode 644
- source: salt://ssh/ssh_config
- require:
- pkg: openssh-client
  ssh/server.sls文件内容

include:
- ssh
openssh-server:
pkg.installed
sshd:
service.running:
   - require:
- pkg: openssh-client
- pkg: openssh-server
- file: /etc/ssh/banner
- file: /etc/ssh/sshd_config
/etc/ssh/sshd_config:
file.managed:
   - user: root
- group: root
- mode: 644
- source: salt://ssh/sshd_config
- require:
- pkg: openssh-server
/etc/ssh/banner:
file:
   - managed
- user: root
- group: root
- mode: 644
- source: salt://ssh/banner
- require:
- pkg: openssh-server
  ssh/init.sls,学过Python的都知道目录下面的init文件是特殊文件,它怎么特殊呢,它特殊在当我们应用目录时会应用该文件的内容,如我们执行 salt ‘*’ state.sls ssh时应用的就是init.sls文件,明白了吗?再看里面的内容,前两行我们已经看过了,是描述某个rpm包有没有安装的,第三行是ID,也可以用来表示-name,以省略-name,file.managed是file模块与函数managed的快捷写法,看server.sls下最后就知道了,managed它描述了某个文件的状态,后面跟的是managed的参数,user,group,mode你们一看就知道什么意思了,关于这个source是指从哪下载源文件,salt://ssh/sshd_config是指的从salt的文件服务器里面下载,salt文件服务器其实就是file_roots默认/srv/salt/明白了吗,所以salt://ssh/sshd_config指的就是 /srv/salt/ssh/sshd_config,出来用salt的文件服务器,也可以用http,ftp服务器。- require是依赖系统不表,以后会详细说它的。再往下是server.sls文件,include表示包含意思,就是把ssh/init.sls直接包含进来
  这时你会看到/srv/salt的目录树是:

ssh/init.sls
ssh/server.sls
ssh/banner
ssh/ssh_config
ssh/sshd_config
  下面再来看一个官方样例:
  ssh/custom-server.sls 文件内容

include:
- ssh.server
extend:
/etc/ssh/banner:
   file:
- source: salt://ssh/custom-banner
  python/mod_python.sls文件内容

include:
- apache
extend:
apache:
   service:
- watch:
   - pkg: mod_python
  首先我们include的别的文件,但是里面的内容并不是全部符合我们的要求,这时我们就需要用extend来重写部分内容,特殊的是依赖关系都是追加。custom-server.sls文件意思是包含ssh/server.sls,扩展/etc/ssh/banner,重新其source而其它的如user,group等不变,与include一致。 mode_python.sls文件意思是把apache.sls包含进来,想apache-service是追加了依赖关系(watch也是依赖系统的函数).
  常用状态配置 salt-states-master.zip

十、关于渲染器render system
  我们上面也提过salt默认的渲染器是yaml_jinja,salt处理我们的sls文件时,会先把文件用jinja2处理,然后传给ymal处理器在处理,然后生成的是salt需要的python数据类型。除了yaml_jinja还有yaml_mako,yaml_wempy,py,pydsl,我比较感兴趣的就是yaml_jinja,还有py,yaml_jinja是默认的,而py是用纯python来写的。下面来看个样例吧,
  apache/init.sls文件内容

apache:
pkg:installed:
   {% if grains['os'] == 'RedHat' %}
- name: httpd
{% endif %}
service.running:
   {% if grains['os'] == 'Redhat' %}
- name: httpd
{% endif %}
- watch:
- pkg: apache
  这个样例很简单,就是加了个判断,如果Minion的grains的os是RedHat那么apache的包名是httpd,默认是apache,我们知道在别的Linux发行版上,如ubuntu,suse他们的apache的包名就是叫apache,而在redhat系上则叫httpd,所以才有了这个判断写法,下面的service也是如此。我们着重说语法,jinja中判断,循环等标签是放在{% %}中的,通常也会有结束标签{% end** %},而变量是放在 {{ }}中的,salt,grains,pillar是salt中jinja里面的三个特殊字典,salt是包含所有salt函数对象的字典,grains是包含minion上grains的字典,pillar是包含minion上pillar的字典。
  示例:for user/init.sls文件内容

{% set users = ['jerry','tom','gaga'] %}
{% for user in users %}
{{ user }}:
user.present:
   - shell: /bin/bash
   - home: /home/{{ user }}
{% endfor %}
  示例;salt字典 user/init.sls文件内容

{% if salt['cmd.run']('uname -i') == 'x86_64' %}
hadoop:
user.present:
   - shell: /bin/bash
   - home: /home/hadoop
{% elif salt['cmd.run']('uname -i') == 'i386' %}
openstack:
user.present:
   - shell: /bin/bash
- home: /home/openstack
{% else %}
django:
user.present:
   - shell: /sbin/nologin
{% endif %}
  py渲染器 说明:py渲染器是用纯python写的sls文件,它返回的数据与yaml_jinja经过jinja处理经过yaml处理后的数据类似 ,用其他渲染器需要在sls文件头行声明用的渲染器类型,#!py就是声明用的py渲染器,py中可用的变量有salt,grains,pillar,opts,env,sls,前三个分别对应jinja里的salt,grains,pillar,opts是minion的配置文件的字典,env对应的是环境如base,sls对应的是sls的文件名
  示例: user/init.sls

#!py
import os
def run():
   '''add user hadoop'''
platform = os.popen('uname -a').read().strip()
if platform == 'x86_64':
   return {'hadoop': {'user': ['present',{'shell': '/bin/bash'}, {'home': '/home/hadoop'}]}}
elif platform == 'i386':
       return {'openstack': {'user': ['present', {'shell': '/bin/bash'}, {'home': '/home/openstack'}]}}
else:
   return {'django': {'user': ['present', {'shell': '/sbin/nologin'}]}}
  说明: 首行声明了使用py作为渲染器,导入了os模块,声明run函数,py渲染sls文件是从run函数开始的,其它的就是python的语法了,注意的是return的数据结构{ID: {module: }} 或 {ID: {module.func: }} 。表示的内容与“示例;salt字典”表达的相同

九、state的执行顺序
  以前我们说过,state的执行时无序,那个无序是指执行我们写的那个sls是无序的,正是因为那个无序,salt保证每次执行的顺序是一样的,就加入了state order,在说它之前看看High Data(高级数据?)和Low Data(低级数据?),高级数据我理解的就是我们编写sls文件的数据,低级数据就是经过render和parser编译过的数据。
  查看highdata

salt '*' state.show_highstate
  查看lowdata

salt '*' state.show_lowstate
  通过查看lowdata我们发现里面有一个字段order,因为salt默认会自动设置order,从10000开始。可以通过设置master配置文件参数state_auto_order: False来关闭
  Order的设定:
  1.include 被include的文件Order靠前,先执行
  2.手动定义order字段,如

apache:
    pkg:
- installed
- order: 1
order的数字越小越先执行从1开始,-1是最后执行
  3.依赖关系系统

十一、依赖关系系统requisite system
  前面我们已经用过了依赖关系系统,就是定义状态与状态之间的依赖关系的,经常遇到的依赖系统的函数有’require’和’watch’和它们的变种’require_in’,’watch_in’,require和watch有什么区别吗?
  1.不是所有的state都支持watch,比较常用的是service
  2.watch定义的依赖条件发生变化时会执行一些动作,如当配置文件改变时,service会重启
  示例: apache/init.sls文件内容

/etc/httpd/httpd.conf:
file:
   - managed
- source: salt://httpd/httpd.conf
httpd:
pkg:
   - installed
service:
   - running
   - require:
   - pkg: httpd
   - watch:
   - file: /etc/httpd/httpd.conf            ##当httpd.conf改变时,重启httpd服务
  require与require_in, watch与watch_in
  require,watch是指依赖,require_in,watch_in是指被依赖
  a reuire b 那么就是b require_in a
  a watch b 那么就是b watch_in a
  示例: apache/init.sls文件内容

/etc/httpd/httpd.conf:
file:
   - managed
- source: salt://httpd/httpd.conf
- watch_in:
- service: httpd
httpd:
pkg:
   - installed
- require_in:
- service: httpd
service:
   - running
十二、salt state环境
  针对不用环境,应用不同的state的file,salt支持多环境,比如开发,测试,生产等环境,我们通过修改Master配置文件对不同的环境应用不同的目录!

file_roots:
base:
   - /srv/salt/prod   ##生产环境
qa:
   - /srv/salt/qa   ##测试环境,如果没发现去prod里面找
- /srv/salt/prod
dev:
   - /srv/salt/dev    ##开发环境,如果找不到,先去qa里找,如果找不到再去prod里面找
- /srv/salt/qa
- /srv/salt/prod
/srv/salt/prod/top.sls文件内容
base:
'web*prod*':
   - webserver.foobarcom
qa:
'web*qa*':
   - webserver.foobarcom
dev:
'web*dev':
   - webserver.foobarcom
   -
  pillar的目录与file_roots无关,所以Pillar的目录默认还是/srv/salt,pillar只是Minion的一些信息,不会对系统有什么改变,所以不需要区分环境,通常base即可。
  /srv/pillar/top.sls文件内容

base:
'web*prod*':
   - webserver.prod
'web*qa*':
   - webserver.qa
'web*dev*':
   - webserver.dev
  /srv/pillar/webserver/prod.sls文件内容

webserver_role: prod
  /srv/pillar/webserver/qa.sls文件内容

webserver_role: qa
  /srv/pillar/webserver/dev文件内容

webserver_root: dev
  最后sls文件/srv/salt/prod/webserver/foobarcom.sls(该文件会被所有环境访问到)的内容:

{% if pillar.get('webserver_role', '') %}
/var/www/foobarcom:
file.recurse:
   - source: salt://webserver/src/foobarcom
- env: {{ pillar['webserver_role'] }}
- user: www
- group: www
- dir_mode: 755
- file_mode: 644
{% endif %}
  开发完成后,应用sls文件
  1.现在开发环境
  salt -I ‘webserver_role:dev’ state.sls webserver.foobarcom

十三、salt schedule
  schedule是salt中的crontab,就是周期性执行一些函数,需要注意的是在minion上执行的函数是salt的可执行模块里的函数,在master上执行的是runner模块的函数,下面看看如何设置: master是修改master配置文件/etc/salt/master:

schedule:
overstate:                  ##这个是ID,可以随意起,全文件唯一
   function: state.over      ##对于master,function就是runner
   seconds: 35               ##间隔秒数
   minutes: 30               ##间隔分数
   hours: 3                  ##间隔小时数
  这时每隔3小时30分35秒,master就会运行一个state.over这个runner
  minion的schedule定义有两种方式
  1.通过修改minion的配置文件,这种方式需要修改所有Minion的配置文件略麻烦

schedule:
highstate:
   function: state.highstate
seconds: 30
minutes: 5
hours: 1
  2.为Minion指定pillar
  /srv/pillar/schedule.sls文件内容

schedule:
highstate:
   function: state.highstate
seconds: 30
minutes: 5
hours: 1
  通过top file指定到Minion
  /srv/pillar/top.sls文件内容

base:
*:
   - schedule
十四、YAML语法风格
  1.空格和Tabs
  在YAML中不要使用Tab
  2.缩进
  YAML推荐缩进为2个空格,’:’,’-’后面缩进1个空格再写
  3.数字会解析成数字
  如mode: 0644会解析成mode: 644,可用’括住防止mode: ’0644&prime;此情况
  4.YAML不允许双简写
  vim:

pkg.installed   ##第一个简写,单一个简写没问题
user.present    ##第二个简写,加上它是不支持的
  不要偷懒写成下面这样吧。
  vim: pkg:
- installed user: – present – 5.YAML只支持ASCII
  其它字符集最好不要使用,如果非要使用用以下格式:


[*]micro: ‘\u00b5&prime;
  6.下划线_将会被删除

date: 2013_05_13--> date: 20130513
  通过’括住防止出现该问题

date: '2013_05_13'
十五、salt事件系统与反应系统 event and reacter system
  我们知道Master与Minion是基于ZMQ通信的,他们通信我们看来是消息队列,对它们来说这些消息就是一些事件,什么事件应该做什么,是salt基本已经预设好了。我们学习它的事件系统来完成一些自定义的行为,后面的反应系统就是基于事件系统的。一条消息其实就是一个事件,事件通常是一个字典数据,这个字典数据通常包含tag,这个tag是用来区分用途过滤消息的,详见绿大-https://groups.google.com/forum/#!topic/saltstack-users-cn/wXVE4ydnnzc ,让我们来看看这些事件。
  捕捉事件(listen event)
  1.下载官方给的事件捕捉程序eventlisten
  https://github.com/saltstack/salt/blob/develop/tests/eventlisten.py 打开网址,复制下载,不要直接wget
  2.运行该程序

Master: python2.6 eventlisten.py                         ##捕捉master端的event直接运行即可
Minion: python2.6 eventlisten.py -n minion <minion-id>   ##捕捉minion端的需要额外参数,minion-id是该Minion的id
  发送事件(fire event)
  Master发给minion

salt '*' event.fire "{'data': 'some message'}" "tag"   ##前面必须是字符串包住的字典,后面是tag,如果你的minion在监听event,你会看到这条event的
  Minion发给minion

salt-call event.fire_master 'some message' 'tag'##前面数据类型没有要求,后面是tag,去master那看看收到了没有
  Minion发给自己

salt-call event.fire "{'data': 'some message'}" 'tag' ##前面必须是字符串包住的字典,后面是tag
  用code来捕捉,并发送event
  捕捉事件 Master:

# python2.6
>>> import salt.utils.event
>>> event = salt.utils.event.SaltEvent('master', '/var/run/salt/master')
##master表明是在master端监听,/var/run/salt/master是你master的sock_dir
>>> data = event.get_event()
>>> print(data)       ##查看内容
>>> data = event.get_event(wait=10, tag='auth') ##wait是指timeout时间,默认5s,用tag来过滤事件,可省略
>>> print(data)               
>>> for data in event.iter_events(tag='auth'):##用迭代器一直查看事件
>>>   print(data)
Minion:
#python2.6
>>> import salt.utils.event
>>> event = salt.utils.event.SaltEvent('minion', '/var/run/salt/minion',id='minion_id')
##minion代表是在minion端监听,/var/run/salt/minion是minion端的sock_dir,minion_id是该Minion的id
>>> data = event.get_event()
>>> print(data)
>>> for data in event.iter_events(tag='auth'):##用迭代器一直查看事件
>>>   print(data)
  —————–先这样吧 发送事件:

Master:
>>> import salt.utils.event
>>> event = salt.utils.event.SaltEvent('master', '/var/run/salt/minion')
>>> event.fire_event({'hello': 'world'}, 'hello')
  —————–先这样
  反应系统(reacter system)
  反应系统是基于事件系统的,它的作用是当master收到来自minion的特殊事件后就触发某些动作,比如minion上线后发送一个init事件,master收到后,对其应用init的状态文件,minion没有反应系统,事情就是这样的。
  配置reactor
  1.修改master配置文件或者在/etc/salt/master.d/中建立reactor.conf,内容

reactor:
- 'testtag':                  ##接收到的tag
   - /srv/reactor/start.sls
- /srv/reactor/monitor.sls
- 'test1*tag':                  ##接收到的tag,支持通配符
   - /srv/reactor/other.sls

[*]2.建立reactor响应sls文件
  /srv/reacter/start.sls文件内容

{% if data['id'] == 'mysql1' %}
delete_file:
cmd.cmd.run:
   - tgt: 'G@os:CentOS'
- expr_form: compound
- arg:
- rm -rf /tmp/*
{% endif %}
  /srv/reactor/other.sls文件内容

{% if data['data']['state'] == 'refresh' %}
overstate_run:
runner.state.over
{% endif %}
  下面来解释一下这两个文件,reacter的sls文件是支持jinja的,所以第一行是通过jinja来判断,reacter的sls支持两个变量data和tag, data是接受事件的那个字典,tag就是事件的tag,所以第一行的判断就很好理解了,第二行是id,可以随意起,第三行是要运行的执行模块或者runner,如果是执行模块,以cmd.开始,如果是runner则以runner.开始,可执行模块执行需要target,所以- tat:后面跟的就是可执行模块的target,- expr_form指的target的匹配方式,- arg是只执行模块函数的参数,runner一般不需要这些。所以第一个示例相当于执行了salt -C 'G@mysql1' cmd.run 'rm -rf /tmp/*' 第二个相当于执行了 salt-run state.over

十六、salt Mine
  salt的用的词都太高明,像Grains,Pillar,Mine真心没一个合适的词去翻译,Mine是做什么的呢?Mine的作用是在静态数据和动态数据建立起一座桥梁(官方文档如是说),Mine从minon收集数据然后发送给Master,并缓存在Master端,所有Minion都可以轻易的共享到,Master通常会维护比较新的数据,如果需要维护长期数据,就要考虑retruner或外部的工作缓存了。 mine的出现是用来解决一定问题的. 在Salt的网络体系中,各个minion是毫无关系,相互独立的. 但是在实际应用中,minion之间其实是有一定关联的,比如一台机器需要获取到另一台机器的一些信息或者执行一些命令. 后来Salt加入了peer系统(http://docs.saltstack.com/ref/peer.html)使其成为可能. 但是peer系统每次使用的时候都会重新执行一遍, 显然很多不常变化的信息重复执行效率较低,性能开销较大. 所以就有了后来的mine(peer和mine的关系是我杜撰出来的,如有雷同,纯属巧合). mine系统存储在master端, minion想获取的时候, 通过mine.get获取下就可以了,简单方便
  修改minion配置文件,配置Mine

mine_functions:
network.interfaces: []
test.ping: []
mine_interval: 1
  重启Minion,在master端测试

salt '*' mine_get '*' network.interfaces
salt '*' mine_get '*' test.ping
salt 'test1' mine_get '*' test.ping    ##查看test1上能得到mine数据
十七、salt ssh
  从0.17.0开始salt加入salt ssh,salt ssh不需要在客户端安装salt-minion包了,是通过ssh协议来完成运城命令执行,状态管理等任务的。它是作为master-minion形式的补充出现的,原理是有一个花名册的文件,里面记录了各个minion的信息,ip,账号,密码,等,需要远程执行命令时,直接通过ssh来执行,速度与master-minion形式慢很多。
  使用: 1.配置/etc/salt/roster格式如下

test1:
host: 192.168.1.133
user: salt
passwd: redhat
sudo: True
port: 22
timeout: 5
test2:
host: 192.168.1.134
user: root
passwd: redhat
test3:
host: 192.168.1.135
user: sa
sudo: True
  说明: test1我们定义了所有常见的选项,test2我们用了超级用户,使用账号密码,test3我们使用普通用户,没有写密码,就是通过key来认证了,并且以sudo方式执行的,需要注意的是1.key认证用的是/etc/salt/pki/master/ssh/目录下的密钥。2.如果普通用户的话,需要有sudo权限,因为一些功能,包括test.ping都需要sudo权限。
  测试:

salt-ssh '*' test.ping
salt-ssh '*' -r 'ls /'   ##执行shell命令
salt-ssh '*' cmd.run 'ls /' ##用模块来执行也是可以的
salt-ssh '*' state.sls   ##执行状态,state.sls在0.71.0中还存在bug,0.72.0中已解决
十八、Returners
  默认所有minion返回的值都会发送到master端,我们可以看到,returner就是让Minion把返回的值发给其它地方,如redis,MySQL,或者一个文本 下面我们来自定义一个returner:
  1.建立自定义returner

mkdir -p /srv/salt/_returners;
vim mysql.py##就用官方给的例子吧,修改其中mysql的Host,user和pass
  内容见https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py
  2.建立需要的数据库
  见https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py注释里的见表语句
  3.授权其他主机用户可写该表

>grant all on salt.* to 'user_in_returner'@'%' identified by 'passwd_in_returner';
  4.同步

salt '*' saltutil.sync_all      ##同步到minion上去
  5.测试

salt '*' test.ping --return mysql    ##数据返回到mysql上去,打开mysql查看
十九、扩展salt
  通过自定义各个模块来扩展salt,常见自定义模块有:
  1.可执行模块 Execution Modules
  如我们常用的cmd.run , test.ping这样的可执行模块
  2.Grains
  扩展grains,grains是一些静态信息,可能好多我们需要的没有,我们可以通过编写grains模块自定义grains
  3.状态模块 State Module
  如我们常用的pkg.install,file.managed
  4.Returners
  我们可以自定义returner,将返回的数据发送到其他存储,只要符合固定的格式就行了
  5.Runner
  Runner是在master端快速执行的模块,自定义很方便

二十、自定义可执行模块
  所有可执行module见https://github.com/saltstack/salt/tree/develop/salt/modules,或http://docs.saltstack.com/ref/modules/all/index.html?highlight=full%20list%20builtin
  1.建立自定义模块目录,通常所有自定义模块放在该目录下

mkdir /srv/salt/_modules
  2.编写模块

vim test.py
-*- coding: utf-8 -*-
'''
support for yum of RedHat family!
'''
def __virtual__():
   '''
   Only RedHat family os can use it.
   '''
   if __grains__.get('os_family', 'unkown') == 'RedHat':
       return 'yum'
   else:
       return False

def install(rpm):
   cmd = 'yum -y install {0}'.format(rpm)
   ret = __salt__['cmd.run'](cmd)
   return ret
  说明:__virtual__函数通常用来匹配是否满足该模块的环境,如果满足return出来的字符串作为该模块的名字而不是文件名,如果return的是False代表的此模块无效,不能使用。在自定义模块中可以中__grains__是一个包含了minion 所有grains的字典,__pillar__是包含了所有Pillar的grains字典,__salt__是所有可执行函数对象的字典,通常最常使用的就是这三个变量了。再往下面是定义了函数install,在salt中一般不用’%s’ % var这种格式化形式,而是使用字符串的format方法,具体使用见百度。下面就是通过__salt__执行了cmd.run这个函数来运行yum命令,很简单吧,最后把结果返回回去。
  3.测试

salt '*' yum.install ftp##查看返回值
二十一、自定义grains
  自定义的grains也是由Python写成的,通常放在/srv/salt/_grains下,grains需要返回一个字典,__salt__,__grains__,__pillar__也是可以在grains中使用的。前面已经介绍过写简单自定义grains了,复杂就就参照https://github.com/saltstack/salt/blob/develop/salt/grains/core.py官方这个吧

二十二、自定义returner
  前面已经看过官方的mysql的returner了,今天来说说自定义returner需要注意的,来个例子吧。 /srv/salt/_returners/file.py内容

def __virtual__():
   return 'file'
def returner(ret):
   '''
   Return information to /tmp/returns.txt.
   '''
   # open a file
   result_file = '/tmp/returns.txt'
   f = open(result_file, 'a+')
   f.write(str(ret))
   f.close()
salt '*' saltutil.sync_all         ##同步模块
salt '*' test.ping --return file   ##测试
cat /tmp/returns.txt               ##在minion上查看
{'jid': '20131227153001246117', 'return': True, 'retcode': 0, 'success': True, 'fun': 'test.ping', 'id': 'test1'}
  说明: 通过这个简单的例子我们了解返回的值是个字典,字典包括的项就是上面我们看到的,以后写其它returner时,也就是把这个字典的值写到不同的地方而已。这个returner的意思就是把返回的值写到各个minion的/tmp/returns.txt中。

二十三、file state backup
  来例子看看吧。 /srv/salt/test.sls文件内容

/tmp/test.txt:
file.managed:
   - source: salt://test.txt
   - backup: minion
  其中多了一个参数backup,后面跟的值minion,意思是说这个文件在minion中备份一份,文件名带着时间戳,备份位置在/var/cache/salt/minion/file_backup
  执行并测试:

salt '*' state.sls test    ##注,多修改几次test.txt,多运行几次该state
salt '*' file.list_backups /tmp/test.txt ##这是会返回备份序号,时间,位置,大小
  回退 当文件改错后,我们可以用备份文件回退

salt '*' file.restore_backup /tmp/test.txt 2   ##回退的文件,与想要回退的序列号
  删除 删除不需要的备份文件

salt '*' file.delete_backup /tmp/test.txt 3
二十四、应用实例

saltstack 远程触发文件备份、回滚
  1、创建模块方法文件

mkdir /srv/salt/_modules
  默认没有此文件,自己生成一个
  下面的py文件自己定义,下面是我写的两个方法:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys,string,shutil
import os,tarfile
import datetime,time
tn=datetime.datetime.today()
time_now=tn.strftime("%Y-%m-%d")
data_bak='/data/databak'
data_tmp='/data/databak/tmp/%s' % time_now
com_f="%s/%s" % (data_bak,time_now)
if not os.path.exists(com_f):
   os.makedirs(com_f)
def CpFile():
   id = sys.argv
   dir = sys.argv            #传入两个变量,任务自动生成的id与要替换的文件
   filename = '%s/%s.tar' % (com_f, id)
   mode = 'w:tar'
   os.chdir(data_bak)                                                                                                                                                
   w_file=open("/tmp/tmp.list",'w')      
   w_file.write(id+" "+dir)            #记录每次备份的id与相对应的备份目录或文件的路径
   w_file.close()
   file = tarfile.open( filename, mode )
   file.add( '/tmp/tmp.list' )
   file.add( dir )   
   file.close()
   return 'ok'       #测试过程,就先让返回ok吧,之后再做判断

def RollBack():
   id = sys.argv      #想要回滚到的版本id
   if not os.path.exists(data_tmp):
          os.makedirs(data_tmp)
   filename = '%s/%s.tar' % (com_f, id)
   tar = tarfile.open("%s" % filename)
   for b in tar:
          tar.extract(b,path="%s" % data_tmp)
   tar.close()
   for line in open('%s/tmp/tmp.list' % data_tmp):
          id = line.split(" ")[:1]
          dir = line.split(" ")       #读取备份时的路径
          backup_dir='%s/%s' % (data_tmp,dir)
          os.system('\cp -rp %s %s' % (backup_dir,dir))
          return 'ok'
  2、测试:
  master上同步方法脚本到节点

salt '*' saltutil.sync_all
  然后先测试备份 方法
saltstack
    salt ‘*’ cp_bakfile.CpFile 1234/tmp/test    #id + 路径
  上节点服务器上查看,存在
  把/tmp/test下内容删除,测试回滚操作

salt '*' cp_bakfile.RollBack 1234
使用gitfs做fileserver
  用gitfs后,master会从git服务器取回文件缓存,minion不会直接联系git服务器 修改master配置文件/etc/salt/master(注:以后说master配置文件就是指该文件)

fileserver_backend:
- git
gitfs_remotes:
- git://github.com/saltstack/saltstack.git
- git://github.com/example/test1.git      ##可以多个git
- file:///root/td                         ##可以使用本地git
  需要:python的模块GitPython >= 0.3.0
  saltstack的目录结构

.
|-- bfile
|-- edit
|   `-- vim.sls
`-- top.sls
vim.sls
/tmp/a.txt:
file.managed:
   - source: salt://bfile
ftp:
pkg:
   - installed
  也可以使用git下的子目录作为文件服务器根目录

gitfs_root: somefolder/otherfolder
  也可以混合使用git和本地磁盘作为文件服务器

fileserver_backend:
- roots
- git
-
  使用ssh协议的GitFS,私钥为~/.ssh/id_rsa

gitfs_remotes:
- git+ssh://git@github.com/example/salt-states.git



http://holbrook.github.io/2013/06/25/salt_usage.html

salt的主要功能及使用
  摘要:
本文介绍Salt的主要功能和基本使用,包括minion节点的管理,批量操作,以及非常重要的配置管理。 掌握了这些内容,可以使用Salt极大提高运维的效率(事实上,Salt对于开发阶段也能提供很大的帮助,开发和运维的界限正在逐渐模糊)。



2013-06-25评论






目录


[*]1 批量操作(targeting)
[*]2 节点分组(nodegroups)
[*]3 命令编排(execution)
[*]4 节点信息(grains)
[*]5 配置管理(state)

[*]5.1 状态描述

[*]5.1.1 基本描述(yaml)
[*]5.1.2 扩展描述(jinja)
[*]5.1.3 逻辑关系


[*]5.2 保存状态
[*]5.3 状态生效(State Enforcement)
[*]5.4 更多


[*]6 小结
  Salt的介绍中提到了Salt支持变更操作、配置管理、状态监控所需的一些功能,如下图:



salt_functions
  本文详细介绍如何使用这些功能。
  如果想对Salt的功能和使用有一个初步的了解,最好参考官方文档:Salt Stack Walkthrough。

1 批量操作(targeting)
  再回顾一下前文中的例子:
  



</p>
<p># 测试连通性 salt '*' test.ping</p>
<p># 查询主机运行了多长时间 sudo salt '*' cmd.run &quot;uptime&quot;</p>
<p># 批量重启服务 salt '*' cmd.run &quot;service httpd restart&quot;</p>
<p># 让多台机器一起,使用Apache Bench进行压力测试 salt '*' cmd.run &quot;ab -n 10 -c 2 http://www.google.com/&quot;</p>
<p>
  
  上面的例子都是对多个节点进行批量操作:使用通配符"'*'"对所有注册的节点进行操作。Salt支持多种方式对节点id(minion id)进行匹配。包括:


[*]默认:通配符(globbing)
[*]E:正则表达式(Regular Expression)
[*]L:列表
[*]N: 分组(group)
[*]C:复合匹配
  先看一下通配符、正则表达式和列表的例子:
  



</p>
<p># 通配符是最常用的匹配方式。Salt使用<a href="http://docs.python.org/2/library/fnmatch.html">linux风格的通配符</a> salt '<em>' test.ping salt '</em>.example.net' test.ping salt '<em>.example.</em>' test.ping salt 'web?.example.net' test.ping salt 'web' test.ping salt 'web-' test.ping</p>
<p># 正则表达式可以适应更复杂的情况。使用<a href="http://docs.python.org/2/library/re.html#module-re">python的re模块</a>进行匹配 salt -E 'web1-(prod|devel)' test.ping</p>
<p># 最直接的方式是自己指定多个minion,即列表 salt -L 'web1,web2,web3' test.ping</p>
<p>
  
  复合匹配(Compound matchers)有点复杂,后续会在其他文章中专门介绍。
  分组匹配见本文的下一节。

2 节点分组(nodegroups)
  好吧,批量操作确实很爽。但是每次都输入匹配规则有点麻烦,对于复杂的匹配规则更是如此。 salt的 ((http://docs.saltstack.com/topics/targeting/nodegroups.html)可以将常用的匹配规则保存下来(称之为minion的分组)。批量操作是,只需要使用L标记指定要操作的group名字即可。 groups定义在master的配置文件/etc/salt/master中。
  group 的定义可以使用各种匹配规则,比如:
  



</p>
<p>group1: 'L@foo.domain.com, bar.domain.com,baz.domain.com or bl*.domain.com' group2: 'G@os:Debian and foo.domain.com'</p>
<p>
  
  同样的,使用复合匹配(Compound matchers)定义group的内容不在本文范围之内。

3 命令编排(execution)
  Salt生来就有命令编排的功能。据说,Salt最先实现的是远程执行技术,然后才添加的配置管理功能。Salt使用ZeroMQ来处理命令执行的请求和响应消息,安装配置简单,并且性能非常高。
  Salt即可以批量执行命令,也可以单机执行。通常单机执行用于测试:


[*]单机(立即)执行。 使用salt-call命令单机执行操作
[*]批量(立即)执行。最常用的操作。使用salt命令,对匹配的minion节点执行操作
  Salt可以执行的命令也可以分为两种:


[*]系统命令,使用cmd.run执行
[*]Salt模块,将常用的命令/批处理封装到内置的Salt模块(module),使用模块名.功能名的方式执行。
  比如:
  



</p>
<p># 执行系统命令 salt '*' cmd.run 'hostname'</p>
<p># 执行Salt模块 salt '*' disk.usage</p>
<p>
  
  使用Salt模块的好处是能够做到一致。比如同样是查看磁盘使用情况,salt '*' cmd.run "df -h"只能用于NIX节点,而salt '*' disk.usage对NIX和Windows都适用,并且采用相同结构返回数据,便于批量处理。
  Salt已经内置了大量的模块,这些模块涵盖了日常管理任务的主要任务,包括:


[*]通用的管理任务,比如apt, at, cp, cron, disk, extfs, file, grains, hosts, iptables, mount, network, pam, parted, pkg, ps, selinux, shadow, ssh, test等
[*]针对特定软件的任务,比如apache, cassandra, djangomod, git, mongodb, mysql, nginx, nova, postgres, solr, sqlite3, 和tomcat
  而且,自己开发Salt模块也非常简单,很容易将实际管理操作中的一些经验通过自定义的模块固化下来,并方便分享。
  在开发和调试模块的时候,可以使用test=True参数进行模拟执行(Dry run)。比如:

salt 'minion1.example.com' state.highstate -v test=True
4 节点信息(grains)
  grains是Salt内置的一个非常有用的模块。在用salt进行管理客户端的时候或者写state的时候都可以引用grains的变量。
  grains的基本使用举例如下:
  



</p>
<p># 查看grains分类 salt '*' grains.ls</p>
<p># 查看grains所有信息 salt '*' grains.items</p>
<p># 查看grains某个信息 salt '*' grains.item osrelease</p>
<p>
  

5 配置管理(state)
  配置管理是Salt中非常重要的内容之一。Salt通过内置的state模块支持配置管理所需的功能。关于这部分内容,官方文档有很详细的描述,可以参考 part 1, part 2和 part 3。
  Salt中可以定义节点的目标状态,称之为state。state对应配置管理中的配置,可以对其进行标识、变更控制、变更识别、状态报告、跟踪和归档以及审计等一些的管理行为。

5.1 状态描述
  Salt使用SLS文件(SaLt State file)描述状态。SLS使用YAML格式进行数据序列化,因此简单明了,可读性也很高。

5.1.1 基本描述(yaml)
  下边是一个简单的SLS文件例子:
  



</p>
<p>apache: pkg: - installed service: - running - require: - pkg: apache</p>
<p>
  
  该文件描述一个ID为apache的配置状态:


[*]软件包(pkg)已经安装
[*]服务应该处于运行中
[*]服务的运行依赖于apache软件包的安装
  state文件中的所有YAML变量名来自Salt的state模块。
  Salt内置了大量的state模块,比如cron, cmd, file, group, host, mount, pkg, service, ssh_auth,user等。 详细清单参考这里。
  还可以开发自己的state模块。

5.1.2 扩展描述(jinja)
  state可以使用jinja模板引擎进行扩展,其语法可以参考这里。
  下面是一个更复杂的例子:
  



</p>
<p>vim: pkg: { % if grains['os_family'] == 'RedHat' % } - name: vim-enhanced { % elif grains['os'] == 'Debian' % } - name: vim-nox { % elif grains['os'] == 'Ubuntu' % } - name: vim-nox { % endif % } - installed</p>
<p>
  
  该state增加了判断逻辑:如果是redhard系列的就安装 vim-enhanced,如果系统是Debian或者Ubuntu就安装vim-nox。

5.1.3 逻辑关系
  state之间可以有逻辑关系。常见的关系举例如下:


[*]require:依赖某个state,在运行此state前,先运行依赖的state,依赖可以有多个
  



httpd: pkg: - installed file.managed: - name: /etc/httpd/conf/httpd.conf - source: salt://httpd/httpd.conf - require: - pkg: httpd
  


[*]watch:在某个state变化时运行此模块
  



redis: pkg: - latest file.managed: - source: salt://redis/redis.conf - name: /etc/redis.conf - require: - pkg: redis service.running: - enable: True - watch: - file: /etc/redis.conf - pkg: redis
  
  watch除具备require功能外,还增了关注状态的功能


[*]order:优先级比require和watch低,有order指定的state比没有order指定的优先级高
  



vim: pkg.installed: - order: 1
  
  想让某个state最后一个运行,可以用last

5.2 保存状态
  状态描述文件(SLS)要保存在master节点中,并通过指令分发到minion节点。


[*]路径设置
  Salt master的配置文件(/etc/salt/master)中可以通过file_roots参数指定状态文件的保存路径。可以为不同的环境(如开发环境、UAT环境、生产环境、灾备环境等)分别指定路径,如下所示:
  



</p>
<p>file_roots: base: - /srv/salt/ dev: - /srv/salt/dev/services - /srv/salt/dev/states prod: - /srv/salt/prod/services - /srv/salt/prod/states</p>
<p>
  
  其中,base环境是必须的。


[*]入口文件
  file_roots中必须指定“base”环境的路径,因为该路径中存在Salt state的入口文件: top.sls。
  Top文件建立配置环境、节点和状态配置之间的映射关系。比如一个简单的top.sls文件:
  



</p>
<p>base: '<em>': - servers dev: '</em>nodb*': - mongodb</p>
<p>
  
  该文件指定了: - 所有节点使用base环境的servers配置 - nodb节点使用dev环境的mongodb配置
  结合第一部分的file_roots配置,该top配置意味存在以下的配置文件:


[*]/srv/salt/servers.sls
[*]/srv/salt/dev/mongodb.sls
  注:这里也可以使用文件夹/srv/salt/servers/和/srv/salt/dev/mongodb/,在文件夹中放置一组状态文件和配置文件,便于建立复杂的状态配置。
  top.sls中的可配置内容非常丰富,具体内容可以参考官方文档。

5.3 状态生效(State Enforcement)
  master上对状态进行定义,最终这些状态要传递到minion节点上。在本节的例子中,如果定义好了状态文件/srv/salt/dev/mongodb.sls:
  



</p>
<p>mongodb: pkg: - installed</p>
<p>
  
  可以使用命令salt "minion1" state.highstate -v使得所有针对"minion1"的state生效;
  在执行状态之前先进行测试是个好主意,需要指定参数test=True。比如,salt "minion1" state.highstate -v test=True。
  关于state模块的更多用法,可以参考state模块说明,或官方文档。

5.4 更多
  Salt的state模块的功能不仅如此,还可以使用模板和变量,以及定义状态的定时自动生效。

6 小结
  本文介绍Salt的主要功能和基本使用,包括minion节点的管理,批量操作,以及非常重要的配置管理。 掌握了这些内容,可以使用Salt极大提高运维的效率(事实上,Salt对于开发阶段也能提供很大的帮助,开发和运维的界限正在逐渐模糊)。
  后续会介绍一些使用案例以及Salt的高级功能。
页: [1]
查看完整版本: saltstack基础使用简版000;