LabHub
学习 学习路径 课程

Ansible 基础

变量优先级与 facts 的处理

在 LabHub 中继续学习

目标

将数值从代码中分离并放到不同位置,亲自确认发生冲突时哪个值优先。同时处理通过 fact 和 register 在运行过程中取得的值。

为什么重要

“变量改了却没有生效”这个问题,答案几乎总是优先级。Ansible 允许从多个位置接收同名变量,即使发生冲突也不会报错,而是静默采用优先级更高的值。这种特性虽然方便,却让调试更困难。因此需要具备这样的设计意识:允许覆盖的值放在弱优先级位置(role 的 defaults),必须严格保持的值放在强优先级位置。命令行 -e 可以覆盖一切,但它不会记录在任何地方;如果在故障处理中使用了它,就必须把变更补回代码,否则下一次部署会静默删除该值。

步骤

  1. 创建 /root/ans/vars/site.yml,并在 play 的 vars: 中定义 app_name: checkout。将该值写入 /root/ans/vars/out/app_name.txt
  2. /root/ans/vars/vars/common.yml 中设置 app_port: 9090,并通过 vars_files 读取。将值写入 /root/ans/vars/out/app_port.txt
  3. /root/ans/inventory/group_vars/web.yml 中设置 node_role: frontend,在 /root/ans/inventory/host_vars/web1.yml 中设置 node_role: canary。这两个目录必须与第一个实验创建的 /root/ans/inventory/hosts.ini 位于同一位置,才能自动读取。web2 应显示 frontend,web1 应显示 canary。
  4. 执行命令并用 register 接收结果,然后只把标准输出保存到 /root/ans/vars/out/uptime.txt
  5. 启用 gather_facts,把收集到的 fact 中的主机名、架构和系统保存为 JSON 文件 /root/ans/vars/out/facts.json
  6. 使用 -e app_port=9999 运行,并把该值保存到 /root/ans/vars/out/precedence.txt。第 2 步创建的 app_port.txt 必须仍为 9090。
  7. 使用 set_fact 拼接 app_nameapp_port,将结果保存到 /root/ans/vars/out/endpoint.txt,格式为 checkout:9090
  8. 创建 /root/ans/vars/out/summary.json,其中必须有四个键:app(=checkout)、port(=9090)、role(web1 的主机变量值)和 host(所收集 fact 中的主机名)。

参考

定义并使用 play 变量

创建 /root/ans/vars/site.yml,并在 play 的 vars: 中定义 app_name: checkout。将该值写入 /root/ans/vars/out/app_name.txt

把值放在 play 的 vars: 下,并在 copy 模块的 content 中通过 Jinja2 引用。

拆分变量文件

/root/ans/vars/vars/common.yml 中设置 app_port: 9090,并通过 vars_files 读取。将值写入 /root/ans/vars/out/app_port.txt

vars_files: 接受路径列表。变量增多后,通常会从 play 中拆分到单独文件。

创建组变量和主机变量

/root/ans/inventory/group_vars/web.yml 中设置 node_role: frontend,在 /root/ans/inventory/host_vars/web1.yml 中设置 node_role: canary。这两个目录必须与第一个实验创建的 /root/ans/inventory/hosts.ini 位于同一位置,才能自动读取。web2 应显示 frontend,web1 应显示 canary。

目录名称本身就是约定。group_vars 下的文件名对应组名,host_vars 下的文件名对应主机名。

将命令结果保存到变量

执行命令并用 register 接收结果,然后只把标准输出保存到 /root/ans/vars/out/uptime.txt

register 得到的是一个对象。文件中只应写入其中的标准输出。

收集 fact 并保存为 JSON

启用 gather_facts,把收集到的 fact 中的主机名、架构和系统保存为 JSON 文件 /root/ans/vars/out/facts.json

启用 gather_facts,从 ansible_facts 中选择所需部分并写成 JSON。to_nice_json 过滤器会有帮助。

使用命令行变量覆盖

使用 -e app_port=9999 运行,并把该值保存到 /root/ans/vars/out/precedence.txt。第 2 步创建的 app_port.txt 必须仍为 9090。

通过 -e 传入的值优先级最高。不要覆盖前一步保存的文件,请使用另一个文件名。

使用 set_fact 组合值

使用 set_fact 拼接 app_nameapp_port,将结果保存到 /root/ans/vars/out/endpoint.txt,格式为 checkout:9090

把两个变量拼成一个新值并写入文件,格式为 이름:포트

汇总变量、fact 与主机变量

创建 /root/ans/vars/out/summary.json,其中必须有四个键:app(=checkout)、port(=9090)、role(web1 的主机变量值)和 host(所收集 fact 中的主机名)。

创建包含四个键(app、port、role、host)的 JSON。role 来自 web1 的主机变量,host 来自收集到的 fact。