RHCE8.0讲义:管理事实

来自CloudWiki
跳转至: 导航搜索

描述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