/ 编程

SaltStack: There and back again

First Class 之后,master 可以管理 minion 了,这里记下一些用法,从“低端”用法,到不那么“低端”的用法。除非特殊说明,执行命令和编辑文件都是在 master 上进行的。

saltstack 有很多的可执行模块(execution modules),比如下面要提到的 file, cmd, state, cp 等等,这里是 saltstack 所有的可执行模块列表。这些模块一般是这样用的

salt '*' module_name.module_function args...

'*' 表示所有 minion,可以指定特定一个 minion,或者使用通配符 'a*' 之类的字符串,还可以'x[0-9]'这样写,表示从 'x0' 到 'x9' 之间的名称。还支持正则表达式。通过 -L 指定一个 minion 的列表。

salt -L 'web1,web2,web3' test.ping

这类模块的作用,可以大概理解成,在 master 机器上敲一行命令,告诉 minion 要做一件什么事情。

saltstack 有个重要的概念:state,或许可以这么理解,这是让所有 minion 变成统一状态 (state) 的 saltstack 的一个系统。这个系统也包含了很多模块,这里是所有 state 模块的列表。

前面提到的可执行模块里有个 state,它是用来对 saltstack 的 state 系统进行控制的。

state 是较为“高端”的用法。编辑一些文件,在 master 机器上定义好所管理的机器应该处于什么状态,装些什么包,配置文件怎么样,运行哪些服务,然后告诉 minion, minion 就把所在机器变成这个样子。

从简单的开始。先把两个最容易想到的两件事情搞定。

salt '*' cmd.run 'date'

cmd 模块的 run 方法,命令在所有 minion 上执行 date 命令。

salt '*' cp.get_file salt://file /tmp/abcd

这个命令让我很迷惑,我以为是在 minion 端执行,去 master 拉取文件,试了好多次才知道,这个命令是在 master 执行的。

上面这一行命令是让所有 minion 拉取 master 上 salt://file 文件到本地的 /tmp/abcd, salt://file 的真实路径跟 file_roots 的配置有关,例如

file_roots:
  base:
    - /srv/salt

这样 salt://file 就是 /srv/salt/file

如果要批量执行某个脚本,可以把脚本放在 master 上前面说的 salt:// 目录,然后执行 salt '*' cmd.script salt://hello.sh 让所有 minion 执行 hello.sh 这个脚本。

批量执行命令、传文件,这种任务用 fabric 也是可以轻松做到的,这也不是 saltstack 主要的用途。

state

上面这种方法并不是一个批量处理 minion 机器某个软件配置文件的好方法。通过 state,可以这样做。

下发文件

/srv/salt/ 目录编辑文件 testfile.sls,文件内容:

/tmp/abcd:
  file.managed:
    - source:
      - salt://file

执行 salt '*' state.sls testfile,作用是把 master 的 salt://file 文件下发到各个 minion 保存为 /tmp/abcd。看上去跟前面 cp.get_file 作用是一样的。

这条命令表示执行 state 模块的 sls 方法,即执行名为 testfile 的 sls 文件,sls 的意思就是 Salt State。

testfile.sls 的第一行表示目标,第二行表示使用 state 的 file 模块,managed 方法,下面是该方法的参数,这里只用了一个 source 参数,表示源文件路径,还可以添加其他参数,用于设置目标的权限、所属用户等属性。

整个目录

还可以下发整个目录,编辑新文件 testdir.sls 文件内容

/tmp/dir:
  file.recurse:
    - makedirs: True
	- source: salt://dir_test
    - include_empty: True

执行 salt '*' state.sls testdir,作用是把 salt://dir_test 目录及其子目录包括空文件,下发到各个 minion,存为 /tmp/dir

这种方法要比 cp.get_file 强大灵活得多,因为 state 的 file 模块还有很多其他方法,比如 file.append 用于追加字符串或者是一个文件到 minion 的目标文件。文档地址是 salt.states.file

顺带提一下,还可以用名为 file 可执行模块进行一些操作,比如在 minion 的 /etc/foo.conf 末尾追加一行字符串 'world'。

salt '*' file.append /etc/foo.conf world

这个跟 state 的 file 模块不是一回事,不要搞混了。file 可执行模块的文档地址是 salt.modules.file

上面的传文件和目录都是用的 state 的 file 模块,下面用到的是 state 的 cmd 模块。

执行命令

state 系统有 file 模块,也有 cmd 模块,最简单的使用方法是:
/srv/salt/test_cmd.sls 内容:

date:
  cmd.run

执行salt '*' state.sls test_cmd.sls,就在每一个 minion 执行了 date 命令。

执行脚本

如果要所有机器都执行一个脚本,一个个传上去,然后一个个执行是个相当蠢的办法。使用 saltstack 可以大大解放我们的双手。
/srv/salt/scripts/test.sls 内容:

salt://scripts/test.sh:
  cmd.script

/srv/salt/scripts/test.sh 内容

date;

/srv/salt/scripts/test.sh 就是希望在所有 minion 都执行的脚本,这里只写了一个 date 命令。

执行 salt '*' state.sls scripts.test,就在每一个 minion 执行 test.sh 脚本。这个命令里最后的参数是 scripts.test,因为 test.sls 文件的路径在 srv/salt/scripts/,在 file_roots 设定的 saltstack “根”目录的 scripts 目录下。

state 的 cmd 模块的文档在这里 salt.states.cmd

上面几节都是用的 state.sls 方法,参数是 sls 文件名(不包含后缀'sls'),这个文件可能有两种方式存在着,假设名字叫 xxxxx,一种是像这样在 /srv/salt/ 目录下的 xxxxx.sls 文件,还有一种是在 /srv/salt/xxxxx/ 下创建一个 init.sls 文件。

可执行模块 state 还有别的用法,比如 state.highstate。具体的各种方法请看 salt.modules.state

综合例子

这里有个比较综合,简单的例子。来自 SaltStack Walk-Through

/srv/salt/edit/vim.sls:

vim:
  pkg.installed

/etc/vimrc:
  file.managed:
    - source: salt://edit/vimrc
	- mode: 644
	- user: root
	- group: root

执行 salt '*' state.sls edit.vim

首先是制定需要安装 vim,大多数 saltstack 文档都提到了 pkg 这个模块。然后是把 /srv/salt/edit/vimrc 文件放到每个 minion 的 /etc/vimrc,并且设置好 644 权限以及 root 用户和组。

注意命令最后是 edit.vim,跟上面 scripts.test 类似,因为 vim.sls 路径不是在 file_roots 设定的 /srv/salt/ “根”目录,而是多了一层 edit/


最后写几个可能有用的命令

查看 minion 在线状态

salt-run manage.status // 查看在线、离线 minion
salt-run manage.up			// 查看在线 minion
salt-run manage.down		// 查看离线 minion

查看 minion 的版本

salt '*' test.version	

用了 test 可执行模块,还有其他可执行的方法,比如 minion 和 master 能“互动”之后,执行一条 salt '*' test.ping


两篇文章,只能记下 saltstack 的皮毛,好在官方文档很完善,由浅入深,而且很清晰标明哪些属于“新手入门”,哪些是“深入 saltstack”,哪些是“最佳实践”。赞!