续上集,继续研究《Salt States 基本法》,本集前情提要:
介绍如何使用
file_roots
来建立一套可同时用于研发、测试、生产线的运行环境。
sls 根目录
Salt
的 sls
文件服务器允许一个运行环境下配多个根目录,如下,使用了一个本地目录和网络共享目录:
/etc/salt/master
:
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
:
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
下面的文件可以用于 qa
和 dev
环境,而 /srv/salt/dev
下面的文件只能用于 dev 环境。
根据如上定义的根目录次序,新编辑的 sls
文件可以先放在目录 /srv/salt/dev
,发布到相应的 dev
主机去测试。
dev
测试没问题后,这些 sls
文件可以移到 /srv/salt/qa
,发布到相应的 qa
主机去测试。
最后,dev
和 qa
都觉得测试没问题,就可以把它们都移到 /srv/salt/prod
目录,发布给生产环境的主机去上线运行了。
实用案例
作为上面这种情况的一个典型例子,考虑这样一个网站,它安装在 /var/www/foobarcom
,下面是 top.sls
,它放在 /srv/salt/prod
目录,根据上述的 sls
遍历原则,三种环境都可以找到这个 top
文件:
/srv/salt/prod/top.sls
:
base:
'web*prod*':
- webserver.foobarcom
qa:
'web*qa*':
- webserver.foobarcom
dev:
'web*dev*':
- webserver.foobarcom
通过 pillar
,给不同的主机设置不同的角色(开发机器?测试机器?还是直接跑在线上的机器?):
/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.sls
:
webserver_role: dev
最后,是部署网站的 sls
文件:
/srv/salt/prod/webserver/foobarcom.sls
:
{% 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
环境:
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
。
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
环境去测试:
salt --pillar 'webserver_role:qa' state.apply webserver.foobarcom
最后,当在 qa
环境测试通过后,网站源文件就可以从 /srv/salt/qa/webserver/src/foobarcom
移到 /srv/salt/prod/webserver/src/foobarcom
,部署到生产线运行:
salt --pillar 'webserver_role:prod' state.apply webserver.foobarcom
得益于 salt
到根目录体系,即使网站源文件移到了 /srv/salt/prod
,它们在 dev
和 qa
环境下同样可以访问。
期望是美好的,but
,很诡异的是,这最后部署到 prod
到步骤,出错了:
哎呀,真是买了个表啊~看上图,src
文件夹明明就在 prod
下面啊?!这个问题,我看了半天,头都大了……
折腾了半天,终于搞明白了:因为 file_roots
里面并没有声明有 prod
这个运行环境啊,亲!
把 /srv/salt/prod/webserver/foobarcom.sls
中的这行:
- saltenv: {{ pillar['webserver_role'] }}
saltenv
改为 base
或 dev
或 qa
即可。
下集预告
介绍有关
pillar
的那些事儿,吼不吼啊?
很惭愧,今晚又做了一点微小的贡献,谢谢大家!