Ansible 的条件语句与循环详解
本文将详细讲解 Ansible 中条件语句与循环的用法,并结合生产环境实例,展示如何高效地自动化日常运维任务。
1. 条件语句(Conditionals)
在实际场景中,任务的执行往往依赖于特定的条件,例如主机的系统版本、硬件配置、网络状态等。Ansible 提供了 when 关键字用于条件控制。
1.1 基本语法
- name: Task descriptionmodule_name:key: valuewhen: <condition>
condition 是一个布尔表达式,可以使用变量、任务结果、系统事实等。
1.2 条件语句应用实例
1.2.1 根据操作系统类型安装软件
生产环境中,不同的主机可能运行着不同的操作系统,需要选择合适的软件包进行安装。
- name: Install web servershosts: alltasks:- name: Install Nginx on RedHatyum:name: nginxstate: presentwhen: ansible_facts['os_family'] == 'RedHat'- name: Install Apache on Ubuntuapt:name: apache2state: presentwhen: ansible_facts['os_family'] == 'Debian'
说明:
ansible_facts['os_family'] 是系统事实,自动收集主机的操作系统类型。 不同的任务根据条件选择性执行。
1.2.2 动态调整任务执行
例如,需要根据主机的内存大小调整服务的运行参数:
- name: Configure memory for Redishosts: alltasks:- name: Use high-memory configurationtemplate:src: redis_high_memory.j2dest: /etc/redis/redis.confwhen: ansible_facts['memtotal_mb'] > 16384- name: Use low-memory configurationtemplate:src: redis_low_memory.j2dest: /etc/redis/redis.confwhen: ansible_facts['memtotal_mb'] <= 16384
高内存主机加载性能优化的配置文件,低内存主机使用精简版配置。
1.3 任务结果与条件配合
在某些情况下,需要根据前一任务的执行结果决定后续任务是否继续。例如,检查某个服务是否运行:
- name: Check if service is runningshell: systemctl is-active nginxregister: nginx_statusignore_errors: yes- name: Restart service if not runningservice:name: nginxstate: restartedwhen: nginx_status.stdout != 'active'
说明:
register 将任务结果保存到变量 nginx_status。 后续任务根据 nginx_status.stdout 判断服务状态,动态执行。
1.4 条件语句的逻辑组合
支持 and, or, not 等逻辑运算符来组合复杂条件。
- name: Perform task if multiple conditions are metshell: 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 examplemodule_name:key: "{{ item }}"loop:- item1- item2- item3
2.2 循环应用实例
2.2.1 批量安装多个软件包
在多台主机上批量安装常用软件包:
- name: Install common packageshosts: alltasks:- name: Install softwareyum:name: "{{ item }}"state: presentloop:- vim- git- curl
说明:
loop 列表中的每一项会作为 item 的值依次执行。
2.2.2 创建多个用户
批量创建用户,并为每个用户设置权限:
- name: Create multiple usershosts: alltasks:- name: Add usersuser:name: "{{ item.name }}"groups: "{{ item.group }}"state: presentloop:- { name: "alice", group: "sudo" }- { name: "bob", group: "admin" }
说明:
通过字典列表传递复杂参数,为每个用户设置不同的组。
2.2.3 文件分发
将一组配置文件分发到多个主机:
- name: Distribute configuration fileshosts: alltasks:- name: Copy config filescopy: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 exampledebug: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 RedHatyum:name: "{{ item }}"state: presentloop:- nginx- httpdwhen: ansible_facts['os_family'] == 'RedHat'
3.2 条件限制循环中的每个项
根据条件跳过部分项:
- name: Install selected packagesyum:name: "{{ item.name }}"state: presentloop:- { name: "nginx", enabled: true }- { name: "httpd", enabled: false }when: item.enabled
4. 生产环境实例:高效服务部署
以下是一个生产环境中的完整示例,展示如何结合条件和循环部署不同类型的服务。
需求:
在 web 主机组上部署 Nginx。
在 db 主机组上部署 MySQL。
针对不同主机分配特定的配置文件。
解决方案:
- name: Deploy services based on roleshosts: alltasks:- name: Install Nginx on web serversyum:name: nginxstate: presentwhen: "'web' in group_names"- name: Install MySQL on db serversyum:name: mysql-serverstate: presentwhen: "'db' in group_names"- name: Configure web serverscopy:src: "/configs/nginx/{{ inventory_hostname }}.conf"dest: /etc/nginx/nginx.confwhen: "'web' in group_names"- name: Configure db serverscopy:src: "/configs/mysql/{{ inventory_hostname }}.cnf"dest: /etc/my.cnfwhen: "'db' in group_names"
本文先介绍到这里
