playbook

一、 核心定位:剧本 vs. 临时命令

要理解 Playbook,首先要区分它与 Ad-Hoc 命令(如 ansible all -m ping)的区别:

  • Ad-Hoc 命令:适合临时、一次性的任务(如重启服务、查看进程)。是一条命令。

  • Playbook :适合复杂、重复、需要长期维护的任务。它是一个脚本文件

核心优势:

  1. 幂等性:这是 Playbook 最重要的特性。意思是,同一个 Playbook 执行 1 次和执行 10 次的结果应该是一样的。只有状态不符合定义时才会修改,符合定义时则跳过。这保证了服务器配置不会因为重复执行而错乱。

  2. 结构化:像代码一样管理基础设施(IaC)。

  3. 编排:可以定义复杂的执行流程(先配置 Web,后配置 DB,发邮件通知等)。


二、 语法基础:YAML

Playbook 严格遵循 YAML 语法。

关键点:

  • 缩进 :必须使用空格,不能使用 Tab。通常缩进为 2 个空格。

  • 短横线- 用于表示列表(List/Array)。

  • 冒号: 用于表示字典(Key/Value)。冒号后面必须跟一个空格。


三、 Playbook 的核心构成(重点)

一个 Playbook 文件通常包含一个或多个 Play 。每个 Play 对应在一组主机上执行的一系列 Task(任务)。

1. Play 定义

每个 Play 通常由以下几个顶级关键字构成:

关键字 作用 示例
name 描述这个 Play 的作用(虽然不是强制,但必须写,用于日志输出) name: Install and configure web server
hosts 目标主机。指定哪些主机执行该 Play。 hosts: webservers (对应 inventory 中的组)
become 权限提升。是否需要 sudo 或 root 权限。 become: yes
vars 定义该 Play 内使用的变量。 vars: http_port: 80
tasks 核心。要执行的具体任务列表。 见下文
handlers 特殊任务。只在被通知时触发(通常用于重启服务)。 见下文
2. Tasks (任务)

Tasks 是一个列表,从上到下按顺序执行。每个 Task 必须包含一个 模块 的名称。

Task 的结构:

yaml

复制代码
tasks:
  - name: 确保 Nginx 已安装   # 任务名称
    ansible.builtin.yum:      # 使用的模块
      name: nginx
      state: present
    # 注意:模块的参数是缩进在模块名下面的

关键概念:幂等性

  • 模块必须支持幂等性。

  • 例如:state: present。如果 Nginx 已经安装了,这个 Task 会返回 ok(绿色)且不会再次安装。

3. Handlers (触发器)

Handlers 与普通 tasks 类似,但只有在被 task 通知时才会执行 ,并且只在所有 tasks 执行完毕后的最后执行

典型场景:配置文件变了,才重启服务。

yaml

复制代码
tasks:
  - name: 更新 Nginx 配置
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: 重启 Nginx      # 通知 handler

handlers:
  - name: 重启 Nginx
    ansible.builtin.service:
      name: nginx
      state: restarted
  • 注意 :如果配置文件没变,notify 不会被触发,Nginx 就不会被重启。这避免了不必要的服务中断。

四、 变量 (Variables) ------ 灵活性的核心

Playbook 中的变量优先级非常复杂,但必须掌握以下几种常用定义方式:

  1. Play 内定义 (vars):

    yaml

    复制代码
    vars:
      package_name: nginx
  2. 文件引用 (vars_files):

    yaml

    复制代码
    vars_files:
      - vars/redhat.yml   # 引入外部变量文件
  3. 主机清单定义 (Inventory):

    ini

    复制代码
    [webservers]
    192.168.1.10 http_port=8080
  4. 注册变量 (Register):捕获命令执行结果,供后续任务使用。

    yaml

    复制代码
    tasks:
      - name: 查看文件内容
        ansible.builtin.shell: cat /etc/hostname
        register: hostname_result
      
      - name: 打印结果
        ansible.builtin.debug:
          msg: "主机名是 {{ hostname_result.stdout }}"

五、 控制流程 (重点)

Playbook 不仅仅是顺序执行,还支持复杂的逻辑。

1. 条件判断 (when)

极其常用,用于区分操作系统版本、判断变量是否存在等。

yaml

复制代码
tasks:
  - name: 在 CentOS 上安装 httpd
    ansible.builtin.yum:
      name: httpd
    when: ansible_facts['os_family'] == "RedHat"

  - name: 在 Ubuntu 上安装 apache2
    ansible.builtin.apt:
      name: apache2
    when: ansible_facts['os_family'] == "Debian"
2. 循环 (loop)

取代了旧版的 with_items

yaml

复制代码
tasks:
  - name: 创建多个用户
    ansible.builtin.user:
      name: "{{ item }}"
      state: present
    loop:
       - alice
       - bob
       - charlie
3. 块 (Blocks)

用于组合 tasks,进行分组或异常处理(类似编程中的 try-catch-finally)。

yaml

复制代码
tasks:
  - block:
      - name: 安装软件包
        ansible.builtin.yum:
          name: "{{ package }}"
      - name: 复制配置文件
        ansible.builtin.template:
          src: app.conf.j2
          dest: /etc/app.conf
    rescue:
      - name: 如果上面报错,执行回滚
        ansible.builtin.debug:
          msg: "安装失败,执行清理"
    always:
      - name: 无论是否报错,最后都会执行
        ansible.builtin.debug:
          msg: "任务结束"

六、 模板 (Templates) ------ Jinja2

Playbook 通常结合 Jinja2 模板引擎来动态生成配置文件。

  • 文件后缀通常为 .j2

  • 使用 template 模块。

模板示例 (nginx.conf.j2):

jinja2

复制代码
# 动态渲染端口
server {
    listen {{ http_port }};
    server_name {{ server_name }};
    
    # 循环渲染
    {% for item in whitelist_ips %}
    allow {{ item }};
    {% endfor %}
}

Playbook 调用:

yaml

复制代码
- name: 部署动态配置
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: 重启 Nginx

七、 复用与组织 (Roles)

当 Playbook 变得庞大(超过几百行)时,必须使用 Roles(角色)。这是生产环境的标准实践。

Roles 是一种文件目录结构,它将变量、任务、处理器、模板等自动组合在一起。

目录结构:

text

复制代码
roles/
  common/               # 角色名
    tasks/              # 包含 main.yml
      main.yml
    handlers/           # 包含 main.yml
    templates/          # .j2 文件
    files/              # 普通文件
    vars/               # 优先级较高的变量
    defaults/           # 优先级最低的默认变量
  webserver/            # 另一个角色
    ...

Playbook 引用 Roles:

yaml

复制代码
- name: 应用配置
  hosts: all
  roles:
    - common          # 先执行通用角色
    - webserver       # 再执行 Web 角色

八、 执行与调试

1. 执行命令

bash

复制代码
# 检查语法 (强烈推荐)
ansible-playbook site.yml --syntax-check

# 模拟执行 (Dry Run),查看会改变什么,但不实际执行
ansible-playbook site.yml --check

# 执行并询问 sudo 密码
ansible-playbook site.yml --ask-become-pass

# 指定标签执行
ansible-playbook site.yml --tags "nginx"
2. 调试技巧
  • debug 模块:打印变量。

    yaml

    复制代码
    - name: 打印变量
      ansible.builtin.debug:
        var: my_var
  • ansible.builtin.setup:获取目标主机的 Facts(IP、OS、内存等)。

  • -v / -vvv :增加输出详细程度,-vvv 可以看到 SSH 传输的原始数据。


九、 总结:优秀 Playbook 的编写原则

  1. 幂等性第一 :确保同一个脚本运行多次结果唯一。避免使用 shell/command 模块做那些"非幂等"的操作(如 mkdir),优先使用 file 模块。

  2. 命名清晰 :所有 name 字段都要写得清晰明了,因为执行时会打印出来,方便排查日志。

  3. 利用 Facts :尽量使用 ansible_facts 来适配不同的操作系统,而不是写死逻辑。

  4. 版本控制:Playbook 是代码,必须放在 Git 仓库中管理。

  5. 分层结构

    • 简单的几个任务 -> Playbook 文件。

    • 复杂的应用栈 -> Roles。

如果你刚入门,建议先手写一个最简单的 Playbook(例如:安装并启动 Nginx),然后逐步引入变量、Handlers 和 Templates,最后再学习 Role 的组织方式。

相关推荐
我爱学习好爱好爱2 小时前
Ansible 入门:ad-hoc 临时命令与常用模块
linux·服务器·ansible
s09071362 小时前
【Zynq 进阶一】深度解析 PetaLinux 存储布局:NAND Flash 分区与 DDR 内存分配全攻略
linux·fpga开发·设备树·zynq·nand flash启动·flash分区
lwx9148522 小时前
Linux-sftp命令详解
linux·运维·服务器
珠海西格2 小时前
四可装置如何监测组件衰减与逆变器效率?
大数据·运维·服务器·分布式·能源
oi..2 小时前
Flag入门—Flag在返回包中
网络·笔记·测试工具·安全·网络安全
Zacks_xdc2 小时前
【全栈】云服务器安装 MySQL + Next.js 连接完整 Demo
服务器·javascript·mysql·阿里云·nextjs·云服务器
wang09072 小时前
Linux性能优化之平均负载
linux·数据库·性能优化
BieberChen3 小时前
ubuntu定时执行脚本---crontab详细使用指南
linux·运维·ubuntu