事实与任务控制

一、Ansible管理事实(fact)

1、Ansible事实描述

Ansible事实是Ansible在受管主机上自动检测到的变量
事实(fact)中包含有与主机相关的信息,可以像play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用
一些事实可能包括:
主机名称、内核版本、网络接口、IP地址、操作系统版本、各种环境变量、CPU数量、提供的或可用的内存、可用磁盘空间等等
借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作
例如:
可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
可以根据通过事实报告的可用内存来自定义MySQL配置文件
可以根据事实的值设置配置文件中使用的IPv4地址
每个play在执行第一个任务之前会先自动运行setup模块来收集事实
查看为受管主机收集的事实的一种方式是,运行一个收集事实并使用debug模块显示ansible_facts变量值的简短playbook。

- name: Fact dump
  hosts: 192.168.197.135
  tasks:
    - name: Print all facts
      debug:
        var: ansible_facts


[root@localhost ~]# ansible-playbook sisi.yml

PLAY [Fact dump] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.197.135]

TASK [Print all facts] *********************************************************
ok: [192.168.197.135] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.122.1",
            "192.168.197.135"
        ],
        "all_ipv6_addresses": [
            "fe80::6d29:381:82a7:1697"
        ],
        "ansible_local": {},
        "apparmor": {
            "status": "disabled"
        },
        "architecture": "x86_64",
        "bios_date": "07/22/2020",
        "bios_version": "6.00",
        "cmdline": {
            "BOOT_IMAGE": "(hd0,msdos1)/vmlinuz-4.18.0-193.el8.x86_64",
            "crashkernel": "auto",
            "quiet": true,
            "rd.lvm.lv": "rhel/swap",
            "resume": "/dev/mapper/rhel-swap",
            "rhgb": true,
            "ro": true,

事实变量
短主机名ansible_facts[‘hostname’]
完全限定域名ansible_facts[‘fqdn’]
IPv4地址ansible_facts[‘default_ipv4’][‘address’]
所有网络接口的名称列表ansible_facts[‘interfaces’]
/dev/vda1磁盘分区的大小ansible_facts[‘devices’][‘vda’][‘partitions’][‘vda1’][‘size’]
DNS服务器列表ansible_facts[‘dns’][‘nameservers’]
当前运行的内核版本ansible_facts[‘kernel’]

在playbook中使用事实时,Ansible将事实的变量名动态替换为对应的值:

---
- hosts: 192.168.197.135
  tasks:
    - name: Prints various Ansible facts
      debug:
        msg: >
          The default IPv4 address of {{ ansible_facts.fqdn }}
          is {{ ansible_facts.default_ipv4.address }}

[root@localhost ~]# ansible-playbook sisi.yml

PLAY [192.168.197.135] *********************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.197.135]

TASK [Prints various Ansible facts] ********************************************
ok: [192.168.197.135] => {
    "msg": "The default IPv4 address of localhost.localdomain is 192.168.197.135\n"
}

PLAY RECAP *********************************************************************
192.168.197.135            : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

2 Ansible事实作为变量注入

在Ansible2.5之前,事实是作为前缀为字符串ansible_的单个变量注入,而不是作为ansible_facts变量的一部分注入。例如,ansible_facts[‘distribution’]事实会被称为ansible_distribution。

许多较旧的playbook仍然使用作为变量注入的事实,而不是在ansible_facts变量下创建命名空间的新语法。我们可以使用临时命令来运行setup模块,以此形式显示所有事实的值。以下示例中使用一个临时命令在受管主机172.16.103.129上运行setup模块:

ansible 192.168.197.135 -m setup

选定的Ansible事实名称比较

目前,Ansible同时识别新的事实命名系统(使用ansible_facts)和旧的2.5前“作为单独变量注入的事实”命名系统。

将Ansible配置文件的[default]部分中inject_facts_as_vars参数设置为False,可关闭旧命名系统。默认设置目前为True。

inject_facts_as_vars的默认值在Ansible的未来版本中可能会更改为False。如果设置为False,则只能使用新的ansible_facts.*命名系统引用Ansible事实。所以建议大家一开始就要适应这种方式。

3.关闭事实收集

可将gather_facts关键字设置为no

4.创建自定义事实

创建自定义事实
除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上。这些事实整合到setup模块在受管主机上运行时收集的标准事实列表中。它们让受管主机能够向Ansible提供任意变量,以用于调整play的行为。

自定义事实可以在静态文件中定义,格式可为INI文件或采用JSON。它们也可以是生成JSON输出的可执行脚本,如同动态清单脚本一样。

有了自定义事实,我们可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行任务。动态自定义事实允许在play运行时以编程方式确定这些事实的值,甚至还可以确定提供哪些事实。

默认情况下,setup模块从各受管主机的/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实。各个文件或脚本的名称必须以.fact结尾才能被使用。动态自定义事实脚本必须输出JSON格式的事实,而且必须是可执行文件。

以下是采用INI格式编写的静态自定义事实文件。INI格式的自定义事实文件包含由一个部分定义的顶层值,后跟用于待定义的事实的键值对:

[root@localhost ~]# mkdir -p /etc/ansible/facts.d
[root@localhost ~]# cd /etc/ansible/
[root@localhost ansible]# ls
facts.d
[root@node1 localhost]# vim facts.d/test.fact
[packages]
web_package = httpd
db_package = mariadb-server

[users]
user1 = yhxx
user2 = yyy      

同样的事实可能以JSON格式提供。以下JSON事实等同于以上示例中INI格式指定的事实。JSON数据可以存储在静态文本文件中,或者通过可执行脚本输出到标准输出:

{
  "packages": {
    "web_package": "httpd",
    "db_package": "mariadb-server"
  },
  "users": {
    "user1": "yhxx",
    "user2": "yyy"
  }
}

自定义事实文件不能采用playbook那样的YAML格式。JSON格式是最为接近的等效格式。
自定义事实由setup模块存储在ansible_facts.ansible_local变量中。
事实按照定义它们的文件的名称来整理。例如,假设前面的自定义事实由受管主机上保存为/etc/ansible/facts.d/custom.fact的文件生成。在这种情况下,ansible_facts.ansible_local[‘custom’][‘users’][‘user1’]的值为yhxx。

二、编写循环和条件任务

利用循环迭代任务

通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。

Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

简单循环

可以通过循环用一条命令创建多个用户

[root@localhost ansible]# vim playbook/test.yml
---
- hosts: 192.168.197.135
  gather_facts: no
  tasks:
    - name: create user
      user:
        name: "{{ item }}"
        state: present
      loop:
        - xxx
        - hhh
        - yyy

循环散列或字典列表

loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过item.name和item.groups变量来检索。


- name: Users exist and are in the correct groups
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  loop:
    - name: xxx
      groups: hhh
    - name: yyy
      groups: root

这一示例中结果是用户xxx存在且为组hhh的成员,并且用户yyy存在且为组root的成员。
将Register变量与Loop一起使用
egister关键字也可以捕获循环任务的输出。以下代码片段显示了循环任务中register变量的结构:

[root@localhost ansible]# vim playbook/test.yml
---
- name: test
  gather_facts: no
  hosts: 192.168.197.135
  tasks:
    - name: Looping Echo Task
      command: "echo This is my item: {{ item }}"
      loop:
        - yyy
        - hhh
      register: echo_results
    - name: Show echo_results variable
      debug:
        var: echo_results

[root@localhost ansible]# ansible-playbook playbook/test.yml 

PLAY [test] *************************************************************************************

TASK [Looping Echo Task] ************************************************************************
changed: [192.168.197.135] => (item=hhh)
changed: [192.168.197.135] => (item=yyy)

有条件的执行任务

Ansible可使用conditionals在符合特定条件时执行任务或play。例如,可以利用一个条件在Ansible安装或配置服务前确定受管主机上的可用内存。

我们可以利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔值的运算符。

以下场景说明了在Ansible中使用条件的情况:

可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如,如果某一程序失败,则将路过批处理。
可以利用Ansible事实来确定受管主机网络配置,并决定要发送的模板文件(如,网络绑定或中继)。
可以评估CPU的数量,来确定如何正确调节某一Web服务器。
将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的MD5检验以和查看服务是否已更改。
条件任务语法
when语句用于有条件地运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足,则跳过任务。

可以测试的一个最简单条件是某一布尔变量是True还是False。以下示例中的when语句导致任务仅在run_my_task为True时运行:

---
- name: Simple Boolean Task Demo
  hosts: 192.168.197.135
  vars:
    run_my_task: True
  tasks:
    - name: httpd package is installed
      yum:
        name: httpd
      when: run_my_task

以下示例测试my_service变量是否具有值。若有值,则将my_service的值用作要安装的软件包的名称。如果未定义my_service变量,则跳过任务且不显示错误。

---
- name: Test Variable is Defined Demo
  hosts: 192.168.197.135
  vars:
    my_service: httpd
    
  tasks:
    - name: "{{ my_service }} package is installed"
      yum:
        name: "{{ my_service }}"
      when: my_service is defined

下表显示了在处理条件时可使用的一些运算:

示例条件操作 示例
等于(值为字符串)ansible_machine == “x86_64”
等于(值为数字)max_memory == 512
小于min_memory < 128
大于min_memory > 256
小于等于min_memory <= 256
大于等于min_memory >= 512
不等于min_memory != 512
变量存在min_memory is defined
变量不存在min_memory is not defined

布尔变量是True。1、True或yes的求值为True memory_available
布尔变量是False。0、False或no的求值为False not memory_available
第一个变量的值存在,作为第二个变量的列表中的值 ansible_distribution in supported_distros
上表中的最后一个条目初看起来有些令人困惑。下例演示了它的工作原理。

---
- name: test
  gather_facts: no
  hosts: 192.168.197.135
  tasks:
    - name: Looping Echo Task
      user:
        name: "{{ item }}"
      loop:
        - yyy
        - hhh
      when: '"{{ item }}" == "hhh"'

注意when语句的缩进。由于when语句不是模块变量,它必须通过缩进到任务的最高级别,放置在模块的外面。

任务是YAML散列/字典,when语句只是任务中的又一个键,就如任务的名称以及它所使用的模块一样。通常的惯例是将可能存在的任何when关键字放在任务名称和模块(及模块参数)的后面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值