Ansible-Playbook 剧本编写全攻略:从入门到进阶

目录

前言

[一、Playbook 的结构](#一、Playbook 的结构)

[二、Ansible Playbook 示例](#二、Ansible Playbook 示例)

[三、命令行运行 Playbook](#三、命令行运行 Playbook)

四、变量和引用

[1. 变量定义方式](#1. 变量定义方式)

主机和组变量定义

变量使用示例

变量继承说明

执行结果

[2. 内置变量](#2. 内置变量)

[五、条件判断 when](#五、条件判断 when)

常用示例

[六、迭代:使用 with_items 或 loop](#六、迭代:使用 with_items 或 loop)

[1. loop 示例(推荐)](#1. loop 示例(推荐))

[2. with_items 示例(旧版)](#2. with_items 示例(旧版))

[3. 遍历字典列表](#3. 遍历字典列表)

[七、Templates 模块](#七、Templates 模块)

核心步骤

[示例:动态生成 Nginx 虚拟主机配置](#示例:动态生成 Nginx 虚拟主机配置)

[八、Tags 模块](#八、Tags 模块)

使用示例

常用命令

[九、Roles 模块](#九、Roles 模块)

[1. Roles 目录结构](#1. Roles 目录结构)

[2. 编写 Roles 示例(以 nginx Role 为例)](#2. 编写 Roles 示例(以 nginx Role 为例))

[3. 调用 Roles](#3. 调用 Roles)

[基础部署 Nginx 服务的 Playbook](#基础部署 Nginx 服务的 Playbook)

[带变量覆盖的进阶 Playbook](#带变量覆盖的进阶 Playbook)

目录结构建议

[4. Roles 依赖](#4. Roles 依赖)

总结


前言

Ansible 作为一款轻量级的自动化运维工具,其核心优势之一便是通过 Playbook 实现任务的编排与自动化执行。相较于单条 ad-hoc 命令,Playbook 支持更复杂的逻辑控制、变量引用、模块组合等功能,是实现批量部署、配置管理、任务自动化的关键。本文将从 Playbook 核心结构出发,逐步讲解编写技巧、核心功能及进阶用法,带你轻松掌握剧本编写精髓。

一、Playbook 的结构

Playbook 本质是遵循 YAML 语法的文本文件,其核心结构层层嵌套,清晰明了。一个完整的 Playbook 通常包含以下几个核心组件:

  1. Play :Playbook 的最小执行单元,定义了"在哪些主机上执行哪些任务"。一个 Playbook 可以包含多个 Play,实现多主机、多任务的批量编排。每个 Play 必须包含 hosts(目标主机)和 tasks(任务列表)两个核心字段。

  2. Hosts :指定 Play 执行的目标主机,需与 Ansible inventory(主机清单)中的主机名/组名对应,支持通配符(如 webservers*.test.com)。

  3. Tasks :任务列表,每个任务对应一个 Ansible 模块(如 yum 安装软件、copy 复制文件),任务按顺序执行,前一个任务失败则后续任务终止。每个任务需指定name(任务描述,可选但推荐)和模块参数。

  4. Variables:变量定义,用于存储可复用的值(如软件版本、文件路径),支持在 Play 内定义、从 inventory 继承、通过命令行传递等多种方式。

  5. Handlers :触发器,用于响应任务的状态变化(如配置文件修改后重启服务)。只有当任务通过notify 调用且任务状态为 changed 时,Handlers 才会执行,且多个任务触发同一 Handler 时,Handler 仅执行一次。

  6. Roles:角色,用于将 Playbook 按功能拆分(如 web 角色、db 角色),实现代码复用与模块化管理,是 Playbook 进阶编写的核心。

YAML 语法注意事项:缩进统一使用 2 个空格(禁止使用 Tab);键值对冒号后需加空格(如 hosts: webservers);列表项以 - 开头,后跟空格。

二、Ansible Playbook 示例

以下是一个基础的 Playbook 示例,实现"在 web 服务器上安装 Nginx 并启动服务"的功能,文件名保存为 install_nginx.yml

yaml 复制代码
- name: 安装并启动 Nginx
  hosts: webservers
  remote_user: root
  
  tasks:
    - name: 安装 Nginx 软件
      yum:
        name: nginx
        state: present
    
    - name: 复制 Nginx 配置文件
      copy:
        src: ./nginx.conf
        dest: /etc/nginx/nginx.conf
        mode: 0644
      notify: restart nginx
    
    - name: 启动 Nginx 服务并设置开机自启
      service:
        name: nginx
        state: started
        enabled: yes
  
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted
 

该示例包含 1 个 Play、3 个任务和 1 个 Handler,逻辑清晰:先安装 Nginx,再复制配置文件(配置变化则触发重启),最后启动服务并设置开机自启。

三、命令行运行 Playbook

编写完 Playbook 后,通过 ansible-playbook 命令执行,核心语法如下:

ansible-playbook [选项] 剧本文件名.yml

常用选项说明:

  • -i <inventory_path>:指定主机清单路径,默认路径为 /etc/ansible/hosts。例:ansible-playbook -i ./my_hosts install_nginx.yml

  • -u <remote_user>:指定远程执行用户,优先级高于 Playbook 中定义的 remote_user。例:ansible-playbook -u centos install_nginx.yml

  • --become:切换到 root 权限执行(sudo),如需指定 sudo 密码,可加 --ask-become-pass(缩写 -K)。例:ansible-playbook --become -K install_nginx.yml

  • --check:模拟执行(干跑),不实际修改目标主机,用于验证 Playbook 语法和逻辑。例:ansible-playbook --check install_nginx.yml

  • --tags <tag_name>:仅执行指定标签的任务(后续 Tags 模块详解)。例:ansible-playbook --tags install install_nginx.yml

  • -e <key=value>:传递额外变量(优先级最高)。例:ansible-playbook -e "nginx_version=1.24" install_nginx.yml

执行成功后,终端会输出每个任务的执行状态(ok:无变化,changed:有修改,failed:失败),以及最终的执行统计信息。

四、变量和引用

变量是 Playbook 复用性的核心,支持多种定义方式,引用时使用 {``{ 变量名 }} 语法。

1. 变量定义方式

  • Play 内定义 :通过 vars 字段定义,作用域仅限于当前 Play。示例:

    yaml 复制代码
    - name: 测试变量
      hosts: webservers
      vars:
        nginx_version: 1.24
        nginx_conf_path: /etc/nginx/nginx.conf
      
      tasks:
        - name: 安装指定版本 Nginx
          yum:
            name: nginx-{{ nginx_version }}
            state: present
        
        - name: 验证配置文件路径
          file:
            path: "{{ nginx_conf_path }}"
            state: file
     
  • Inventory 中定义:在主机清单中为主机/组定义变量,作用域为对应主机/组。示例(inventory 文件):

    主机和组变量定义

    以下代码实现了在Ansible中定义主机级变量和组级变量的功能:

    ini 复制代码
    [webservers]
    web1.test.com nginx_version=1.24 # 主机级变量
    web2.test.com nginx_version=1.23
    
    [webservers:vars]
    nginx_conf_path=/etc/nginx/nginx.conf # 组级变量,所有webservers主机继承

    变量使用示例

    在playbook中可以通过以下方式引用这些变量:

    yaml 复制代码
    - hosts: webservers
      tasks:
        - name: Display Nginx version
          debug:
            msg: "Nginx version is {{ nginx_version }}"
    
        - name: Display Nginx config path
          debug:
            msg: "Nginx config path is {{ nginx_conf_path }}"

    变量继承说明

    组级变量nginx_conf_path会被所有webservers组中的主机继承,而主机级变量nginx_version则只对特定主机有效。

    执行结果

    当运行上述playbook时:

  • 对于web1.test.com会显示:

    复制代码
    Nginx version is 1.24
    Nginx config path is /etc/nginx/nginx.conf
  • 对于web2.test.com会显示:

    复制代码
    Nginx version is 1.23
    Nginx config path is /etc/nginx/nginx.conf
  • 命令行传递 :通过 -e 选项传递,优先级最高,会覆盖其他方式定义的同名变量。示例:ansible-playbook -e "nginx_version=1.25" install_nginx.yml

  • 变量文件引入 :将变量写入独立 YAML 文件(如 vars.yml),通过 vars_files 引入,适合变量较多的场景。示例:

    yaml 复制代码
    nginx_version: 1.24
    nginx_conf_path: /etc/nginx/nginx.conf
     
    yaml 复制代码
    - name: 引入变量文件
      hosts: webservers
      vars_files:
        - ./vars.yml
    
      tasks:
        - name: 安装 Nginx
          yum:
            name: nginx-{{ nginx_version }}
            state: present
    
        - name: 确保 Nginx 配置文件存在
          file:
            path: "{{ nginx_conf_path }}"
            state: touch
    
        - name: 启动 Nginx 服务
          service:
            name: nginx
            state: started
            enabled: yes
     

2. 内置变量

Ansible 提供大量内置变量( Facts ),用于获取目标主机的系统信息(如 IP、系统版本、内存等),可通过 ansible <host> -m setup 命令查看所有 Facts。常用内置变量:

  • {``{ ansible_fqdn }}:目标主机的完全限定域名

  • {``{ ansible_default_ipv4.address }}:目标主机的默认 IPv4 地址

  • {``{ ansible_os_family }}:目标主机的系统家族(如 RedHat、Debian)

五、条件判断 when

通过 when 关键字实现条件判断,仅当条件满足时,任务才会执行。when 支持多种条件表达式(比较运算、逻辑运算、内置变量判断等)。

常用示例

  1. 根据系统类型执行不同任务(区分 CentOS 和 Ubuntu):

    yaml 复制代码
    - name: 条件判断示例
      hosts: all
      tasks:
        - name: CentOS 系统安装 Nginx
          yum:
            name: nginx
            state: present
          when: ansible_os_family == "RedHat"
    
        - name: Ubuntu 系统安装 Nginx
          apt:
            name: nginx
            state: present
            update_cache: yes
          when: ansible_os_family == "Debian"
     
  2. 逻辑运算条件(and/or/not):

    yaml 复制代码
    - name: 逻辑运算条件
      hosts: webservers
      vars:
        env: prod  # 环境变量:prod生产环境,test测试环境
      
      tasks:
        - name: 生产环境且系统为CentOS时执行
          yum:
            name: nginx
            state: present
          when: env == "prod" and ansible_os_family == "RedHat"
     
  3. 判断变量是否存在

    yaml 复制代码
    - name: 判断变量是否存在
      hosts: webservers
      tasks:
        - name: 变量存在时执行
          debug:
            msg: "Nginx版本:{{ nginx_version }}"
          when: nginx_version is defined
    
        - name: 变量不存在时执行
          debug:
            msg: "nginx_version变量未定义"
          when: nginx_version is not defined
     

六、迭代:使用 with_items 或 loop

当需要重复执行同一类任务(如安装多个软件、创建多个目录)时,可通过迭代功能简化代码。Ansible 支持 with_items(旧版,仍常用)和 loop(新版,推荐)两种方式,本质都是遍历列表数据。

1. loop 示例(推荐)

遍历列表,安装多个软件:

yaml 复制代码
- name: 迭代安装基础软件  
  hosts: webservers  
  tasks:  
    - name: 通过yum安装软件包  
      yum:  
        name: "{{ item }}"  
        state: present  
      loop:  
        - nginx  
        - mysql-server  
        - php-fpm  
      loop_control:  
        label: "{{ item }}"  
 

2. with_items 示例(旧版)

功能与 loop 类似,语法略有差异:

yaml 复制代码
- name: 迭代示例(with_items)
  hosts: webservers
  tasks:
    - name: 创建多个目录
      file:
        path: "{{ item }}"
        state: directory
        mode: 0755
      with_items:
        - /etc/nginx/conf.d
        - /var/log/nginx
        - /usr/share/nginx/html
 

3. 遍历字典列表

当需要传递多个参数时,可遍历字典列表:

yaml 复制代码
- name: 遍历字典列表创建用户并指定组
  hosts: webservers
  tasks:
    - name: 创建多个用户并指定组
      user:
        name: "{{ item.name }}"
        group: "{{ item.group }}"
        state: present
      loop:
        - { name: "nginx", group: "nginx" }
        - { name: "php", group: "php" }
        - { name: "mysql", group: "mysql" }
 

七、Templates 模块

Templates 模块用于将本地的 Jinja2 模板文件渲染到目标主机,支持在模板中嵌入变量、条件判断、循环等逻辑,适合动态生成配置文件(如 Nginx 虚拟主机配置、MySQL 配置等)。

核心步骤

  1. 创建 Jinja2 模板文件(后缀通常为 .j2),在模板中嵌入变量或逻辑。

  2. 使用 template 模块将模板渲染到目标主机。

示例:动态生成 Nginx 虚拟主机配置

  1. 创建 Jinja2 模板nginx_vhost.j2):

    nginx 复制代码
    server {
        listen {{ nginx_listen_port }};
        server_name {{ ansible_default_ipv4.address }};
        root {{ nginx_root_dir }};
        index index.html index.php;
    
        {% if enable_ssl %}
        listen 443 ssl;
        ssl_certificate {{ ssl_cert_path }};
        ssl_certificate_key {{ ssl_key_path }};
        {% endif %}
    }
     
  2. Playbook 中使用 template 模块

    yaml 复制代码
    - name: 使用 Templates 模块
      hosts: webservers
      vars:
        nginx_listen_port: 80
        nginx_root_dir: /usr/share/nginx/html
        enable_ssl: false  # 不启用SSL
      
      tasks:
        - name: 渲染 Nginx 虚拟主机配置
          template:
            src: ./nginx_vhost.j2  # 本地模板文件路径
            dest: /etc/nginx/conf.d/default.conf  # 远程目标配置文件
            mode: 0644
          notify: restart nginx  # 配置变化触发重启
      
      handlers:
        - name: restart nginx
          service:
            name: nginx
            state: restarted
     

八、Tags 模块

Tags 用于为 Play 或任务添加"标签",执行 Playbook 时可通过 --tags--skip-tags 选项指定执行/跳过的任务,适合在复杂 Playbook 中仅执行部分任务(如仅安装软件、仅更新配置)。

使用示例

yaml 复制代码
- name: Nginx 部署与管理
  hosts: webservers
  
  tasks:
    - name: 安装 Nginx 软件包
      yum:
        name: nginx
        state: present
      tags: 
        - install
        - package

    - name: 部署 Nginx 配置文件
      template:
        src: ./templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      tags:
        - config
        - deploy
      notify: reload nginx

    - name: 确保 Nginx 服务运行
      service:
        name: nginx
        state: started
        enabled: yes
      tags:
        - service
        - start

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

常用命令

  • 仅执行 install 标签的任务:ansible-playbook --tags install install_nginx.yml

  • 执行 installconfig 标签的任务:ansible-playbook --tags "install,config" install_nginx.yml

  • 跳过 restart 标签的任务:ansible-playbook --skip-tags restart install_nginx.yml

  • 执行所有任务(默认):ansible-playbook install_nginx.yml

九、Roles 模块

当 Playbook 越来越复杂时,通过 Roles 可实现"功能模块化拆分",将不同功能的任务、变量、模板等按固定目录结构组织,实现代码复用、团队协作和简化维护。Roles 是 Ansible 规模化部署的核心。

1. Roles 目录结构

Roles 有固定的目录规范,每个 Role 对应一个目录,目录名即为 Role 名。标准结构如下:

stylus 复制代码
roles/
└── nginx/
    ├── defaults/
    │   └── main.yml
    ├── vars/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── handlers/
    │   └── main.yml
    ├── templates/
    │   └── nginx.conf.j2
    ├── files/
    │   └── index.html
    └── meta/
        └── main.yml
 

说明:每个目录下的 main.yml 是入口文件,Ansible 会自动加载该文件中的内容。

2. 编写 Roles 示例(以 nginx Role 为例)

  1. tasks/main.yml(核心任务):

    yaml 复制代码
    - name: 安装 Nginx
      yum:
        name: nginx-{{ nginx_version }}
        state: present
    
    - name: 复制 Nginx 配置文件(模板渲染)
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        mode: 0644
      notify: restart nginx
    
    - name: 复制首页静态文件
      copy:
        src: index.html
        dest: "{{ nginx_root_dir }}/index.html"
        mode: 0644
    
    - name: 启动 Nginx 服务
      service:
        name: nginx
        state: started
        enabled: yes
     
  2. vars/main.yml (自定义变量): nginx_version: 1.24 ``nginx_root_dir: /usr/share/nginx/html ``nginx_listen_port: 80

  3. handlers/main.yml (触发器): - name: restart nginx `` service: `` name: nginx `` state: restarted

3. 调用 Roles

编写 Playbook(site.yml)调用 nginx Role:

基础部署 Nginx 服务的 Playbook

yaml 复制代码
- name: 部署 Nginx 服务
  hosts: webservers
  roles:
    - nginx

带变量覆盖的进阶 Playbook

yaml 复制代码
- name: 部署 Nginx 服务(自定义变量)
  hosts: webservers
  roles:
    - role: nginx
      vars:
        nginx_version: 1.25
        nginx_listen_port: 8080
 

目录结构建议

复制代码
roles/
└── nginx/
    ├── tasks/
    │   └── main.yml
    ├── defaults/
    │   └── main.yml
    ├── vars/
    │   └── main.yml
    └── templates/
        └── nginx.conf.j2

执行命令:ansible-playbook -i ./inventory site.yml

4. Roles 依赖

若一个 Role 依赖其他 Role(如 nginx Role 依赖 firewalld Role 开放端口),可在 meta/main.yml 中定义依赖:

复制代码

# nginx/meta/main.yml dependencies: - role: firewalld # 依赖 firewalld Role firewalld_ports: - 80/tcp - 443/tcp

执行 nginx Role 时,Ansible 会自动先执行依赖的 firewalld Role。

总结

Ansible-Playbook 剧本编写的核心是掌握 YAML 语法和核心组件(Play、Tasks、Variables 等),再通过条件判断、迭代、模板等功能实现复杂逻辑,最终通过 Roles 实现模块化和规模化部署。本文从基础到进阶,覆盖了 Playbook 编写的全流程要点,建议结合实际场景多动手练习(如部署 Nginx、MySQL 等服务),才能快速掌握。如果需要进一步深入,可学习 Ansible 的变量优先级、加密变量(Vault)、动态 Inventory 等高级功能。

相关推荐
青山如墨雨如画2 小时前
【北邮-研-图论】网络最大流的标号算法V1.0
网络·算法·图论·北邮
Joren的学习记录2 小时前
【Linux运维大神系列】docker详解(三)
linux·运维·docker
一岁天才饺子2 小时前
SSRF漏洞绕过与漏洞解决
网络·网络安全·ssrf
怪我冷i2 小时前
最像 Windows 的 Linux 发行版 —— Zorin OS 18 vmware17 安装与体验
linux·ai写作
AI即插即用2 小时前
即插即用系列 | CMPB PMFSNet:多尺度特征自注意力网络,打破轻量级医学图像分割的性能天花板
网络·图像处理·人工智能·深度学习·神经网络·计算机视觉·视觉检测
j_xxx404_2 小时前
Linux:版本控制器Git(第一章)|历史|理解Git|相关git操作|提交冲突解决
linux·运维·git·ai
apihz2 小时前
全球IP归属地查询免费API详细指南
android·服务器·网络·网络协议·tcp/ip
Robot侠2 小时前
ROS1从入门到精通 1 :ROS1简介与环境搭建(Ubuntu 20.04 + Noetic完整指南)
linux·ubuntu·ros·机器人操作系统
雨落秋垣3 小时前
五台腾讯云轻量服务器高可用架构方案(宝塔面板+宝塔WAF)
服务器·架构·腾讯云