用实测而不是文档来立变量优先级表
目标
把同一个名称的变量一个位置一个位置地放进十二个位置,亲自测量谁会赢,并把结果留成团队可以阅读的名次表。
为什么重要
“明明写在 group_vars 里了,却出现了别的值”这类报告不会以错误的形式出现。playbook 成功,文件被创建,只是内容不同。语法检查和 lint 都抓不到这个。能抓到的只有一件事——测量“此刻在这个位置上,这个名称解析成什么”。所以本实验不抄写文档的列表,而是测量。测量过一次的人,即使不背表,下次也知道先该怀疑什么。而最后要得出的结论不是表——减少位置的设计比了解表更强。
步骤
- 在
/root/ans/prec/inventory/hosts.ini中写入 web1、web2(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root),并在/root/ans/prec/roles/probe/中创建测量用 role。在defaults/main.yml中放svc_tier: role-defaults和probe_out,tasks/main.yml由两个 task 构成:用 debug 显示WINNER={{ svc_tier }},再把同一个值写到probe_out路径。用/root/ans/prec/p01.yml对 web1 运行这个 role,留下/root/ans/prec/out/01.txt。 - 把
/root/ans/prec/inv-vars/做成目录 inventory。在hosts.yml中写 web 组(web1、web2)和 db 组(db1),在group_vars/all.yml中以svc_tier放入inv-all,在group_vars/web.yml中放入inv-web,在host_vars/web2.yml中放入inv-host。用/root/ans/prec/p02.yml测量全部三台主机,留下/root/ans/prec/out/02-<호스트>.txt(占位符为主机名)。 - 创建
/root/ans/prec/p03.yml,在 play 的vars:中放入svc_tier: play-vars,测量 web1。inventory 使用第 2 步的inv-vars,结果留到/root/ans/prec/out/03.txt。 - 在
/root/ans/prec/vars/tier.yml中写svc_tier: vars-file,/root/ans/prec/p04.yml与第 3 步一样在 play 的vars:中保留play-vars,同时用vars_files:读入那个文件。结果是/root/ans/prec/out/04.txt。 - 在
/root/ans/prec/roles/probe_locked/中创建第二个测量 role。在vars/main.yml中放svc_tier: role-vars(defaults中只放probe_out),tasks/main.yml写得与 probe 相同。/root/ans/prec/p05.yml保留与第 4 步相同的两个位置,同时调用这个 role,留下/root/ans/prec/out/05.txt。 - 创建
/root/ans/prec/p06.yml。play 用vars_files:读入 tier.yml,并在一个 block 上加vars: {svc_tier: block-vars}。block 内的第一个 task 调用probe_lockedrole,留下/root/ans/prec/out/06-block.txt,第二个 task 在自己的vars:上加svc_tier: task-vars,把值写到/root/ans/prec/out/06-task.txt。 - 创建
/root/ans/prec/p07.yml。先用set_fact设定svc_tier: set-fact,然后让在 taskvars:上加了task-vars的 task 把值写到/root/ans/prec/out/07-setfact.txt,最后调用probe_lockedrole 并传入svc_tier: role-param,留下/root/ans/prec/out/07-roleparam.txt。 - 在
/root/ans/prec/vars/limits.yml中把base_limits和svc_limits设为{cpu: "1", memory: 1Gi},让/root/ans/prec/p08.yml在与-e svc_tier=extra-vars一起运行时,把命令行的值写到/root/ans/prec/out/08.txt。在同一个 playbook 中,把用 taskvars:给出svc_limits: {memory: 2Gi}的结果和用combine合并的结果,以replaced、combined两个键留到/root/ans/prec/out/08-hash.json,并把十二个位置的测量结果以表格形式写到/root/ans/prec/out/rank.md。
参考
- 测量用的 role 不做判断。它只是把此刻看到的值原样搬到画面(
WINNER=...)和文件中。这把尺子在第 1 步做好,一直用到最后。 - inventory 内部的较量,不用 playbook 也能看到。
ansible-inventory -i <인벤토리> --list(占位符为 inventory)会以 JSON 给出合并后的结果。 - 以目录形式给出的 inventory 里有会被忽略的扩展名。如果一台主机都看不到,先怀疑文件名。
- 常见错误:在测量胜负时把下面的位置删掉。两个位置必须同时存在,才能知道谁赢了。
- 常见错误:用手修改产出物文件。评分不只看文件,还会把 playbook 以检查模式重新运行一遍,看现在是否仍得到同样的值。
- Using Variables · Precedence rules · Build your inventory · combine filter
最底层的位置——role 默认值
在 /root/ans/prec/inventory/hosts.ini 中写入 web1、web2(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root),并在 /root/ans/prec/roles/probe/ 中创建测量用 role。在 defaults/main.yml 中放 svc_tier: role-defaults 和 probe_out,tasks/main.yml 由两个 task 构成:用 debug 显示 WINNER={{ svc_tier }},再把同一个值写到 probe_out 路径。用 /root/ans/prec/p01.yml 对 web1 运行这个 role,留下 /root/ans/prec/out/01.txt。
这个 role 是本实验始终使用的尺子。无论值来自哪个位置,role 只要把“此刻看到的值”写下来就行。结果文件路径每个 play 都不同,所以也要用变量接收。
inventory 内的三个位置
把 /root/ans/prec/inv-vars/ 做成目录 inventory。在 hosts.yml 中写 web 组(web1、web2)和 db 组(db1),在 group_vars/all.yml 中以 svc_tier 放入 inv-all,在 group_vars/web.yml 中放入 inv-web,在 host_vars/web2.yml 中放入 inv-host。用 /root/ans/prec/p02.yml 测量全部三台主机,留下 /root/ans/prec/out/02-<호스트>.txt(占位符为主机名)。
目录 inventory 里有会被忽略的扩展名。如果一台主机都看不到,先怀疑文件名。想把主机名放进结果文件名,把路径本身当作模板使用即可。
play vars 覆盖 inventory
创建 /root/ans/prec/p03.yml,在 play 的 vars: 中放入 svc_tier: play-vars,测量 web1。inventory 使用第 2 步的 inv-vars,结果留到 /root/ans/prec/out/03.txt。
目的是看 inventory 中已经有值时,这个位置是否还会赢。role 原样使用,只重新写 play。
出人意料的位置——vars_files
在 /root/ans/prec/vars/tier.yml 中写 svc_tier: vars-file,/root/ans/prec/p04.yml 与第 3 步一样在 play 的 vars: 中保留 play-vars,同时用 vars_files: 读入那个文件。结果是 /root/ans/prec/out/04.txt。
这是写在下面的压过写在上面的位置。必须把两个位置都留着,胜负才会显露,所以不要删掉 play vars。
很难从外面覆盖的位置——role vars
在 /root/ans/prec/roles/probe_locked/ 中创建第二个测量 role。在 vars/main.yml 中放 svc_tier: role-vars(defaults 中只放 probe_out),tasks/main.yml 写得与 probe 相同。/root/ans/prec/p05.yml 保留与第 4 步相同的两个位置,同时调用这个 role,留下 /root/ans/prec/out/05.txt。
即使在同一个 role 目录里,defaults 和 vars 的性质也正好相反。一个在最底层,一个高得多。所以要另外再做一个新 role——probe 作为测量最底层位置的尺子原样保留。
范围越窄越高——block 与 task
创建 /root/ans/prec/p06.yml。play 用 vars_files: 读入 tier.yml,并在一个 block 上加 vars: {svc_tier: block-vars}。block 内的第一个 task 调用 probe_locked role,留下 /root/ans/prec/out/06-block.txt,第二个 task 在自己的 vars: 上加 svc_tier: task-vars,把值写到 /root/ans/prec/out/06-task.txt。
在 block 里调用 role,block 变量就叠在 role vars 之上。第二个 task 不经过 role 直接写文件也行——要测量的是位置,而不是 role。
运行中产生的值与传给 role 的参数
创建 /root/ans/prec/p07.yml。先用 set_fact 设定 svc_tier: set-fact,然后让在 task vars: 上加了 task-vars 的 task 把值写到 /root/ans/prec/out/07-setfact.txt,最后调用 probe_locked role 并传入 svc_tier: role-param,留下 /root/ans/prec/out/07-roleparam.txt。
运行中设定的值比事先写好的那些位置更高。但在它之上还有一个——调用 role 时传入的值。
命令行、字典,以及名次表
在 /root/ans/prec/vars/limits.yml 中把 base_limits 和 svc_limits 设为 {cpu: "1", memory: 1Gi},让 /root/ans/prec/p08.yml 在与 -e svc_tier=extra-vars 一起运行时,把命令行的值写到 /root/ans/prec/out/08.txt。在同一个 playbook 中,把用 task vars: 给出 svc_limits: {memory: 2Gi} 的结果和用 combine 合并的结果,以 replaced、combined 两个键留到 /root/ans/prec/out/08-hash.json,并把十二个位置的测量结果以表格形式写到 /root/ans/prec/out/rank.md。
要看命令行的值是否真的赢,play 内部也必须保留其他位置。表要从低位置开始一行一行写,每行写明在那个位置测得的值——前面步骤的产出物就是依据。