# Ansible Playbook编写详细教程

Ansible是一种强大的自动化工具,而Playbook是Ansible的核心组件,用于定义自动化任务的配置和执行流程。本教程将详细介绍如何编写高效、可维护的Ansible Playbook,包含基础概念、语法结构、常用模块以及最佳实践。

1. Ansible Playbook基础

Playbook是Ansible的核心配置、部署和编排语言,它使用YAML格式编写,描述了在一组主机上执行的任务序列。每个Playbook由一个或多个"play"组成,每个"play"定义了一组在特定主机上执行的任务。

Playbook的主要优势:

  • 人类可读的YAML语法
  • 幂等性(多次运行结果一致)
  • 强大的错误处理
  • 灵活的任务控制结构
  • 2. Playbook结构与基本语法

一个基本的Playbook结构包含以下元素:

  • `hosts`: 指定目标主机或主机组
  • `remote_user`: 指定远程执行用户
  • `tasks`: 定义要执行的任务列表
  • `vars`: 定义变量
  • `handlers`: 定义处理程序(特定任务触发时执行)

基本语法示例:

---
- name: Basic Playbook Example
  hosts: webservers
  remote_user: ubuntu
  become: yes  # 使用sudo权限执行任务

  vars:
    package_name: nginx
    doc_root: /var/www/html

  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: "{{ package_name }}"
        state: present
        update_cache: yes

    - name: Start nginx service
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: restart nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

3. 任务(Tasks)详解

任务是Playbook的基本执行单元,每个任务调用一个Ansible模块来完成特定操作。任务可以包含名称、模块参数以及条件判断。

常用模块示例

#### 文件操作

---
- name: File Operations Example
  hosts: all

  tasks:
    - name: Create a directory
      ansible.builtin.file:
        path: /opt/myapp
        state: directory
        mode: '0755'

    - name: Create a file with content
      ansible.builtin.copy:
        dest: /opt/myapp/config.ini
        content: |
          [app]
          debug = true
          port = 8080
        mode: '0644'

    - name: Update file permissions
      ansible.builtin.file:
        path: /opt/myapp/config.ini
        mode: '0600'

#### 包管理

---
- name: Package Management Example
  hosts: db_servers

  tasks:
    - name: Install multiple packages (Debian/Ubuntu)
      ansible.builtin.apt:
        name:
          - postgresql
          - postgresql-contrib
          - python3-psycopg2
        state: present
      when: ansible_os_family == "Debian"

    - name: Install multiple packages (RHEL/CentOS)
      ansible.builtin.yum:
        name:
          - postgresql-server
          - postgresql-contrib
          - python3-psycopg2
        state: present
      when: ansible_os_family == "RedHat"

#### 服务管理

---
- name: Service Management Example
  hosts: app_servers

  tasks:
    - name: Ensure Apache is running
      ansible.builtin.service:
        name: httpd
        state: started
        enabled: yes

    - name: Restart Apache if config changed
      ansible.builtin.service:
        name: httpd
        state: restarted
      when: config_changed is defined and config_changed

4. 变量与事实(Facts)

定义和使用变量

变量可以在Playbook中定义,也可以从外部文件或命令行传入。

---
- name: Variable Usage Example
  hosts: all

  vars:
    app_port: 8080
    app_user: webapp

  tasks:
    - name: Create application user
      ansible.builtin.user:
        name: "{{ app_user }}"
        shell: /bin/bash
        system: yes

    - name: Create config file with variables
      ansible.builtin.template:
        src: templates/app.conf.j2
        dest: /etc/app/app.conf
      notify: restart app

使用系统事实(Facts)

Ansible会自动收集目标主机的系统信息(事实),可以在Playbook中直接使用。

---
- name: Facts Usage Example
  hosts: all

  tasks:
    - name: Display OS information
      ansible.builtin.debug:
        msg: "OS Family: {{ ansible_os_family }}, Distribution: {{ ansible_distribution }}-{{ ansible_distribution_version }}"

    - name: Install package based on OS
      ansible.builtin.package:
        name: "{{ 'apache2' if ansible_os_family == 'Debian' else 'httpd' }}"
        state: present

5. 条件判断与循环

条件判断(when)

使用`when`语句可以根据条件控制任务的执行。

---
- name: Conditional Tasks Example
  hosts: all

  tasks:
    - name: Install Debian-specific package
      ansible.builtin.apt:
        name: "docker-ce"
        state: present
      when: ansible_distribution == "Debian"

    - name: Install RHEL-specific package
      ansible.builtin.yum:
        name: "docker-ce"
        state: present
      when: ansible_os_family == "RedHat"

    - name: Configure for production
      ansible.builtin.copy:
        src: production.conf
        dest: /etc/app/config.conf
      when: env == "production"

循环(loops)

使用循环可以重复执行任务,支持不同类型的循环结构。

---
- name: Loops Example
  hosts: all

  tasks:
    - name: Create multiple users
      ansible.builtin.user:
        name: "{{ item }}"
        groups: "developers"
      loop:
        - alice
        - bob
        - charlie

    - name: Install multiple packages
      ansible.builtin.package:
        name: "{{ item.name }}"
        state: "{{ item.state }}"
      loop:
        - { name: 'nginx', state: 'present' }
        - { name: 'python3', state: 'latest' }

    - name: Create multiple directories
      ansible.builtin.file:
        path: "/var/www/{{ item }}"
        state: directory
      loop:
        - site1
        - site2
        - site3

6. 处理程序(Handlers)

处理程序是特殊的任务,只有在其他任务通知它们时才会执行。它们通常用于服务重启等操作。

---
- name: Handlers Example
  hosts: web_servers

  tasks:
    - name: Update nginx configuration
      ansible.builtin.template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx

    - name: Update app configuration
      ansible.builtin.copy:
        src: files/app.conf
        dest: /etc/app/app.conf
      notify:
        - restart app
        - check app status

  handlers:
    - name: restart nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

    - name: restart app
      ansible.builtin.service:
        name: myapp
        state: restarted

    - name: check app status
      ansible.builtin.uri:
        url: "http://localhost:8080/health"
        method: GET
      register: health_check
      until: health_check.status == 200
      retries: 3
      delay: 5

7. 角色(Roles)组织

角色是组织Playbook的最佳实践方式,可以将变量、任务、处理程序等按功能分组。

角色目录结构

roles/
    common/
        tasks/
            main.yml
        handlers/
            main.yml
        templates/
            config.j2
        files/
            script.sh
        vars/
            main.yml
        defaults/
            main.yml
        meta/
            main.yml

角色使用示例

---
- name: Role Usage Example
  hosts: all

  roles:
    - common
    - { role: nginx, env: production }
    - { role: app, when: deploy_app == true }

角色任务示例 (`roles/nginx/tasks/main.yml`):

---
- name: Install nginx
  ansible.builtin.package:
    name: nginx
    state: present

- name: Configure nginx
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx

- name: Start nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes

8. 错误处理与调试

错误处理策略

---
- name: Error Handling Example
  hosts: all

  tasks:
    - name: This task may fail
      ansible.builtin.command: /usr/bin/false
      ignore_errors: yes  # 忽略错误继续执行
      register: result
      failed_when: result.rc != 0 and "specific error" not in result.stderr

    - name: Handle failure
      ansible.builtin.debug:
        msg: "Previous task failed, but we're handling it"
      when: result is failed

    - name: Block with rescue
      block:
        - name: Run risky operation
          ansible.builtin.command: /usr/bin/risky-command

      rescue:
        - name: Rescue task
          ansible.builtin.debug:
            msg: "Risky operation failed, running rescue"

      always:
        - name: Always run
          ansible.builtin.debug:
            msg: "This task always runs"

调试技巧

---
- name: Debugging Example
  hosts: all

  tasks:
    - name: Show variable values
      ansible.builtin.debug:
        var: ansible_os_family

    - name: Show specific variable
      ansible.builtin.debug:
        msg: "The hostname is {{ inventory_hostname }} and OS is {{ ansible_distribution }}"

    - name: Debug with verbosity
      ansible.builtin.debug:
        msg: "Detailed debugging information"
      verbosity: 2

9. 最佳实践

1. 使用版本控制:将所有Playbook和角色存储在Git仓库中

2. 模块化设计:将功能分解为可重用的角色

3. 幂等性:确保任务可以多次安全运行

4. 变量管理:使用`group_vars`和`host_vars`组织变量

5. 错误处理:为关键任务添加适当的错误处理

6. 文档注释:为复杂的任务和角色添加说明

7. 测试:使用Molecule或Testinfra测试Playbook

8. 安全:使用Ansible Vault保护敏感数据

总结

本教程详细介绍了Ansible Playbook的编写方法,从基础概念到高级特性,包括变量使用、条件判断、循环、处理程序、角色组织和错误处理等关键内容。通过掌握这些技能,您可以创建强大、可维护的自动化配置管理方案。

关键要点回顾:

  • Playbook使用YAML语法,由一个或多个play组成
  • 任务是基本执行单元,调用各种Ansible模块
  • 变量和事实提供了灵活的配置能力
  • 条件和循环控制任务执行流程
  • 处理程序实现基于通知的操作
  • 角色是组织Playbook的最佳实践
  • 错误处理确保自动化流程的健壮性

持续实践和探索Ansible的丰富模块生态系统,将帮助您构建更高效、更可靠的自动化解决方案。Ansible的强大之处在于其简单易学的语法和强大的功能组合,使其成为现代IT自动化的理想选择。

发表回复

后才能评论