RHCE8.0讲义:管理事实
目录
描述ANSIBLE事实
Ansible事实是Ansible在受管主机上自动检测到的变量。事实中含有与主机相关的信息,可以像 play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。
事实的范围
为受管主机收集的一些事实可能包括
- 主机名称
- 内核版本
- 网络接口
- IP地址
- 操作系统版本
- 各种环境变量
- CPU数量
- 提供的或可用的内存
- 可用磁盘空间
借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作。例如:
- 可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重新启动服务器。
- 可以根据通过事实报告的可用内存来自定义MySQL配置文件。
- 可以根据事实的值设置配置文件中使用的IPv4地址。
事实的使用
收集事实的方法
通常,每个play在执行第一个任务之前会先自动运行setup模块来收集事实。这在Ansible 2.3中 报告为Gathering Facts任务,或者在更早版本的Ansible中报告为setup。默认情况下,您无 需具有在play中运行setup的任务。它通常会自动为您运行。
查看为受管主机收集的事实的另种方式是,运行一个收集事实并使用debug模块显示 ansible_facts 变量值的简短 playbook。
--- - name: Fact dump hosts: all tasks: - name: Print all facts debug: var: ansible_facts
运行该playbook时,事实将显示在作业输出中:
[user@demo ~]$ ansible-playbook facts.yml
PLAY [Fact dump] *** TASK [Gathering Facts] * ok: [demol.example.com] TASK [Print all facts] *********** ok: [demol.example.com] => { "ansible-facts": { "all_ipv4_addresses":[ "172.25.250.10" ], "all_ipv6_addresses":[ "fe80::5054:ff:fe00:faQa" ], "ansible_local": {}, "apparmor": { "status": "disabled" }, "architecture": "x86_64", "bios_date": "01/01/2011", "bios_version": "0.5.1", "cmdline": { "BOOT_IMAGE": "/boot/vmlinuz-3.10.0-327.el7.x86_64", "LANG": "en_US.UTF-8", "console": "ttySO,115200n8"z "crashkernel": "auto", "net.ifnames": "0", "no_timer_check": true, "ro": true, "root": "UUID=2460ab6e-e869-4011-acae-31b2e8c05a3b" }, ・..output omitted
Playbook以JSON格式显示ansible_facts变量的内容,作为变量的散列/字典。您可以浏览输 出来查看收集了哪些事实,并查找您可能要在play中使用的事实。
下表显示了可能从受管节点收集的并可在playbook中使用的一些事实:
Ansible事实的示例
事实 变量 短主机名 ansible_facts['hostname'] 完全限定的域名 ansible_facts['fqdn'] 主要IPv4地址(基于路由) ansible_facts['default_ipv4']['address'] 所有网络接口的名称列表 ansible_facts['interfaces'] /dev/vdal磁盘分区的大小 ansible_facts['devices1]['vda']['partitions'] ['vdal'jt'size'] DNS服务器列表 ansible_facts['dns']['nameservers1] 当前运行的内核的版本 ansible_facts[1 kernel']
引用事实的方法
注意:请记住,如果变量的值为散列/字典,则可使用两种语法来检索该值。从上表中举两 个例子:
- ansible_facts [' default_ipv4' ] [' address ']也可以写成 ansible_facts.default_ipv4.address
- ansible_facts [' dns' ] [' nameservers']也可以写成 ansible_facts.dns.nameservers
在playbook中使用事实时,Ansible将事实的变量名动态替换为对应的值:
- hosts: all tasks: - name: Prints various Ansible facts debug: msg: > The default IPv4 address of {{ ansible_facts.fqdn }} is {{ ansible_facts.default_ipv4.address }}
下列输出演示了 Ansible如何查询受管节点,并且动态使用系统信息来更新变量。也可使用事实来 创建符合特定标准的动态主机组。
[user@demo ~]$ ansible-playbook playbook.yml
play *************************************** TASK [Gathering Facts] ***************** ok: [demol.example.com] TASK [Prints various Ansible facts] ************************************ ok: [demol.example.com] => { "msg": "The default IPv4 address of demol.example.com is 172.25.250.10" play recap ****************************** demol.example.com : ok=2 changed=0 unreachable=0 failed=0
新旧事实名称
在Ansible2.5之前,事实是作为前缀为字符串ansible —的单个变量注入,而不是作为 ansible_facts 变量的一部分注入。例如,ansible_facts [' distribution ']事实会被称 为 ansible_distribution
许多较旧的playbook仍然使用作为变量注入的事实,而不是在ansible_facts变量下创建命名 空间的新语法。您可以使用临时命令来运行setup模块,以此形式显示味有事实的值。以下示例中 使用一个临时命令在受管主机demol. example. com上运行setup模块:
[root@servera ~]# ansible 10.0.0.30 -m setup
10.0.0.30 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "10.0.0.30" ], "ansible_all_ipv6_addresses": [ "fe80::dffd:fae2:f3d3:9000" ], "ansible_apparmor": { "status": "disabled" }, "ansible_architecture": "x86_64", "ansible_bios_date": "07/29/2019", "ansible_bios_vendor": "Phoenix Technologies LTD", "ansible_bios_version": "6.00", "ansible_board_asset_tag": "NA", "ansible_board_name": "440BX Desktop Reference Platform", "ansible_board_serial": "None", "ansible_board_vendor": "Intel Corporation", "ansible_board_version": "None", "ansible_chassis_asset_tag": "No Asset Tag", "ansible_chassis_serial": "None", "ansible_chassis_vendor": "No Enclosure", "ansible_chassis_version": "N/A", "ansible_cmdline": { "BOOT_IMAGE": "/vmlinuz-3.10.0-1062.el7.x86_64", "LANG": "en_US.UTF-8", "quiet": true, "rd.lvm.lv": "centos/swap", "rhgb": true, "ro": true, "root": "/dev/mapper/centos-root" },... output omitted …
下表比较了旧的和新的事实名称。
选定的Ansible事实名称的比较
ANSIBLE.FACTS 形式 旧事实变量形式 ansible_facts['hostname'] ansible_hostname ansible_facts['fqdn'] ansible_fqdn ansible_facts['default_ipv4'] [* address'] ansible_default_ipv4['address'] ansible_facts['interfaces'] ansible_interfaces ansible_facts['devices']['vda'] ['partitions'][1vdal']['size'] ansible_devices['vda'] ['partitions']['vdal']['size'] ansible_facts[1dns1] ['nameservers'] ansible_dns['nameservers'] ansible_facts['kernel1] ansible_kernel
重要
目前,Ansible同时识别新的事实命名系统(使用ansible_facts)和旧的2.5 前“作为单独变量注入的事实”命名系统。
将Ansible配置文件的[default]部分中的inject_facts_as_vars参数设置为 false,可关闭旧命名系统。默认设置目前为true。
inject_facts_as_vars的默认值在Ansible的未来版本中可能会更改为false。 如果设置为false,则只能使用新的ansible_facts. *命名系统引用Ansible事 实。在这种情况下,尝试通过旧命名空间引用事实将导致以下错误:
... output omitted... task [Show me the facts] ************************************************* fatal: [demo.example.com]: FAILED I => ("msg": "The task includes an option with an undefined variable. The error was: 'ansible_distribution' is undefined\n\nThe error appears to have been in '/home/student/demo/playbook.yml': line 5, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Show me the facts\n 八 here\n") ... output omitted...
关闭事实收集
有时,您不想为play收集事实。这样做的原因有几个。可能是您不准备使用任何事实,并且希望 加快play速度或减小play在受管主机上造成的负载。可能是受管主机因为某种原因而无法运行 setup模块,或者需要安装一些必备软件后再收集事实。
要为play禁用事实收集,可将gather_facts关键字设置为no:
--- - name: This play gathers no facts automatically hosts: large_farm gather_facts: no
即使为play设置了 gather_facts: no,您也可以随时通过运行使用setup模块的任务来手动收 集事实:
tasks: - name: Manually gather facts setup: .…output omitted...
创建自定义事实
什么是自定义事实
管理员可以创建自定义事实,将其本地存储在每个受管主机上。这些事实整合到setup模块在受管 主机上运行时收集的标准事实列表中。它们让受管主机能够向Ansible提供任意变量,以用于调整 play的行为。
自定义事实可以在静态文件中定义,格式可为INI文件或采用JSON。它们也可以是生成JSON输出 的可执行脚本,如同动态清单脚本一样。
借助自定义事实,管理员可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行 任务。动态自定义事实允许在play运行时以编程方式确定这些事实的值,甚至还可以确定提供哪些事实。
自定义事实举例
默认情况下,setup模块从各受管主机的/etc/ansible/facts.d目录下的文件和脚本中加载 自定义事实。各个文件或脚本的名称必须以.fact结尾才能被使用。动态自定义事实脚本必须输出 JSON格式的事实,而且必须是可执行文件。
以下是采用INI格式编写的静态自定义事实文件。INI格式的自定义事实文件包含由一个部分定义的 顶层值,后跟用于待定义的事实的键值对:
[packages] web_package = httpd db_package = mariadb-server [users] userl = joe user2 = jane
同样的事实可能以JSON格式提供。以下JSON事实等同于以上示例中INI格式指定的事实。JSON 数据可以存储在静态文本文件中,或者通过可执行脚本输出到标准输出:
"packages": { "web_package": "httpd", "db_package": "mariadb-server" }, "users'*: { "userl": “joe”, "user2": "jane" } }
注意:自定义事实文件不能采用playbook那样的YAML格式。JSON格式是最为接近的等效 格式。
自定义事实的存储位置
自定义事实由setup模块存储在ansible_facts.ansible_local变量中。事实按照定义它们的文件的名称来整理。例如,假设前面的自定义事实由受管主机上保存为/etc/ansible/facts.d/custom.fact的文件生成。在那种情况下,ansible_facts. ansible_local[' custom' ] [' users'] ['userl']的值为joe
您可以利用临时命令在受管主机上运行setup模块来检查自定义事实的结构。
[user@demo 〜]$ ansible demol.example.com -m setup
demol.example.com | SUCCESS => { "ansible_facts": ( ... output omitted "ansible_local": { "custom": { "packages": { "db_package": "mariadb-server", "web_packagen: "httpd" }, "users": { "userl": "joe", "user2": "jane" } ) }, ...output omitted... }, "changed": false }
自定义事实的使用方式
自定义事实的使用方式与playbook中的默认事实相同:
[user@demo ~]$ cat playbook.yml
- hosts: all tasks: -name: Prints various Ansible facts debug: msg: > The package to install on {{ ansible_facts['fqdn'] }} is {{ ansible_facts['ansible_local']['custom']['packages'] ['web_package1] }}
[user@demo ~]$ ansible-playbook playbook.yml
play ******************************************************************* TASK [Gathering Facts] ******* ok: [demol.example.com] TASK [Prints various Ansible facts] ****************************** ok: [demol.example.com] => { "msg": "The package to install on demol.example.com is httpd" play recap ********************************************************** demol.example.com : ok=2 changed=0 unreachable=O failed=0
使用魔法变量
一些变量并非事实或通过setup模块配置,但也由Ansible自动设置。这些魔法变量也可用于获取 与特定受管主机相关的信息。
最常用的有四个:
- hostvars
包含受管主机的变量,可以用于获取另一台受管主机的变量的值。如果还没有为受管主机收集 事实,则它不会包含该主机的事实。
- group_names
列出当前受管主机所属的所有组。
- groups
列出清单中的所有组和主机。
- inventory_hostname
包含清重中配置的当前受管主机的主机名称。这可能因为各种原因而与事实报告的主机名称不 同。
另外还有许多其他的“魔法变量”。有关更多信息,请参见https://docs.ansible.com/ansible/ latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable0 若要深入了解它们的值,一个途径是使用debug模块报告特定主机的hostvars变量的内容:
[root@servera ~]# ansible localhost -m debug -a 'var=hostvars["localhost"]'
localhost | SUCCESS => { "hostvars[\"localhost\"]": { "ansible_check_mode": false, "ansible_config_file": "/root/.ansible.cfg", "ansible_connection": "local", "ansible_diff_mode": false, "ansible_facts": {}, "ansible_forks": 5, "ansible_inventory_sources": [ "/etc/ansible/hosts"
参考文献
I』setup -收集关于远程主机的事实— Ansible文档 https://docs.ansible.com/ansible/latest/modules/setup_module.html
本地事实(Facts.d) —变量 — Ansible 文档 https://docs.ansible.com/ansible/latest/user_guide/ playbooks_variables.html#local-facts-facts-d