Saltstack 数据采集系统
Grains
Grains是SaltStack的一个组件,存放在SaltStack的minion端。
当salt-minion启动时会把收集到的数据静态存放在Grains当中,只有当minion重启时才会进行数据的更新。
由于grains是静态数据,因此不推荐经常去修改它。
应用场景:
信息查询,可用作CMDB。
在target中使用,匹配minion。
在state系统中使用,配置管理模块。
因为grains是存在于minion节点的,并且它的使用方式类似于字典的方式,可以根据需要的指定value值进行提取
例:指定提取minion节点的ipv4地址,也可以指定某一主机
[root@server1 ~]# salt '*' grains.item ipv4
server3:
----------
ipv4:
- 127.0.0.1
- 172.25.254.3
server2:
----------
ipv4:
- 127.0.0.1
- 172.25.254.2
[root@server1 ~]# salt server2 grains.item uid
server2:
----------
uid:
0
想要查看都有哪些key可以使用:salt server2 grains.ls,列出全部的key
自定义grains项
这里的grains也支持自定义,在/etc/salt/minion里打开配置编辑需要指定的项,我自定义roles这个key对应的value是sshd
[root@server2 ~]# systemctl restart salt-minion.service #更改配置需要重启服务
[root@server1 ~]# salt server2 grains.item roles
server2: #再查看指定的roles就是sshd
----------
roles:
sshd
这样的自定义方式还是不推荐使用,因为必须要重启服务才可以生效,这对我们来说非常不友好,所以还有另外一种方法来实现目的
在minion节点的/etc/salt/下建立文件grains,编辑这个文件,写入需要自定义的grains值
[root@server3 ~]# vim /etc/salt/grains #在server3里编辑文件
roles: nginx
[root@server1 ~]# salt server3 saltutil.sync_grains #master节点同步grains
server3:
[root@server1 ~]# salt server3 grains.item roles #查看出指定的值
server3:
----------
roles:
nginx
编写远程执行的grains模块
和编写module类似,也是需要在salt-master的base目录下创建目录_grains,在这个目录下再去编写需要执行的.py文件
例:
[root@server1 ~]# cd /srv/salt/
[root@server1 salt]# mkdir _grains
[root@server1 salt]# vim _grains/grain.py
def my_grain(): #定义函数名
grains = {} #创建一个新字典
grains['roles'] = 'sshd' #指定字典里的key和value值
grains['hello'] = 'test'
return grains #返回查看的值
[root@server1 salt]# salt '*' saltutil.sync_grains #同步grains给其他minion
[root@server1 salt]# salt server2 grains.item hello
server2: #再去获取hello对应的value
----------
hello:
test
同步之后在其他被同步的节点上和之前一样也是收到同步过来的文件件,还是一样收到指令后去调用本机里的这个文件执行
[root@server2 ~]# ls /var/cache/salt/minion/files/base/_grains/
grain.py
master节点可以通过指定grains来匹配符合条件的minion
[root@server1 salt]# salt -G roles:nginx cmd.run hostname
server3: #-G是grains,可以符合这个条件roles:nginx,执行显示主机名
server3
[root@server1 salt]# salt -G hello:test cmd.run hostname
server2:
server2
server3:
server3
同时也可以在top文件中使用grains匹配批量主机,例如给部署nginx 的主机都配置“roles: nginx” 使用grain去匹配筛选符合这个条件的主机
[root@server1 salt]# vim top.sls
base:
'roles:nginx': #指定grains
- match: grain
- nginx.install #匹配后执行的操作
[root@server1 salt]# salt '*' state.highstate #高级推给所有节点
server2是失败的因为不符合,server3成功执行操作
Pillar
pillar和grains一样也是一个数据系统,但是应用场景不同。
pillar是将信息动态的存放在master端,主要存放私密、敏感信息(如用户名密码等),而且可以指定某一个minion才可以看到对应的信息。
pillar更加适合在配置管理中运用。
因为pillar是不去推送给minion节点的所以就不能在/srv/salt里面写文件,它的base目录可以在/etc/salt/master里搜索pillar_roots 指定路径,默认是/srv/pillar,如果更改了默认路径就需要重启服务
所以需要创建/srv/pillar目录,再去里面编写执行文件
[root@server1 /]# mkdir /srv/pillar
[root@server1 /]# cd /srv/pillar/
编写的内容可以使用去结合grains的判断执行相应的操作
[root@server1 pillar]# vim packages.sls
{% if grains['fqdn'] == 'server3' %} #判定如果主机名是server3
package: nginx #执行操作安装nginx
{% elif grains['fqdn'] == 'server2' %} #如果是server2
package: httpd #安装httpd
{% endif %}
如果存在多台主机这里要注意还需要对其他不能匹配的主机也指定操作,现在只有两台minion就不要再去加,不然会报错
package: mariadb
因为pillar是动态信息,只要设定不需要同步就会自动生效
编写一个top文件执行packages.sls
[root@server1 pillar]# vim top.sls
base:
'*': #针对所有主机
- packages #执行上面编写的packages.sls
[root@server1 pillar]# salt '*' pillar.items #查看pillar值就会同步更新出来
server2:
----------
package:
httpd
server3:
----------
package:
nginx
当需要查看指定项的时时候,或者使用pillar进行匹配的时候就需要先刷新才可以查看到
[root@server1 pillar]# salt '*' saltutil.refresh_pillar #刷新
server2:
True
server3:
True
[root@server1 pillar]# salt '*' pillar.item package #查看package的值
server2:
----------
package:
httpd
server3:
----------
package:
nginx
[root@server1 pillar]# salt -I 'package:httpd' test.ping #-I表示pillar方式查看
server2:
True
引用执行
使用pillar进行检索通过定义的判定显示指定的值
[root@server1 pillar]# cd /srv/salt/
[root@server1 salt]# vim apache/init.sls
web:
pkg.installed:
- pkgs:
- {{ pillar['package'] }} #pillar里定义package对应server2的值就是httpd
- php
file.managed:
- source: salt://apache/httpd.conf
- name: /etc/httpd/conf/httpd.conf
service.running:
- name: {{ pillar['package'] }}
- enable: True
- watch:
- file: web
[root@server1 salt]# salt server2 state.sls apache #推送执行模块,可以成功执行
Jinja模板
Jinja是一种基于python的模板引擎,在SLS文件里可以直接使用jinja模板来做一些操作。
通过jinja模板可以为不同服务器定义各自的变量。
两种分隔符: {% … %} 和 {{ … }},前者用于执行诸如 for 循环 或赋值的语句,后者把表达式的结果打印到模板上。
jinja最基本的用法是使用控制结构包装条件
[root@server1 salt]# vim test.sls
/mnt/testfile: #name就是声明的文件名
file.append: #操作方式是建立文件
{% if grains['fq dn'] == 'server2' %}
- text: server2 #文件内容是通过判定grains['fq dn']截取到的主机名
{% elif grains['fqdn'] == 'server3' %}
- text: server3
{% endif %}
[root@server1 salt]# salt '*' state.sls test #推送执行
[root@server2 ~]# cat /mnt/testfile
server2
[root@server3 ~]# cat /mnt/testfile
server3
文件里使用jinja模板
在pillar的指定里添加一个端口的值
[root@server1 salt]# vim /srv/pillar/packages.sls
{% if grains['fqdn'] == 'server3' %}
package: nginx
{% elif grains['fqdn'] == 'server2' %}
package: httpd
port: 80 #指定端口的值为80
{% endif %}
在执行文件里添加jinja模块
web:
pkg.installed:
- pkgs:
- {{ pillar['package'] }}
- php
file.managed:
- source: salt://apache/httpd.conf
- name: /etc/httpd/conf/httpd.conf
- template: jinja #使用jinja模板
- context:
bind: 172.25.254.2 #指定bind对应的值是172.25.254.2
service.running:
- name: {{ pillar['package'] }}
- enable: True
- watch:
- file: web
把配置文件里的监听设定改为指定监听ip从bind取,端口从pillar取值
[root@server1 salt]# vim /srv/salt/apache/httpd.conf
Listen {{ bind }}:{{ pillar['port'] }}
推送执行测试
[root@server1 salt]# salt server2 state.sls apache
[root@server2 ~]# netstat -ntlp | grep httpd
tcp 0 0 172.25.254.2:80 0.0.0.0:* LISTEN 4784/httpd
优化操作
还可以进行优化,将配置文件里的ip指定也作为动态取值
[root@server1 salt]# vim /srv/salt/apache/httpd.conf
Listen {{ grains['ipv4'][-1] }}:{{ pillar['port'] }}
取值grains的ipv4是两个值,前一个是本机的回环接口,第二个是主机ip,[-1]表示倒数第一个
进一步优化
为了方便管理和查看,将配置文件里的变量定义,都放在执行文件里,配置文件里只写取值就可以
[root@server1 salt]# vim /srv/salt/apache/httpd.conf
Listen {{ bind }}:{{ port }}
[root@server1 salt]# vim /srv/salt/apache/init.sls
web:
pkg.installed:
- pkgs:
- {{ pillar['package'] }}
- php
file.managed:
- source: salt://apache/httpd.conf
- name: /etc/httpd/conf/httpd.conf
- template: jinja
- context:
bind: {{ grains['ipv4'][1] }} #定义ip的变量值
port: {{ pillar['port']}} #定义端口的变量值
service.running:
- name: {{ pillar['package'] }}
- enable: True
- watch:
- file: web
模块导入方式
这就类似pytho的写法,定义一个模块,然后使用import方式导入
在sal的base目录下创建一个文件,写入需要指定的值或变量
[root@server1 salt]# vim /srv/salt/lib.sls
{% set port = 8080 %}
在httpd配置文件的最上面导入指定的模板文件
[root@server1 salt]# vim /srv/salt/apache/httpd.conf
{% from 'lib.sls' import port %}
然后直接去推送执行就可以了,
注意的是,上面我们指定了一次端口,是从pillar里取来的值80,这里又定义里一次,最后生效的会是这个导入模块定义的值。
因为在上面的pillar取值执行后才会执行配=配置文件里导入模块的操作,就会覆盖掉之前的操作。
并且在最后放入/etc/httpd/conf/httpd.conf时,我们导入的这个操作行就会被删除,因为如果还存在那httpd的运行就会报错了,无法启动。