saltstack知识点
1 file server configuration
salt有一个用ZeroMQ编写的高性能文件服务,它可以用很小的负载快速管理大量的文件。salt的文件服务是一个感知环境(environment aware)的文件服务,什么是环境感知?就是文件可以被分配在多个根目录下,可以在访问时指定文件路径和搜索路径。独特的环境可以跨越多个根目录覆盖,并以灵活的方式来组织文件。
salt默认的文件服务强制使用base环境,这个base环境必须被定义,当没有写明环境定义的时候,就是从这个base环境下载文件的,环境允许文件和sls数据在逻辑上分离,但彼此都不是孤立的环境。
环境设置了一系列目录来发布文件,在这些目录中进行文件查找,并返回第一个找到的文件。这意味着文件查找是按照设定的目录顺序进行查找的。eg:
1
2
3
4
|
file_roots: base: - / srv / salt / base - / srv / salt / failover |
假如在查找salt://httpd/httpd.conf文件时,第一个搜索的目录是/srv/salt/base/httpd/httpd.conf。如果在这里找到了这个文件,则返回该文件,如果没有该文件,则继续查找/srv/salt/failover/httpd/httpd.conf。
2 salt file server
salt使用文件服务分发文件到minions上,文件服务是一个内嵌在master里面的无状态ZeroMQ服务构成的。salt的文件服务目前用在salt的state system中,因此,文件服务可以用于任何文件传输。cp模块被用于salt的state system,salt-cp可以让salt的文件服务来分发文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
cp.get_file可以用来在minion端下载master上的文件。 salt '*' cp.get_file salt: / / vimrc / etc / vimrc 这个会通知所有的minion客户端来下载vimrc文件到 / etc / vimrc salt '*' cp.get_file "salt://{{grains.os}}/vimrc" / etc / vimrc template = jinja 也可以用模版,表示只在OS系统名称一样的机器上下载文件 salt '*' cp.get_file salt: / / vimrc / etc / vimrc gzip = 5 salt在传输大文件时还支持压缩:压缩比率是 1 - 9 salt '*' cp.get_file salt: / / vimrc / etc / vim / vimrc makedirs = True cp.get_file默认是不会创建目的端的目录的,如果该目录不存在的时候。要改变这种情况可以使用mkaedirs参数 salt '*' cp.get_dir salt: / / etc / apache2 / etc salt '*' cp.get_dir salt: / / etc / {{pillar.webserver}} / etc gzip = 5 template = jinja cp.get_dir和cp.get_file一样,不过get_dir是用来下载整个目录的,也支持模版和压缩 |
3 file server backends
salt在master上引进了一种能力,就是在整合不同的文件服务后端,文件服务后端允许salt的文件服务作为一个传输桥梁连接到外部资源。最好的例子就是git后端,它允许所有的salt文件保存在远程的git仓库中。
文件服务后端系统可以承担不同的后端类型,这样就可以在file_roots中配置不同的后端类型。文件后端这个功能是被master中的fileserver_backend参数管理的,它列出在后端系统中搜索的优先级顺序。例如:
1
2
3
|
fileserver_backend: - roots - git |
根据以上的配置,file_roots配置中定义的先被搜索,如果在file_roots没有搜索到,则git后端才会被搜索。
内建的fileserver模块:http://docs.saltstack.com/ref/file_server/all/index.html
其他两个没用过,主要使用fileserver.roots模块。
4 dynamic module distribution
salt的python模块可以通过salt的文件服务自动的分发。在master通过任何一个file_roots定义的根目录下的模块都可以被使用。
模块同步:自动的从master到minions传输加载、grains、renderers、returners、states模块信息等等。以下目录被优先考虑:
1
2
3
4
5
|
_modules _grains _renderers _returners _states |
在python模块被创建到这些目录后,这些目录下的内容需要被同步到minions上,有好几种办法同步模块:
1 通过states传输,在minion的配置文件中,有一个autoload_dynamic_modules选项,默认是True,当state运行的时候,它使用state system更新所有的动态模块,当动态模块通过states自动加载的时候,modules only pertinent to the environments matched in the master's top file are downloaded。这很重要,因为模块可以被手动的加载,在指定特定的环境特定的模块。
2 通过saltutil模块分发,saltutil模块有一些函数可以同步所有的或者指定的动态模块。saltutil.sync_all可以同步所有的模块到minion。
关于saltutil查看:http://docs.saltstack.com/ref/modules/all/salt.modules.saltutil.html#module-salt.modules.saltutil
5 client acl system
salt的client acl system意思是允许系统账户(非root)可以在master上访问、执行salt命令到minions。
client acl system是在master上的client_acl参数配置的,在client_acl下可以设置用户可以使用的命令,也可以通过正则匹配设置一系列命令。例如:
1
2
3
4
5
6
|
client_acl: thatch: - . * fred: - ping. * - pkg. * |
允许thatch执行任何命令,允许fred使用ping和pkg命令。当然必须要让用户可读相关目录。
chmod 755 /var/cache/salt /var/cache/salt/jobs /var/run/salt
6 state testing
在执行salt state run的时候,可能潜在的改变系统,他可能是令人满意的,但也可能识不满意的。salt提供了一个test接口,报告哪些东西将被改变,这个接口可以被使用在任何state运行的func上面。
1
2
|
salt '*' state.highstate test = True salt '*' state.sls test = True |
7 the top file
top file用来映射什么sls模块会通过state system被安装到minions。top file创建了一些通用的抽象。首先,它把节点映射到某个环境,接下来他定义匹配系统应答从哪个节点拉取。
First it maps what nodes should pull from which environments, next it defines which matches systems should draw from.
top file的环境和设置的file_roots是一致的,在一个简单的,单一环境中,你只设置了base环境,因此你只有一个state tree,例子如下:
1
2
3
|
file_roots: base: - / srv / salt |
以上例子意味着,你的top file只有一个环境可以映射。例子如下:
1
2
3
4
|
base: '*' : - core - edit |
这也意味着/srv/salt有一个state tree,如果你想使用多个环境,或者分隔file server到多个state tree,file_roots可以如下设置:
1
2
3
4
5
6
7
8
9
|
file_roots: base: - / srv / salt / base dev: - / srv / salt / dev qa: - / srv / salt / qa prod: - / srv / salt / prod |
这时我们的top file可以如下引用多个环境:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
dev: 'webserver*dev*' : - webserver 'db*dev*' : - db qa: 'webserver*qa*' : - webserver 'db*qa*' : - db prod: 'webserver*prod*' : - webserver 'db*prod*' : - db |
在上面的设置中,我们设置了三个state tree,并没有设置在base环境中的state tree。
Remember, that since everything is a file in Salt, the environments are primarily file server environments, this means that environments that have nothing to do with states can be defined and used to distribute other files.
关于top file可以参考:http://docs.saltstack.com/ref/states/top.html
8 state modules
State Modules are the components that map to actual enforcement and management of Salt states
state模块很容易编写,传入到sls数据结构的信息会被直接映射到states modules。
怎样使用定制的states模块?把你编写的state模块,放到_states目录下,该目录的具体路径是由file_roots指定的,这些定制的模块可以通过多种方法分发,当state.highstate运行时、执行saltutil.sync_states时、执行salr
tutil.sync_all函数时都会分发定制的模块。注意:state模块的名称模式就是state模块python脚本的名称。模块必须返回字典类型的数据。
内建模块:http://docs.saltstack.com/ref/states/all/index.html
9 salt runners
salt runners是一个便利的应用,方便使用salt-run的命令。就像salt模块发送到minions执行一样。salt runners在master上执行。一个salt runner可以是一个简单的客户端调用也可以是一个复杂的应用。
The use for a Salt runner is to build a frontend hook for running sets of commands via Salt or creating special formatted output.
很容易编写salt runners,它工作起来就和salt模块一样,不同之处在于salt runners在master上运行。一个runner是一个python模块,每个python模块中的共有函数都是一个runner,他可以通过salt-run命令执行。
如果一个python模块是test.py,存放在runners的目录下,test.py有一个函数是foo,则可以通过一下方法使用:
salt-run test.foo
系统自带了一些runner模块
http://docs.saltstack.com/ref/runners/all/index.html
https://github.com/saltstack/salt/tree/develop/salt/runners
10 startup states
有时候希望minion启动的时候就执行state,这个减轻了master发起在新的minion上执行state的压力,因为新的minion客户端启动后会自动执行state,就不需要master发起该操作了。在salt的minion配置文件中有一些参数可以定义该功能。
startup_states 可以传递一个或者多个参数,定义执行哪些states,可用参数如下:
highstate 执行state.highstate
sls 读取sls_list选项,然后执行sls文件
top 读取top_file选项,然后基于master上的top文件执行states
sls_list
top_file
例子:
1
2
3
4
|
startup_states: sls sls_list: - edit.vim - hyper |
11 salt syndic
一个master控制多个master,同时被控制的master又可以控制很多的minion
1 首先在中心节点的master上启动order_masters
2 在次级mastert上启动syndic_master,指定为中心master,启动salt-syndic
比如总的master为master,syndic节点为syndic1,将minion1的master制定为syndic,启动minion服务,然后在syndic1节点就可以看到未接受的key,接受后,syndic就可以管理minion1了,同时master也可以管理minion1了。
参考:http://docs.saltstack.com/ref/syndic.html
12 grains
salt用一个接口收集系统的信息,这个接口称为grains,grains收集到的信息是在minion第一次启动的时候获取的信息,所以必须认识到grains收集到的信息是静态的,是minion第一次启动的时候获取的,这些信息不会变化。grains收集的是客户端的信息,不同的客户端可以有不同的grains,grains.ls则可以列出目标机器上可用的grains的名称。
你可以在minion配置文件总静态的设置grains。如果不想把grains配置在minion文件中,也可以把grains配置在/etc/salt/grains文件中,如果在两边都设置了grains,则minion配置文件中的优先级高。
1
2
3
4
5
6
7
8
9
10
11
12
|
#匹配系统是ubuntu的 进行ping测试 salt - G 'os:Ubuntu' test.ping #获取有效可用的grains salt '*' grains.ls #获取grains的数据,所有的。 salt '*' grains.items #要获取单个的数据,如下: salt '*' grains.item shell salt '*' grains.item osfullname osrelease |
上文说过,可以自己设置grains,既可以设置在minion中也可以设置在grains文件中,先看在minion中的格式:
1
2
3
4
5
6
7
|
grains: roles: - webserver - memcache deployment: datacenter4 cabinet: 13 cab_u: 14 - 15 |
接着看在/etc/salt/grains文件中的格式:
1
2
3
4
5
6
|
roles: - webserver - memcache deployment: datacenter4 cabinet: 13 cab_u: 14 - 15 |
切记:重启minion后才会生效
不过每次都修改客户端配置文件中的grains很麻烦,我们可以用python编写一些动态的grains来执行。minion启动时会自动执行grains包所带的模块和自定义grains中的函数,不过grains模块中的函数必须返回字典类型的值。这些动态的grains很显然是在master上设置的,放置在file_roots设置下的_grains目录中,然后需要执行 state.highstate或者altutil.sync_grains或者saltutil.sync_all,把_grains中的模块分发到minion上。
动态grains例子:https://github.com/saltstack/salt/blob/develop/salt/grains/core.py
参考:http://docs.saltstack.com/topics/targeting/grains.html
13 pillar
所有通过pillar传输的信息能够保证被提交给目标主机,pillar传输的数据是与特定的minion关联的,每个minion只能看到自己的数据,这使得Pillar引擎在Salt中被用来管理安全的信息。pillar能够包含任意基本的数据结构,如:列表数据,或者k/v数据。可以让数据容易在SLS文档中使用。默认情况下,Pillar已经运行在了Salt系统中。
默认情况下,主服务器的配置文件内容装载在pillar中,对所用的从服务器来说,通过配置主服务器的配置文件来使全局的从服务器生效。Pillar的数据创建在Salt主服务器上并且安全的分发到从服务器上。Salt当定义pillar的时候 并不局限于pillar sls文件,可以从其他额外的源取得数据。对于那些把基础结构信息存储在其他地方的会很有用。如果想禁止该功能,则可以设置master中的pillar_opts参数。
pillar使用和state相似的配置,pillar文件子啊地址是在master配置文件中通过pillar_roots参数定义的:
1
2
3
|
pillar_roots: base: - / srv / pillar |
这段代码的意思是base环境下的pillar文件存放在/srv/pillar目录下,与state类似,pillar也有top file,使用相同的匹配方式将数据发送到minion上:/srv/pillar/top.sls
1
2
3
4
|
base: '*' : - data - packages |
/srv/pillar/data.sls内容是:
1
2
3
4
5
6
7
|
{ % if grains[ 'os' ] = = 'RedHat' % } apache: httpd git: git { % elif grains[ 'os' ] = = 'Debian' % } apache: apache2 git: git - core { % endif % } |
/srv/pillar/packages/init.sls内容是:
1
2
3
4
5
|
{ % for user, uid in pillar.get( 'users' , {}).items() % } {{user}}: user.present: - uid: {{uid}} { % endfor % } |
上面的代码表示base环境中的而所有minion都具有data和packages中定义的数据,pillar采用与file server相同的文件映射方式,在上例中data映射到文件/srv/pillar/data.sls,packages映射到文件/srv/pillar/packages/init.sls。
pillar模块有两个函数:pillar.data、pillar.raw,要查看所有的数据,可以如下:
1
|
salt '*' pillar.items |
在master上修改pillar下的文件后,要刷新一下,minion上的才能更新
1
|
salt '*' saltutil.refresh_pillar |
在使用pillar.items后,得出的额数据是python字典格式的,可以直接使用字典方法访问其中的数据。
下面展示一个官方提供的例子:
/srv/pillar/pkg/init.sls
1
2
3
4
5
6
7
8
9
10
11
|
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 % } |
/srv/pillar/top.sls
1
2
3
4
5
|
base: '*' : - data - users - pkg |
/srv/salt/apache/init.sls
1
2
3
|
apache: pkg.installed: - name: {{ pillar[ 'pkgs' ][ 'apache' ] }} |
参考:http://docs.saltstack.com/topics/tutorials/pillar.html
14 Highstate data structure definitions
top file :主要的state入口文件,指定minions在state执行期间可以使用那些环境、模块。
state tree : 一些sls文件,存放在file_roots指定的目录下,使用sls模块的形式组织state tree。
incluede 声明 :定义了一系列modules reference包含在该sls文件中。例如
1
2
3
|
include: - edit.vim - http.server |
module reference:sls模块的名称,定义在单独分开的sls文件中。一个模块edit.vim,意思是它的sls文件在salt://edit/vim.sls.
id 声明:定义一个独特的highstate元素。经常代表一个字典数据,包含state声明和requisite声明。不过可以被name声明覆盖。如果有重复的id声明,则第一个生效。
extend 声明:扩展被引用的sls模块中的name声明,extend的值必须是在被引用的sls模块中定义的id。例如:
1
2
3
4
5
6
7
8
|
include: - apache extend: apache: service: - watch: - file : mywebsite |
state 声明:是一个列表,值是function声明定义的。
requisite 声明:是一个列表,其成员是requisite reference。用来生成动作依赖书,salt states被设计成按顺序执行,作为list组件用在state声明的下一级。
requisite reference:只有一个值,值是被引用的state声明的名字,只能是requisite声明的成员。
function 声明:state中要执行的function,一个state声明中只能有一个function声明。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#简写 httpd: pkg.installed #或者完整写法 httpd: pkg: - installed #注意下面连续两个简写是不生效的 httpd: pkg.installed service.running |
function arg 声明:作为参数传递给function声明。用在function声明的下一级。
1
2
3
4
5
|
/ etc / http / conf / http.conf: file .managed: - user: root - group: root - mode: 644 |
name 声明:覆盖state声明中的name参数,name参数的默认值是ID声明,例如:
1
2
3
4
|
mywebsite: file .managed: - name: / etc / apache2 / sites - available / mywebsite.com - source: salt: / / mywebsite.com |
很明显mywebsite这个名词比/etc/apache2/sites-available/mywebsite.com方便。
参考:http://docs.saltstack.com/ref/states/highstate.html