事实

为受管主机收集的一些事实可能包括:

主机名称
内核版本
网络接口
IP地址
操作系统版本
各种环境变量
CPU数量
提供的或可用的内存
可用磁盘空间

1.查看ansible事实

[root@ansible jay]# vi playbook.yml 

---
- hosts: all
  tasks:
    - name: fact
      debug:
        var: ansible_facts

[root@ansible jay]# ansible-playbook playbook.yml 

PLAY [all] *************************************************************************************************************

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

TASK [fact] ************************************************************************************************************
ok: [192.168.10.129] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.10.129",
            "192.168.122.1"
        ],
        "all_ipv6_addresses": [
            "fe80::4762:8a53:ead1:f2a6"
        ].........
PLAY RECAP *************************************************************************************************************
192.168.10.129             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Playbook以JSON格式显示ansible_facts变量的内容。

Ansible事实的示例

事实

变量

短主机名

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’]

2.从事实中提出本机ip

[root@ansible jay]# vi playbook.yml 

---
- hosts: all
  tasks:
    - name: 提出本机的ip地址
      debug:
        var: ansible_facts['default_ipv4']['address']

[root@ansible jay]# ansible-playbook playbook.yml 

PLAY [all] *************************************************************************************************************

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

TASK [提出本机的ip地址] *******************************************************************************************************
ok: [192.168.10.129] => {
    "ansible_facts['default_ipv4']['address']": "192.168.10.129"
}

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

3.关闭事实的收集

当我们不想为play收集事实。这样做的原因可能有:

1.不准备使用任何事实
2.希望加快play速度
3.希望减小play在受管主机上造成的负载
4.受管主机因为某种原因无法运行setup模块
5.需要安装一些必备软件后再收集事实

gather_facts: no

即使playbook设置了gather_facts: no,还是能够通过运行使用setup模块的任务来手动收集事实:

[root@ansible jay]# vi playbook.yml 

---
- hosts: all
  gather_facts: no
  tasks:
    - name: 提出本机的ip地址
      setup :
    - name : debug
      debug:
        var: ansible_facts['default_ipv4']['address']
[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

TASK [提出本机的ip地址] *****************************************************************
ok: [192.168.10.129] => {
    "ansible_facts['default_ipv4']['address']": "VARIABLE IS NOT DEFINED!"
}

PLAY RECAP ***********************************************************************
192.168.10.129             : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible jay]# vi playbook.yml 
[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

TASK [提出本机的ip地址] *****************************************************************
ok: [192.168.10.129]

TASK [debug] *********************************************************************
ok: [192.168.10.129] => {
    "ansible_facts['default_ipv4']['address']": "192.168.10.129"
}

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

4.创建自定义事实

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

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

[users]
user1 = adw
user2 = jay

5.魔法变量

一些变量并非事实或通过setup模块配置,但也由Ansible自动设置。这些魔法变量也可用于获取与特定受管主机相关的信息。

最常用的有四个:

魔法变量

说明

hostvars

包含受管主机的变量,可以用于获取另一台受管主机的变量的值。如果还没有为受管主机收集事实,则它不会包含该主机的事实。

group_names

列出当前受管主机所属的所有组

groups

列出清单中的所有组和主机

inventory_hostname

包含清单中配置的当前受管主机的主机名称。因为各种原因有可能与事实报告的主机名称不同

可以通过debug模块报告特定主机的hostvars变量的内容:

[root@ansible jay]# ansible all -m debug -a 'var=hostvars["localhost"]'

循环

1.利用循环迭代任务

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

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

2.简单循环

简单循环对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。

---
- hosts: all
  tasks:
    - name: 运行postfix和dovecot
      service:
        name: "{{ item }}"
        state: started
      loop:
        - postfix
        - dovecot
   
[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

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

TASK [运行postfix和dovecot] *********************************************************
changed: [192.168.10.129] => (item=postfix)
changed: [192.168.10.129] => (item=dovecot)

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

也可以通过一个变量提供loop所使用的列表。在以下示例中,变量mail_services含有需要处于运行状态的服务的列表。

---
- hosts: all
  vars:
    mail_ser:
      - postfix
      - dovecot
  tasks:
    - name: 运行postfix和dovecot
      service:
        name: "{{ item }}"
        state: started
      loop: "{{ mail_ser }}"

[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

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

TASK [运行postfix和dovecot] *********************************************************
changed: [192.168.10.129] => (item=postfix)
changed: [192.168.10.129] => (item=dovecot)

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

[root@ansible jay]# vi playbook.yml 
[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

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

TASK [运行postfix和dovecot] *********************************************************
changed: [192.168.10.129] => (item=postfix)
changed: [192.168.10.129] => (item=dovecot)

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

3.循环散列或字典列表

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

---
- hosts: all
  tasks:
    - name: user
      user:
        name: "{{ item.name }}"
        state: present
        groups: "{{ item.groups }}"
      loop:
        - name: adw
          groups: adidas
        - name: lxw
          groups: nike

[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

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

TASK [user] **********************************************************************
changed: [192.168.10.129] => (item={'name': 'adw', 'groups': 'adidas'})
changed: [192.168.10.129] => (item={'name': 'lxw', 'groups': 'nike'})

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

4.Register变量与Loop一起使用

register关键字也可以捕获循环任务的输出。以下代码片段显示了循环任务中register变量的结构:

---
- hosts: all
  tasks:
    - name: asdasd
      shell: "echo this is my item: {{ item }}"
      loop:
        - one
        - two
      register: echo_results
    - name: sadasd
      debug:
        var: echo_results

[root@ansible jay]# ansible-playbook -C playbook.yml 

PLAY [all] ***********************************************************************

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

TASK [asdasd] ********************************************************************
skipping: [192.168.10.129] => (item=one) 
skipping: [192.168.10.129] => (item=two) 

TASK [sadasd] ********************************************************************
ok: [192.168.10.129] => {
    "echo_results": {
        "changed": false,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo this is my item: one",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "one",
                "msg": "skipped, running in check mode",
                "skipped": true
            },
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo this is my item: two",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "two",
                "msg": "skipped, running in check mode",
                "skipped": true
            }
        ]
    }
}

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