Salt States 基本法三

续上集,继续研究《Salt States 基本法》,本集前情提要:

介绍如何使用 file_roots 来建立一套可同时用于研发、测试、生产线的运行环境。

sls 根目录

Saltsls 文件服务器允许一个运行环境下配多个根目录,如下,使用了一个本地目录和网络共享目录:

/etc/salt/master:

1
2
3
4
file_roots:
base:
- /srv/salt
- /mnt/salt-nfs/base

Salt 会依次遍历列这些目录,直到找到对应的 sls 文件。如果有不止一个目录含有相同名字的 sls 文件,那么以最先找到的那个为准。比如,/srv/salt/foo.txt/mnt/salt-nfs/base/foo.txt 都存在的话, 那么 salt://foo.txt 将引用 /srv/salt/foo.txt 文件。

配置运行环境

搭建多种运行环境,其配置如下:

/etc/salt/master:

1
2
3
4
5
6
7
8
9
10
file_roots:
base:
- /srv/salt/prod
qa:
- /srv/salt/qa
- /srv/salt/prod
dev:
- /srv/salt/dev
- /srv/salt/qa
- /srv/salt/prod

从上面给出的各种环境下的根目录信息来看,/srv/salt/prod 下面的文件三种环境都可以用,/srv/salt/qa 下面的文件可以用于 qadev 环境,而 /srv/salt/dev 下面的文件只能用于 dev 环境。

根据如上定义的根目录次序,新编辑的 sls 文件可以先放在目录 /srv/salt/dev,发布到相应的 dev 主机去测试。

dev 测试没问题后,这些 sls 文件可以移到 /srv/salt/qa,发布到相应的 qa 主机去测试。

最后,devqa 都觉得测试没问题,就可以把它们都移到 /srv/salt/prod 目录,发布给生产环境的主机去上线运行了。

实用案例

作为上面这种情况的一个典型例子,考虑这样一个网站,它安装在 /var/www/foobarcom,下面是 top.sls,它放在 /srv/salt/prod 目录,根据上述的 sls 遍历原则,三种环境都可以找到这个 top 文件:

/srv/salt/prod/top.sls:

1
2
3
4
5
6
7
8
9
base:
'web*prod*':
- webserver.foobarcom
qa:
'web*qa*':
- webserver.foobarcom
dev:
'web*dev*':
- webserver.foobarcom

通过 pillar,给不同的主机设置不同的角色(开发机器?测试机器?还是直接跑在线上的机器?):

/srv/pillar/top.sls:

1
2
3
4
5
6
7
base:
'web*prod*':
- webserver.prod
'web*qa*':
- webserver.qa
'web*dev*':
- webserver.dev

/srv/pillar/webserver/prod.sls:

1
webserver_role: prod

/srv/pillar/webserver/qa.sls:

1
webserver_role: qa

/srv/pillar/webserver/dev.sls:

1
webserver_role: dev

最后,是部署网站的 sls 文件:

/srv/salt/prod/webserver/foobarcom.sls:

1
2
3
4
5
6
7
8
{% if pillar.get('webserver_role', '') %}
/var/www/foobarcom:
file.recurse:
- source: salt://webserver/src/foobarcom
- saltenv: {{ pillar['webserver_role'] }}
- dir_mode: 755
- file_mode: 644
{% endif %}

从上面这个 state 可以看出,网站的源文件最初(dev 环境)放在这里:/srv/salt/dev/webserver/src/foobarcom

首先,部署到 dev 环境:

1
salt --pillar 'webserver_role:dev' state.apply webserver.foobarcom

多运行环境下的 top 文件和 state 遍历规则有点恶心:

如果没有明确指定指定运行环境(比如上面这条命令),minion 会在每个运行环境对应的根目录(一个或多个)中搜索 top.sls 并按照 top_file_merging_strategy (这里默认为:merge)来处理多个 top 文件的冲突情况。执行哪个 state 也是类似规则,会在 merge 后的 top.sls 文件里的每个运行环境都匹配一遍。

关于这部分的详细文档,请参考 这里

当然,我们这个例子中,webserver_role 匹配到了 /srv/salt/prod/top.sls 中的 dev 环境,因此准备执行 webserver.foobarcom 这个 state

因此,上面这个命令还可以指定运行环境 saltenv=dev

1
salt --pillar 'webserver_role:dev' state.apply webserver.foobarcom saltenv=dev

当在 dev 环境测试通过后,网站源文件可以从 /srv/salt/dev/webserver/src/foobarcom 移到 /srv/salt/qa/webserver/src/foobarcom,部署到 qa 环境去测试:

1
salt --pillar 'webserver_role:qa' state.apply webserver.foobarcom

最后,当在 qa 环境测试通过后,网站源文件就可以从 /srv/salt/qa/webserver/src/foobarcom 移到 /srv/salt/prod/webserver/src/foobarcom,部署到生产线运行:

1
salt --pillar 'webserver_role:prod' state.apply webserver.foobarcom

得益于 salt 到根目录体系,即使网站源文件移到了 /srv/salt/prod,它们在 devqa 环境下同样可以访问。

期望是美好的,but,很诡异的是,这最后部署到 prod 到步骤,出错了:

哎呀,真是买了个表啊~看上图,src 文件夹明明就在 prod 下面啊?!这个问题,我看了半天,头都大了……

折腾了半天,终于搞明白了:因为 file_roots 里面并没有声明有 prod 这个运行环境啊,亲!

/srv/salt/prod/webserver/foobarcom.sls 中的这行:

1
- saltenv: {{ pillar['webserver_role'] }}

saltenv 改为 basedevqa 即可。

下集预告

介绍有关 pillar 的那些事儿,吼不吼啊?

很惭愧,今晚又做了一点微小的贡献,谢谢大家!

hxzqlh wechat