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 等高级功能。

相关推荐
一叶龙洲1 天前
wslg打开Ubuntu24.04默认打开图形界面
linux·服务器·数据库·ubuntu
星恒讯工业路由器1 天前
5G FWA技术演进与趋势
网络·5g·信息与通信·4g·5g fwa·3gpp规范·fwa趋势
敖行客 Allthinker1 天前
Parallels Ubuntu虚拟机项目如何让手机访问?完整解决方案
linux·运维·ubuntu
keyipatience1 天前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
j7~1 天前
【Linux】二十二.《Linux 信号机制完全指南:表示、捕捉与处理》
linux·信号处理·volatile·可入重函数·保存信号
踏月的造梦星球1 天前
达梦数据库执行计划与性能分析入门:EXPLAIN、AUTOTRACE 与 ET
服务器·数据库·oracle
观山岳五楼1 天前
Ubuntu 24 怎么使用Ubuntu 20 的镜像源
linux·运维·ubuntu
星夜夏空991 天前
网络编程(1)
服务器·网络
川石课堂软件测试1 天前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
上海云盾-小余1 天前
中小站点防护避坑:低价高防服务存在的各类安全短板剖析
网络·爬虫·安全·ddos