Ansible 的条件语句与循环详解

本文将详细讲解 Ansible 中条件语句与循环的用法,并结合生产环境实例,展示如何高效地自动化日常运维任务。

1. 条件语句(Conditionals)

在实际场景中,任务的执行往往依赖于特定的条件,例如主机的系统版本、硬件配置、网络状态等。Ansible 提供了 when 关键字用于条件控制。

1.1 基本语法

复制代码
- name: Task description
  module_name:
    key: value
  when: <condition>

condition 是一个布尔表达式,可以使用变量、任务结果、系统事实等。

1.2 条件语句应用实例

1.2.1 根据操作系统类型安装软件

生产环境中,不同的主机可能运行着不同的操作系统,需要选择合适的软件包进行安装。

复制代码
- name: Install web servers
  hosts: all
  tasks:
    - name: Install Nginx on RedHat
      yum:
        name: nginx
        state: present
      when: ansible_facts['os_family'] == 'RedHat'

    - name: Install Apache on Ubuntu
      apt:
        name: apache2
        state: present
      when: ansible_facts['os_family'] == 'Debian'

说明:

ansible_facts['os_family'] 是系统事实,自动收集主机的操作系统类型。 不同的任务根据条件选择性执行。

1.2.2 动态调整任务执行

例如,需要根据主机的内存大小调整服务的运行参数:

复制代码
- name: Configure memory for Redis
  hosts: all
  tasks:
    - name: Use high-memory configuration
      template:
        src: redis_high_memory.j2
        dest: /etc/redis/redis.conf
      when: ansible_facts['memtotal_mb'] > 16384

    - name: Use low-memory configuration
      template:
        src: redis_low_memory.j2
        dest: /etc/redis/redis.conf
      when: ansible_facts['memtotal_mb'] <= 16384

高内存主机加载性能优化的配置文件,低内存主机使用精简版配置。

1.3 任务结果与条件配合

在某些情况下,需要根据前一任务的执行结果决定后续任务是否继续。例如,检查某个服务是否运行:

复制代码
- name: Check if service is running
  shell: systemctl is-active nginx
  register: nginx_status
  ignore_errors: yes

- name: Restart service if not running
  service:
    name: nginx
    state: restarted
  when: nginx_status.stdout != 'active'

说明:

register 将任务结果保存到变量 nginx_status。 后续任务根据 nginx_status.stdout 判断服务状态,动态执行。

1.4 条件语句的逻辑组合

支持 and, or, not 等逻辑运算符来组合复杂条件。

复制代码
- name: Perform task if multiple conditions are met
  shell: echo "Conditions met"
  when: ansible_facts['os_family'] == 'RedHat' and ansible_facts['memtotal_mb'] > 4096

说明:

只有同时满足操作系统为 RedHat 且内存大于 8GB 时,任务才会执行。

2. 循环(Loops)

在生产环境中,经常需要对一组配置项、文件或主机列表进行重复操作。Ansible 的循环功能通过 loop 关键字实现。

2.1 基本语法

复制代码
- name: Loop example
  module_name:
    key: "{{ item }}"
  loop:
    - item1
    - item2
    - item3

2.2 循环应用实例

2.2.1 批量安装多个软件包

在多台主机上批量安装常用软件包:

复制代码
- name: Install common packages
  hosts: all
  tasks:
    - name: Install software
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - vim
        - git
        - curl

说明:

loop 列表中的每一项会作为 item 的值依次执行。

2.2.2 创建多个用户

批量创建用户,并为每个用户设置权限:

复制代码
- name: Create multiple users
  hosts: all
  tasks:
    - name: Add users
      user:
        name: "{{ item.name }}"
        groups: "{{ item.group }}"
        state: present
      loop:
        - { name: "alice", group: "sudo" }
        - { name: "bob", group: "admin" }

说明:

通过字典列表传递复杂参数,为每个用户设置不同的组。

2.2.3 文件分发

将一组配置文件分发到多个主机:

复制代码
- name: Distribute configuration files
  hosts: all
  tasks:
    - name: Copy config files
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      loop:
        - { src: "/files/config1.conf", dest: "/etc/app/config1.conf" }
        - { src: "/files/config2.conf", dest: "/etc/app/config2.conf" }

2.3 嵌套循环

在实际场景中,可能需要处理嵌套数据,例如多个用户对应多个主机。Ansible 支持嵌套循环:

复制代码
- name: Nested loop example
  debug:
    msg: "User {{ item.0 }} is assigned to host {{ item.1 }}"
  loop:
    - "{{ ['alice', 'bob'] | product(['host1', 'host2']) | list }}"

说明:

product 用于生成两组数据的笛卡尔积。 输出每个用户和每台主机的组合。

3. 条件与循环结合

条件和循环可以结合使用,实现复杂的逻辑控制。

3.1 条件限制整个循环

例如,仅在 RedHat 系统上安装一组软件包:

复制代码
- name: Install packages if RedHat
  yum:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - httpd
  when: ansible_facts['os_family'] == 'RedHat'

3.2 条件限制循环中的每个项

根据条件跳过部分项:

复制代码
- name: Install selected packages
  yum:
    name: "{{ item.name }}"
    state: present
  loop:
    - { name: "nginx", enabled: true }
    - { name: "httpd", enabled: false }
  when: item.enabled

4. 生产环境实例:高效服务部署

以下是一个生产环境中的完整示例,展示如何结合条件和循环部署不同类型的服务。

需求:

  • 在 web 主机组上部署 Nginx。

  • 在 db 主机组上部署 MySQL。

  • 针对不同主机分配特定的配置文件。

解决方案:

复制代码
- name: Deploy services based on roles
  hosts: all
  tasks:
    - name: Install Nginx on web servers
      yum:
        name: nginx
        state: present
      when: "'web' in group_names"

    - name: Install MySQL on db servers
      yum:
        name: mysql-server
        state: present
      when: "'db' in group_names"

    - name: Configure web servers
      copy:
        src: "/configs/nginx/{{ inventory_hostname }}.conf"
        dest: /etc/nginx/nginx.conf
      when: "'web' in group_names"

    - name: Configure db servers
      copy:
        src: "/configs/mysql/{{ inventory_hostname }}.cnf"
        dest: /etc/my.cnf
      when: "'db' in group_names"

本文先介绍到这里

相关推荐
曾凡宇先生3 小时前
OpenEuler中mysql这是在执行 MySQL 密码重置操作时出现的 “找不到mysqld_safe命令” 的错误场景。
数据库·mysql
方二华3 小时前
6 mysql源码中的查询逻辑
数据库·mysql
意疏4 小时前
LibreTV无广告观影实测:聚合全网资源,远程访问家庭影院新方案!
数据库
不见长安在4 小时前
mysql线上主从集群设置
数据库·mysql
tiging4 小时前
mysql 如何让事件执行
数据库·mysql
siriuuus4 小时前
MySQL 数据备份
数据库·mysql·备份
姚远Oracle ACE4 小时前
Oracle AWR 报告中的SQL来自哪儿?
数据库·sql·oracle
熊文豪4 小时前
KingbaseES数据库性能调优工具全面解析
数据库·kingbasees·金仓数据库·电科金仓
冠希陈、5 小时前
PHP7.4.33 安装sqlsrv扩展
数据库