Ansible自动化运维实战:批量配置管理与Playbook编写规范

Ansible架构与Inventory主机清单配置

Ansible是无代理自动化运维工具,通过SSH连接目标主机执行配置任务,不需要在目标机器安装客户端。核心架构包括控制节点(运行Ansible的机器)、Inventory(主机清单)和Playbook(任务编排文件)。

Inventory文件定义被管理主机的分组和连接参数。静态Inventory使用INI格式:

# /etc/ansible/hosts
[web_servers]
web1 ansible_host=192.168.1.11 ansible_user=root
web2 ansible_host=192.168.1.12 ansible_user=root

[db_servers]
db1 ansible_host=192.168.1.21 ansible_user=postgres ansible_port=2222

[prod:children]
web_servers
db_servers

方括号定义主机组,ansible_host指定IP,ansible_user指定SSH用户,ansible_port指定非默认SSH端口。[group:children]定义主机组嵌套,prod组包含web_serversdb_servers的所有主机。

动态Inventory适用于云环境,主机列表从云平台API动态获取:

#!/usr/bin/env python3
import json, requests

def get_inventory():
    r = requests.get("http://consul:8500/v1/catalog/nodes")
    hosts = {"web_servers": {"hosts": [], "vars": {}}, "db_servers": {"hosts": []}}
    for node in r.json():
        if "web" in node["Node"]:
            hosts["web_servers"]["hosts"].append(node["Address"])
        elif "db" in node["Node"]:
            hosts["db_servers"]["hosts"].append(node["Address"])
    return hosts

if __name__ == "__main__":
    print(json.dumps(get_inventory(), indent=2))

使用动态Inventory时,ansible-inventory --list -i dynamic_inventory.py验证主机列表是否正确解析。

Playbook核心语法与模块使用

Playbook是YAML格式的任务编排文件,每个Play定义对哪些主机执行哪些任务。基础结构:

---
- name: 部署Nginx Web服务器
  hosts: web_servers
  become: yes
  tasks:
    - name: 安装Nginx
      apt:
        name: nginx
        state: present
        update_cache: yes

    - name: 配置Nginx站点
      copy:
        src: files/nginx.conf
        dest: /etc/nginx/sites-available/app.conf
        mode: '0644'
      notify: reload nginx

    - name: 启用站点配置
      file:
        src: /etc/nginx/sites-available/app.conf
        dest: /etc/nginx/sites-enabled/app.conf
        state: link

    - name: 确保Nginx运行
      service:
        name: nginx
        state: started
        enabled: yes

become: yes提权执行(等同于sudo),notify触发handler,service模块管理服务状态。常用模块包括:apt/yum(包管理)、copy/template(文件分发)、service/systemd(服务管理)、file(文件操作)、shell/command(命令执行)。

template模块支持Jinja2模板渲染,配置文件中可引用变量:

# templates/nginx.conf.j2
server {
    listen {{ nginx_port }};
    server_name {{ server_name }};
    location / {
        proxy_pass http://{{ backend_host }}:{{ backend_port }};
        proxy_set_header Host $host;
    }
}

变量管理:vars、register与facts机制

Ansible变量来源优先级从低到高:Inventory文件vars、Playbook中vars、命令行--extra-vars。在Playbook中定义变量:

- name: 配置数据库服务器
  hosts: db_servers
  vars:
    postgres_version: "15"
    max_connections: 200
    shared_buffers: "4GB"
  vars_files:
    - vars/{{ ansible_os_family }}.yml
  tasks:
    - name: 安装PostgreSQL
      apt:
        name: "postgresql-{{ postgres_version }}"
        state: present

vars_files按操作系统加载不同变量文件,ansible_os_family是Ansible自动收集的facts变量。setup模块收集目标主机信息:

# 查看所有facts
$ ansible db_servers -m setup

# 筛选特定facts
$ ansible db_servers -m setup -a "filter=ansible_memory*"
# 返回: "ansible_memory_mb": {"real": {"total": 32768, "used": 8192, "free": 24576}}

register捕获任务输出到变量,后续任务可引用:

tasks:
  - name: 检查磁盘空间
    shell: df -h / | tail -1 | awk '{print $5}' | tr -d '%'
    register: disk_usage
    changed_when: false

  - name: 磁盘空间告警
    debug:
      msg: "磁盘使用率 {{ disk_usage.stdout }}%,超过阈值"
    when: disk_usage.stdout | int > 80

changed_when: false标记该任务不改变系统状态(只读操作),避免Ansible报告变更。when条件判断基于register变量值决定是否执行后续任务。

Roles角色复用与目录结构规范

Role是Playbook的模块化封装,将变量、任务、模板、文件按固定目录组织,便于复用和分享。标准Role目录结构:

roles/nginx/
  defaults/main.yml    # 默认变量(优先级最低,可被覆盖)
  vars/main.yml        # 角色变量(优先级高于defaults)
  tasks/main.yml       # 主任务列表
  handlers/main.yml    # 触发器
  templates/nginx.conf.j2  # Jinja2模板
  files/nginx.repo     # 静态文件
  meta/main.yml        # 角色元数据与依赖

在Playbook中引用Role:

- name: 部署Web集群
  hosts: web_servers
  become: yes
  roles:
    - role: nginx
      vars:
        nginx_port: 8080
    - role: logrotate
  tasks:
    - name: 验证服务状态
      uri:
        url: "http://{{ ansible_host }}:8080/health"
        status_code: 200

role关键字后跟角色名,vars为该Role传递参数覆盖defaults/main.yml中的默认值。Role执行顺序:meta依赖、defaults、tasks、handlers。用ansible-galaxy init nginx命令自动生成Role骨架。

Handlers触发机制与条件判断控制

Handler是被notify触发的任务,只在被通知时执行,且在Play中所有普通任务完成后统一执行。这一机制适用于服务重启场景——配置文件变更后才需要重启服务,避免每次执行都重启:

tasks:
  - name: 修改Nginx配置
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: reload nginx

  - name: 添加虚拟主机
    template:
      src: vhost.conf.j2
      dest: /etc/nginx/conf.d/app.conf
    notify: reload nginx

handlers:
  - name: reload nginx
    service:
      name: nginx
      state: reloaded

上述Playbook中两个任务都通知reload nginx,但handler只执行一次。Handler名称必须唯一,notify的名称与handlers中定义的name精确匹配。

when条件控制任务执行,支持Jinja2表达式:

tasks:
  - name: Debian系安装
    apt: name=nginx state=present
    when: ansible_os_family == "Debian"

  - name: RHEL系安装
    yum: name=nginx state=present
    when: ansible_os_family == "RedHat"

  - name: 仅在主节点执行
    shell: init_database.sh
    when: inventory_hostname == groups['db_servers'][0]

loop循环处理批量操作,减少重复任务定义:

tasks:
  - name: 创建多个用户
    user:
      name: "{{ item.name }}"
      groups: "{{ item.groups }}"
      shell: /bin/bash
    loop:
      - { name: "deploy", groups: "www-data" }
      - { name: "monitor", groups: "adm" }
      - { name: "backup", groups: "backup" }

Ansible执行前用--check参数做dry-run预演,不实际修改系统:ansible-playbook deploy.yml --check。配合--diff参数可以查看将要变更的内容,在生产环境部署前验证Playbook影响范围。批量执行时用--forks控制并发数,默认5个主机并行,大规模集群可以调到20-50以加快执行速度,但需评估SSH连接和控制节点的负载承受能力。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/ansible-zi-dong-hua-yun-wei-shi-zhan-pi-liang-pei-zhi-guan/

(0)
小编小编
上一篇 1小时前
下一篇 1小时前

相关推荐