
本文将详细讲解 Ansible 中条件语句与循环的用法,并结合生产环境实例,展示如何高效地自动化日常运维任务。
1. 条件语句(Conditionals)
在实际场景中,任务的执行往往依赖于特定的条件,例如主机的系统版本、硬件配置、网络状态等。Ansible 提供了 when 关键字用于条件控制。
1.1 基本语法
- name: Task description
module_name:
key: value
when:
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']
高内存主机加载性能优化的配置文件,低内存主机使用精简版配置。
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"
本文先介绍到这里
如有帮助,请点个赞和“在看”!如有不足,敬请指出!感谢你的关注与支持。
路虽远,行则将至!
事虽难,做则必成!共勉!