如何在 Ansible 中使用条件语句和其他条件

如果您需要根据不同条件执行 Ansible 任务,那么您来对地方了。 Ansible when 和其他条件 允许您评估条件,例如基于操作系统,或者如果一个任务依赖于前一个任务。

在本教程中,您将学习如何使用 Ansible when 和其他条件,以便您可以执行任务而不会搞砸事情。

让我们开始吧!

先决条件

本教程包括实际操作示例。 如果您想跟着做,请确保您已经准备好以下内容:

  • A remote computer to run commands.
  • 您需要设置一个 清单文件,并已经配置一个或多个主机来运行 Ansible 命令和 playbooks。 本教程将使用一个名为 web 的清单组。

使用 Playbook 中的多个任务处理 Ansible when

执行剧本中有多个任务可能会很烦人,如果它们都没有特定的条件执行。让我们通过在 Ansible 剧本中定义具有多个任务的 Ansible when 条件来开始本教程。

1. 在 Ansible 控制器主机上打开终端。

2. 运行以下命令来创建一个目录,并将其命名为您喜欢的任何名称在您的主目录中,并导航到该目录。

对于这个示例,目录被命名为 ansible_when_condition_demo。该目录将包含您将用于在 Ansible 任务中调用 when 条件的 剧本

# 创建名为 ~/ansible_when_condition_demo 的目录
mkdir ~/ansible_when_condition_demo
# 将工作目录更改为 ~/ansible_when_condition_demo
cd ~/ansible_when_condition_demo

3. 在您喜欢的代码编辑器中,在 ~/ansible_when_condition_demo 目录中创建一个 YAML 文件。在本例中,文件名为 my_playbook.yml。将以下 YAML 剧本内容复制并粘贴到 my_playbook.yml 文件中。

在下面的两个任务(Task-1Task-2)中,when 条件检查每个远程主机所在的操作系统。然后将结果传递给每个任务上的 ansible_os_family 占位符变量。

如果ansible_os_family占位符的值等于RedHatDebian,那么Ansible执行安装Apache的任务之一。

---
- name: Ansible tasks to work on Ansible When
# 定义Ansible将运行的远程服务器
  hosts: web
  remote_user: ubuntu # 将远程主机设置为ubuntu
  become: true # 以提升的用户身份(sudo)运行任务
  tasks:

# (任务1)检查ansible_os_family == "RedHat",然后在远程节点上安装Apache
    - name: Install Apache on CentOS  Server
      yum: name=httpd  state=present
      become: yes
      when: ansible_os_family == "RedHat"

# (任务2)检查ansible_os_family == "Debian",然后在远程节点上安装Apache
    - name: Install Apache on Ubuntu Server
      apt:name=apache2 state=present
      become: yes
      when: ansible_os_family == "Debian"

4. 现在运行下面的ansible-playbook命令来执行playbook中定义的任务(my_playbook.yml),在你现有的清单文件中定义的远程主机上。

ansible-playbook my_playbook.yml 

在下面的截图中,你可以看到:

  • 第一个任务返回了OK状态,这表明任务不需要任何更改。
  • 第二个任务返回了跳过状态。当条件不满足时,任务将被跳过。
  • 第三个任务返回了更改状态,这表明远程主机处于不正确的状态(即Apache不存在)并且已被修改以安装Apache。
Invoking the ansible-playbook using ansible-playbook command

5. 打开SSH会话到远程主机,该主机是Ansible playbook的目标,使用您喜欢的SSH客户端验证Apache是否已安装并正在运行。

6. 最后,运行以下service命令验证Apache是否已安装(status apache2)在远程主机上。

service status apache2

如下所示,您已在远程机器上安装了Apache服务。

Verifying the Apache service on the remote node

使用Ansible when和循环

之前,您根据Ansible when执行了特定参数的任务,如ansible_os_family。 但也许您需要检查在列表中定义的多个参数的条件。 如果是这样,请尝试在任务中添加loop

打开您之前创建的my_playbook.yml文件(“使用Ansible when处理Playbook中的多个任务”下的第三步)。 将my_playbook.yml文件的内容替换为以下代码。

代码中的任务(Task-1)运行loop,其中when条件检查项目值是否大于五并返回结果。

---
- name: Ansible tasks to work on Ansible When
# 定义Ansible将运行的远程服务器
  hosts: web
  remote_user: ubuntu   # 使用远程主机作为ubuntu
  become: true
  tasks:
  #(任务-1)检查项目值是否大于5
    - name: Run with items greater than 5
      ansible.builtin.command: echo {{ item }}
      loop: [ 0, 2, 4, 6, 8, 10 ]
      when: item > 5*

现在运行以下命令以执行之前所做的播放。

 ansible-playbook my_playbook.yml

以下,您可以看到任务在条件为假时返回跳过状态,而在条件为真时返回更改状态。

Checking the when condition for multiple parameters

使用Ansible的when和Ansible的facts来处理任务。

也许您想要添加多个条件以执行任务。如果是这样,请学习如何在when条件中使用Ansible facts。Ansible facts允许您添加条件语句以基于收集到的事实执行任务,例如您的操作系统、IP地址、附加的文件系统等。

使用以下代码替换my_playbook.yml文件的内容。

在下面的代码中,两个任务(Task-1Task-2)只有在以下条件之一为真时才执行(关闭系统):

  • 返回的distributiondistribtion_major_version都为真。
  • os_family的值等于CentOS
---
- name: Ansible When Single task example
  hosts: web
  remote_user: ubuntu
  become: true
  tasks:
#(任务-1):如果发行版是CentOS且主要版本是6,则关闭远程节点
    - name: Shut down CentOS 6 systems
      ansible.builtin.command: /sbin/shutdown -t now
      when:
        - ansible_facts['distribution'] == "CentOS"
        - ansible_facts['distribution_major_version'] == "6"
#(任务-2):如果os_family是CentOS,则关闭远程节点。
    - name: Shut down CentOS flavored systems
      ansible.builtin.command: /sbin/shutdown -t now
      when: ansible_facts['os_family'] == "CentOS"

像之前一样使用以下命令执行playbook。

ansible-playbook my_playbook.yml

请注意,在Ubuntu中,由于跳过状态,两个任务都不执行。任务仅在您在CentOS中时执行。

Executing the ansible-playbook with Ansible facts in Ansible when

使用基于已注册值的 Ansible `when`

根据剧本中先前任务的结果执行或跳过任务是时常需要的。例如,您可能希望在之前的任务升级后配置一个服务。在这种情况下,使用一个已注册变量。已注册变量允许您将先前任务的结果注册为一个变量,并将其用作下一个任务的输入。

1. 创建一个名为/home/ubuntu/hello的空目录。

2. 将my_playbook.yml文件的内容替换为下面的代码,执行以下操作:

第一个任务(任务-1)在内存中列出/etc/hosts目录的内容(文件和子目录),并通过register命令将结果保存到contents1变量中。

第二个任务(任务-2)在内存中列出/home/ubuntu/hello目录的内容(当前为空),并将该列表保存到contents2变量中。

第三个任务(任务-3)检查并在contents1contents2变量的注册结果为空时打印“目录为空”消息。

contents1contents2变量的stdout属性是运行任务命令的结果的保存的shell输出。

---
- name: Ansible When Single task example
  hosts: web
  remote_user: ubuntu
  become: true
  tasks:
#(任务-1):列出 /etc/hosts 目录的目录内容
      - name: List contents of directory and Store in content1
        ansible.builtin.command: ls /etc/hosts
        register: contents1
#(任务-2):列出 /home/ubuntu/hello 目录的目录内容
      - name: List contents of directory and Store in content2
        ansible.builtin.command: ls /home/ubuntu/hello
        register: contents2
#(任务-3):如果目录 /etc/hosts 或 /home/ubuntu/hello 为空,则显示目录为空
# /etc/hosts 或 /home/ubuntu/hello 中任一目录为空时,显示目录为空
      - name: Check contents for emptiness for content1 or content2
        ansible.builtin.debug:
          msg: "Directory is empty"
        when: contents1.stdout == "" or contents2.stdout == ""

3. 最后,使用以下 ansible-playbook 命令执行 Playbook。

ansible-playbook my_playbook.yml

如下所示,由于 contents2 变量的注册结果为空,第三个任务返回 目录为空 消息。

Running the Ansible playbook for Ansible when based on registered values

使用 Ansible 中的 when 处理 Ansible 角色

在这个最终的例子中,您将学习 Ansible 中 whenAnsible roles 内部的工作原理。Ansible roles 允许您重用标准配置并实现更快的部署。继续阅读,了解任务仅在 Ansible when 条件为真时调用 Ansible roles 的方法。

1. 运行以下命令在您的主目录中创建一个名为~/ansible_role_when_demo的目录,并切换到该文件夹作为工作目录。~/ansible_role_when_demo目录将保存此示例的演示文件。

# 在您的主目录中创建一个名为~/ansible_role_when_demo的目录
mkdir ~/ansible_role_when_demo
# 切换到~/ansible_role_when_demo目录
cd ~/ansible_role_when_demo

2. 接下来,运行以下命令创建一个~/ansible_role_when_demo/roles~/ansible_role_when_demo/roles/java/tasks目录。

下面是每个目录包含的内容:

  • ~/ansible_role_when_demo/roles目录将包含您需要部署的角色。

默认情况下,Ansible在两个位置查找角色:在playbook所在目录中的名为roles/的目录中,或在/etc/ansible/roles中。如果希望将角色存储在不同的路径,请使用- role:参数在playbook中声明路径。

  • ~/ansible_role_when_demo/roles/java/tasks文件夹将包含一个main.yml文件,您需要部署一个角色。
# 在 ~/ansible_role_when_demo 目录下创建名为 roles 的目录
mkdir -p roles
# 切换工作目录到 ~/ansible_role_when_demo/roles 目录
cd roles 
# 创建名为 java 的父目录和一个名为 tasks 的子目录
mkdir -p java/tasks

现在,在 ~/ansible_role_when_demo/roles/java/tasks 目录下创建一个名为 main.yml 的文件,然后将下面的剧本代码复制粘贴到 main.yml 文件中。

下面的剧本在远程节点上使用 apt 模块安装 Java。

---
# 安装 Java (Open Jdk) 
- name: Install Java 1.8
  apt: name=openjdk-8-jdk

4. 创建另一个以您喜欢的名称命名的 YAML 文件,并复制/粘贴下面的代码。例如,文件名为 ~/ansible_role_when_demo/java-setup.yml。

下面的代码将 Ansible role (java) 部署到具有管理员访问权限的远程用户 (ubuntu),仅当远程用户位于 Debian 操作系统上时才执行。

- name: Java Installation playbook
# 定义将部署软件包的远程服务器 
  hosts: myserver
  remote_user: ubuntu   # 使用远程用户 ubuntu
  become: true
  tasks:  
  roles:
     - role: java
       # 仅在远程用户位于 Debian 操作系统上时执行任务。
       when: ansible_facts['os_family'] == 'Debian'

5. 运行tree命令,验证在~/ansible_role_when_demo目录中存在所有必需的文件夹和文件。

Verifying all of the required folders in the ~/ansible_role_when_demo directory

6. 最后,使用下面的ansible-playbook命令执行playbook。ansible-playbook java-setup.yml

ansible-playbook java-setup.yml

下面,任务返回了一个changed状态,表示Java已成功安装,因为远程节点是Debian操作系统。 使用Ansible when和Ansible角色运行Ansible playbook

Running the Ansible playbook using Ansible when with Ansible roles

结论

在本教程中,您学习了使用Ansiblewhen和其他条件的不同方式。您还学习了如何应用Ansiblewhen条件,从利用Ansiblefacts执行基本任务到部署Ansibleroles

现在您如何建立在这些新知识上?也许在应用Ansiblewhen条件的同时,使用Ansible模板节省配置多个服务器的时间?

Source:
https://adamtheautomator.com/ansible-when/