ansible 事实,循环,条件判断

目录

ansible事实

 事实实例

将事实替换为动态的值

关闭事实收集

创建自定义事实

魔法变量

循环

利用循环迭代任务

简单循环

循环散列或字典列表

将Register变量与Loop一起使用

条件判断

条件任务语法

测试多个条件

组合循环和有条件任务


ansible事实

Ansible事实是Ansible在受管主机上自动检测到的变量。事实中包含有与主机相关的信息,可以像play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。

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

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

借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作。例如:

  • 可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
  • 可以根据通过事实报告的可用内存来自定义MySQL配置文件
  • 可以根据事实的值设置配置文件中使用的IPv4地址

通常,每个play在执行第一个任务之前会先自动运行setup模块来收集事实。

查看为受管主机收集的事实的一种方式是,运行一个收集事实并使用debug模块显示ansible_facts变量值的简短playbook。

 事实实例

[root@ansible fact]# cat fact.yml  //编写一个读取受关注及lamp的脚本
---
- name:
  hosts: lamp
  tasks: 
    - debug:
        var: ansible_facts
 
[root@ansible opt]# ansible-playbook fact/fact.yml  //执行成功

PLAY [lamp] *************************************************************************************

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

TASK [debug] ************************************************************************************
ok: [192.168.75.150] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.75.150",
            "192.168.122.1"
        ],
        "all_ipv6_addresses": [
            "fe80::124:207:8842:e49d"
        ],
        "ansible_local": {},

将事实替换为动态的值

//指定查看IPV4下的default_ipv4下的address
[root@ansible opt]# cat fact/fact.yml
---
- name:
  hosts: lamp
  tasks: 
    - debug:
            msg: >
              The IPV4 of {{ ansible_facts['default_ipv4']['address'] }} is {{ ansible_facts['fqdn']  }}

//执行成功
[root@ansible opt]# ansible-playbook fact/fact.yml 

PLAY [lamp] *************************************************************************************

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

TASK [debug] ************************************************************************************
ok: [192.168.75.150] => {
    "msg": "The IPV4 of 192.168.75.150 is lamp\n"
}

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

[root@ansible opt]# 
 
//可以用setup模块显示受控主机所有事实

[root@ansible opt]# ansible lamp -m setup
192.168.75.150 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.75.150",
            "192.168.122.1"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::124:207:8842:e49d"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "07/22/2020",
        "ansible_bios_version": "6.00",
......

关闭事实收集

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

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

以上种种原因导致我们可能想要永久或暂时关闭事实收集的功能,要为play禁用事实收集功能,可将gather_facts关键字设置为no:

[root@ansible opt]# cat fact/fact.yml
---
- name:
  hosts: lamp
  gather_facts: no  //加上此行即可关闭事实收集
  tasks: 
    - debug:
            msg: >
              The IPV4 of {{ ansible_facts['default_ipv4']['address'] }} is {{ ansible_facts['fqdn']  }}

创建自定义事实

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

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

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

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

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

[root@master apache]# cat apache.fact //设置apache的键对值
[httpd]
package = httpd
service = httpd
state = started
enabled = yes

[root@master opt]# cat fact/fact.yml  //编写安装apahe的playbook
---
- hosts: lamp
  vars:
    dir: /opt/ansible/facts.d
    file: apache.fact
  tasks:
    - name: create dir
      file:
        state: directory
        recurse: yes
        path: "{{ dir }}"
    - name: create file
      copy:
        src: "{{ file }}"
        dest: "{{ dir }}"

[root@master opt]# ansible-playbook fact/fact.yml 

PLAY [192.168.75.150] ******************************************************************************************************************

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

TASK [create dir] **********************************************************************************************************************
ok: [192.168.75.150]

TASK [create file] *********************************************************************************************************************
changed: [192.168.75.150]

PLAY RECAP *****************************************************************************************************************************
192.168.75.150             : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=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-variable
若要深入了解它们的值,一个途径是使用debug模块报告特定主机的hostvars变量的内容:

ansible 172.16.103.129 -m debug -a 'var=hostvars["localhost"]'

循环

利用循环迭代任务

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

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

简单循环

//编写一个创建用户的循环yml脚本
[root@ansible look]# cat test.yml  
---
- hosts: lamp
  tasks: 
    - name: test useradd
      user: 
        name: "{{item}}"
        state: present
      loop:  //下面是要循环创建的用户
        - tian
        - di
        - xuan
        - huang

//执行
[root@ansible opt]# ansible-playbook look/test.yml 

PLAY [lamp] *************************************************************************************

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

TASK [test useradd] *****************************************************************************
changed: [192.168.75.150] => (item=tian)
changed: [192.168.75.150] => (item=di)
changed: [192.168.75.150] => (item=xuan)
changed: [192.168.75.150] => (item=huang)

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

//查看结果
[root@lamp ~]# id tian
uid=1002(tian) gid=1002(tian) 组=1002(tian)
[root@lamp ~]# id di
uid=1003(di) gid=1003(di) 组=1003(di)
[root@lamp ~]#  id xuan
uid=1004(xuan) gid=1004(xuan) 组=1004(xuan)
[root@lamp ~]# id huang
uid=1005(huang) gid=1005(huang) 组=1005(huang)

循环散列或字典列表

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

//循环创建用户和组
[root@ansible opt]# cat look/test.yml
---
- hosts: lamp
  tasks: 
    - name: test useradd
      user: 
        name: "{{item}}"
        groups: "{{ item.groups  }}"
        state: present
      loop:
        - name: wuhu
          groups: qifei
        - name: bai
          groups: yang


//测试
[root@ansible opt]# ansible-playbook --syntax-check look/test.yml

//执行
playbook: look/test.yml
[root@ansible opt]# ansible-playbook look/test.yml

PLAY [lamp] *************************************************************************************

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

TASK [test useradd] *****************************************************************************
ok: [192.168.75.150]

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

将Register变量与Loop一起使用

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

//编写脚本
[root@master loop]# cat test.yml 
---
- hosts: lamp
  tasks:
    - name:
      user:
        name: "{{ item.name }}"
        groups: "{{ item.groups }}"
        state: present
      loop:
        - name: bai
          groups: yang
        - name: wuhu
          groups: qifei
      register: result
    - name:
      debug:
        var: result

//执行
[root@master opt]# ansible-playbook loop/test.yml 

PLAY [192.168.75.150] ******************************************************************************************************************

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

TASK [user] ****************************************************************************************************************************
ok: [192.168.75.150] => (item={'name': 'bai', 'groups': 'yang'})
ok: [192.168.75.150] => (item={'name': 'wuhu', 'groups': 'qifei'})

条件判断

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

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

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

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

条件任务语法

when语句用于有条件地运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足,则跳过任务。


[root@master loop]# cat test.yml 
---
- hosts: lamp
  vars:  //设置条件变量
    mystest: true
  tasks:
    - name:
      user:
        name: "{{ item.name }}"
        groups: "{{ item.groups }}"
        state: present
      loop:
        - name: bai
          groups: yang
        - name: wuhu
          groups: qifei
      when: mytest  //条件mytest为true即可运行

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

操作示例
等于(值为字符串)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的求值为Truememory_available
布尔变量是False。0、False或no的求值为Falsenot memory_available
第一个变量的值存在,作为第二个变量的列表中的值ansible_distribution in supported_distros

上表中的最后一个条目初看起来有些令人困惑。下例演示了它的工作原理。

在示例中,ansible_distribution变量是在Gathering Facts任务期间确定的事实,用于标识托管主机的操作系统分支。变量supported_distrosplaybook创建,包含该playbook支持的操作系统分发列表。如果ansible_distribution的值在supported_distros列表中,则条件通过且任务运行。

测试多个条件

一个when语句可用于评估多个条件。使用andor关键字组合条件,并使用括号分组条件。

如果任一条件为真时满足条件语句,则应当使用or语句。例如,如果计算机上运行的是红帽企业linux或Fedora,则下述条件得到满足:

when: ansible_distribution == "Redhat" or ansible_distribution == "Fedora"

使用and运算时,两个条件都必须为真,才能满足整个条件语句。例如,如果远程主机是红帽企业Linux7.5主机,并且安装的内核是指定版本,则将满足以下条件:

when: ansible_distribution_version == "7.5" and ansible_kernel == "3.10.0-327.el7.x86_64"

when关键字还支持使用列表来描述条件列表。向when关键字提供列表时,将使用and运算组合所有条件。下面的示例演示了使用and运算符组合多个条件语句的另一方式:

when:
  - ansible_distribution_version == "7.5"
  - ansible_kernel == "3.10.0-327.el7.x86_64"

这种格式提高了可读性,而可读性是良好编写Ansible Playbook的关键目标。

通过使用括号分组条件,可以表达更复杂的条件语句。例如,如果计算机上运行的是红帽企业Linux7或Fedora28,则下述条件语句得到满足。此示例使用大于字符,这样长条件就可以在playbook中分成多行,以便于阅读。

组合循环和有条件任务

循环和条件可以组合使用。

在下例中,yum模块将安装mariadb-server软件包,只要/上挂载的文件系统具有超过300MB的可用空间。ansible_mounts事实是一组字典,各自代表一个已挂载文件系统的相关事实。循环迭代列表中每一字典,只有找到了代表两个条件都为真的已挂载文件系统的字典时,条件语句才得到满足。

- name: install mariadb-server if enough space on root
  yum:
    name: mariadb-server
    state: latest
  loop: "{{ ansible_mounts }}"
  when: item.mount == "/" and item.size_available > 300000000

对某个任务结合使用whenloop时,将对每个项检查when语句。

下面是组合使用条件和注册变量的另一个示例。

---
- name: Restart HTTPD if Postfix is Running
  hosts: 172.16.103.129
  tasks:
    - name: Get Postfix server status
      command: /usr/bin/systemctl is-active postfix     # Postfix是否在运行?
      ignore_errors: yes    # 如果它不在运行并且命令失败,则不停止处理。
      register: result      # 将模块的结果信息保存在名为result的变量中
      
    - name: Restart Apache HTTPD based on Postfix status
      service:
        name: httpd
        state: restarted
      when: result.rc == 0      # 评估Postfix任务的输出。如果systemctl命令的退出代码为0,\
                                # 则Postfix激活并且此任务重启httpd服务
when: >
  ( ansible_distribution == "Redhat" and
    ansible_distribution_major_version == "7" )
  or
  ( ansible_distribution == "Fedora" and
    ansible_distribution_major_version == "28" )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值