Ansible 教程:高效自动化运维实战 – wiki基地


Ansible 教程:高效自动化运维实战

在当今快速变化的 IT 环境中,自动化运维已成为提高效率、减少错误和加速部署的关键。Ansible 作为一款强大的自动化工具,以其简洁、易用和无代理的特性,赢得了广大运维工程师的青睐。本文将深入浅出地介绍 Ansible 的核心概念、安装配置、基本用法到高级特性,助您开启高效自动化运维之旅。

引言:为什么选择 Ansible?

什么是自动化运维?

自动化运维(AIOps)是指利用软件和工具自动执行 IT 基础设施管理、部署、配置、监控和故障排除等任务。它将重复性、耗时的手工操作转化为可脚本化、可重复的流程,从而显著提升效率、降低人为错误率并确保系统的一致性。

为什么 Ansible 脱颖而出?

在众多自动化工具中(如 Puppet, Chef, SaltStack),Ansible 凭借其独特的优势,成为许多团队的首选:

  1. 无 Agent 架构: Ansible 无需在被管理节点上安装任何客户端(Agent)。它通过 SSH(Linux/Unix)或 WinRM(Windows)协议与远程服务器通信,极大地简化了部署和维护。
  2. 简单易学: Ansible 使用 YAML 格式编写 Playbook,语法直观、可读性强,即使是没有编程背景的运维人员也能快速上手。
  3. 功能强大: 涵盖配置管理、应用部署、任务编排、持续交付等多种场景,拥有丰富的模块生态系统。
  4. 幂等性 (Idempotency): Ansible 确保重复执行同一任务时,系统状态保持一致,不会产生副作用。这意味着您可以安全地多次运行 Playbook。
  5. 社区活跃: 拥有庞大的用户社区和丰富的资源,遇到问题时容易找到解决方案。

本文目标

  • 理解 Ansible 的核心概念和工作原理。
  • 掌握 Ansible 的安装与基本配置。
  • 学会使用 Ad-hoc 命令执行快速任务。
  • 能够编写和运行 Playbook,实现复杂自动化工作流。
  • 了解 Ansible 的高级特性和最佳实践。

第一章:Ansible 基础入门

Ansible 核心概念

在深入实践之前,了解 Ansible 的几个核心概念至关重要:

  • 控制节点 (Control Node): 运行 Ansible 的机器。所有 Ansible 命令和 Playbook 都在此节点上执行。通常,控制节点是一台安装了 Ansible 的 Linux/Unix 机器。
  • 被管理节点 (Managed Node): Ansible 通过 SSH(或 WinRM)连接并执行任务的远程服务器。这些节点上无需安装 Ansible。
  • Inventory (库存): 一个配置文件,用于定义 Ansible 所管理的被管理节点列表及其分组信息。Ansible 依靠 Inventory 来知道需要管理哪些服务器。
  • Playbook (剧本): Ansible 的核心,以 YAML 格式编写。它定义了自动化任务的执行顺序、目标主机、变量和模块调用等。一个 Playbook 可以包含一个或多个 Play。
  • Module (模块): Ansible 执行具体任务的功能单元。每个模块都封装了特定的功能,例如 apt 用于包管理,service 用于服务控制,copy 用于文件复制等。Ansible 提供了数百个内置模块。
  • Task (任务): Playbook 中的最小执行单元,由一个模块及其参数组成。一个 Playbook 包含一系列有序的任务。
  • Play: Playbook 中的一个逻辑单元,它定义了一组任务将要执行的目标主机(通过 Inventory 定义)以及这些任务的执行方式(例如是否提升权限)。一个 Playbook 可以包含多个 Play。

安装 Ansible

Ansible 的安装非常简单,推荐使用包管理器或 Python 的 pip 工具。

Linux (Debian/Ubuntu)

bash
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

Linux (RHEL/CentOS)

bash
sudo yum install epel-release
sudo yum install ansible

使用 pip (推荐,跨平台)

首先确保你的系统安装了 Python 和 pip。

bash
python3 -m pip install --user ansible

安装完成后,可以通过 ansible --version 检查安装是否成功。

bash
ansible --version

配置 Inventory

Inventory 文件是 Ansible 的“电话簿”,告诉 Ansible 有哪些主机可以管理。默认的 Inventory 文件路径通常在 /etc/ansible/hosts,但你也可以在项目目录中创建自定义的 Inventory 文件。

INI 格式示例 (最常用)

创建一个名为 hosts.ini 的文件:

“`ini
[webservers]
web1.example.com
web2.example.com ansible_port=2222

[databases]
db1.example.com

[all:vars]
ansible_user=your_ssh_user
ansible_ssh_private_key_file=~/.ssh/id_rsa
“`

  • [webservers][databases] 定义了主机组。
  • web1.example.com 是主机名或 IP 地址。
  • ansible_port=2222 可以为特定主机指定 SSH 端口。
  • [all:vars] 定义了适用于所有主机的变量,例如 SSH 用户名和私钥路径。

YAML 格式示例 (适用于更复杂的结构)

创建一个名为 hosts.yml 的文件:

yaml
all:
hosts:
web1.example.com:
web2.example.com:
ansible_port: 2222
db1.example.com:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
databases:
hosts:
db1.example.com:
vars:
ansible_user: your_ssh_user
ansible_ssh_private_key_file: ~/.ssh/id_rsa

连接测试:

配置好 Inventory 后,可以使用 ansible ping 命令测试与远程主机的连接:

bash
ansible -i hosts.ini all -m ping

  • -i hosts.ini 指定使用 hosts.ini 作为 Inventory 文件。
  • all 表示对 Inventory 中的所有主机执行操作。你也可以指定组名,如 webservers
  • -m ping 表示使用 ping 模块。

如果一切正常,你会看到类似 SUCCESS => {"changed": false, "ping": "pong"} 的输出。

第二章:Ad-hoc 命令 – 快速执行任务

Ad-hoc 命令是 Ansible 的“即兴”命令,用于在不需要编写 Playbook 的情况下,快速执行一次性任务。它们对于快速检查、执行简单的配置更改或测试非常有用。

语法格式:ansible <主机/组> -m <模块名> -a "<模块参数>"

常用模块示例

  1. ping 模块:测试连接性
    bash
    ansible -i hosts.ini webservers -m ping

    确认与 webservers 组中的所有主机都能正常通信。

  2. command / shell 模块:执行远程命令

    • command 模块:执行简单的命令,不经过 shell 解析。
    • shell 模块:支持 shell 特性(如管道、重定向、环境变量等),更强大但需谨慎使用。

    执行 uptime 命令:
    bash
    ansible -i hosts.ini webservers -m command -a "uptime"

    检查 /etc 目录下文件数量:
    bash
    ansible -i hosts.ini all -m shell -a "ls -l /etc | wc -l"

  3. apt / yum 模块:包管理
    安装 nginx 包 (Debian/Ubuntu):
    bash
    ansible -i hosts.ini webservers -m apt -a "name=nginx state=present" --become

    • --become 相当于 sudo,用于提升权限执行命令。Ansible 会提示输入 sudo 密码。

    卸载 nginx 包 (RHEL/CentOS):
    bash
    ansible -i hosts.ini webservers -m yum -a "name=nginx state=absent" --become

  4. service 模块:服务管理
    启动 nginx 服务:
    bash
    ansible -i hosts.ini webservers -m service -a "name=nginx state=started" --become

    重启 nginx 服务:
    bash
    ansible -i hosts.ini webservers -m service -a "name=nginx state=restarted" --become

  5. copy 模块:文件复制
    将本地的 my_config.conf 文件复制到远程主机的 /etc/nginx/ 目录下:
    bash
    ansible -i hosts.ini webservers -m copy -a "src=./my_config.conf dest=/etc/nginx/my_config.conf mode=0644" --become

    • src:本地源文件路径。
    • dest:远程目标文件路径。
    • mode:设置文件权限。

Ad-hoc 命令非常适合快速、临时的操作。但对于复杂、需要重复执行或版本控制的任务,Playbook 才是最佳选择。

第三章:Playbook – 自动化工作流

Playbook 是 Ansible 的核心,它以结构化的 YAML 格式定义了一系列自动化任务,可以实现复杂的配置管理、应用部署和任务编排。

Playbook 结构解析

一个典型的 Playbook 结构如下:

“`yaml

  • name: This is my first playbook # Play 的名称
    hosts: webservers # 目标主机组,来自 Inventory
    become: yes # 是否提升权限 (sudo/su)
    vars: # 定义 Play 级别的变量
    nginx_port: 80
    app_dir: /var/www/my_app

tasks: # 任务列表
– name: Ensure Nginx is installed # 任务名称
ansible.builtin.apt:
name: nginx
state: present

- name: Copy Nginx configuration file
  ansible.builtin.template:
    src: templates/nginx.conf.j2  # 本地模板文件
    dest: /etc/nginx/sites-available/default # 远程目标文件
    mode: '0644'
  notify: Restart Nginx           # 当文件发生变化时触发一个 handler

- name: Enable Nginx site
  ansible.builtin.file:
    src: /etc/nginx/sites-available/default
    dest: /etc/nginx/sites-enabled/default
    state: link
  notify: Restart Nginx

- name: Ensure Nginx service is running and enabled
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes

handlers: # 处理器列表,由任务通过 notify 触发
– name: Restart Nginx
ansible.builtin.service:
name: nginx
state: restarted
“`

  • ---: YAML 文件的开始标志。
  • name: Play 的描述性名称,方便识别。
  • hosts: 指定该 Play 将作用于 Inventory 中的哪些主机或组。
  • become: 设置是否使用 sudosu 提升权限。yes 表示需要。
  • vars: 在 Play 级别定义变量,可以在后续任务中引用。
  • tasks: 这是一个列表,包含 Play 将执行的所有任务。
    • 每个任务也都有一个 name
    • 模块名(如 ansible.builtin.apt)后面跟着模块的参数。
    • notify: 当任务导致远程主机发生改变时,触发指定的 handler
  • handlers: 类似于任务,但它们只在被 notify 触发时执行一次。常用于服务重启。

编写第一个 Playbook:安装和配置 Nginx

假设我们有一个 hosts.ini 文件,其中定义了 webservers 组:

ini
[webservers]
web1.example.com
web2.example.com

1. 创建 Nginx 配置文件模板:templates/nginx.conf.j2

这是一个 Jinja2 模板,可以嵌入 Ansible 变量:

“`nginx
server {
listen {{ nginx_port }}; # 引用 Playbook 中定义的变量
listen [::]:{{ nginx_port }};

root {{ app_dir }}; # 引用 Playbook 中定义的变量

index index.html index.htm index.nginx-debian.html;

server_name _;

location / {
    try_files $uri $uri/ =404;
}

}
“`

2. 创建 Playbook 文件:deploy_nginx.yml

“`yaml

  • name: Deploy and configure Nginx on webservers
    hosts: webservers
    become: yes
    vars:
    nginx_port: 80
    app_dir: /var/www/html/my_website # 定义应用目录

tasks:
– name: Update apt cache and install Nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: yes

- name: Create web application directory
  ansible.builtin.file:
    path: "{{ app_dir }}" # 使用变量
    state: directory
    mode: '0755'

- name: Copy a simple index.html to the web directory
  ansible.builtin.copy:
    content: "<h1>Welcome to my Ansible deployed website!</h1>"
    dest: "{{ app_dir }}/index.html"
    mode: '0644'

- name: Copy Nginx configuration file from template
  ansible.builtin.template:
    src: templates/nginx.conf.j2
    dest: /etc/nginx/sites-available/default
    mode: '0644'
  notify: Restart Nginx # 当模板文件发生变化时触发重启 Nginx

- name: Ensure default site is symlinked (enabled)
  ansible.builtin.file:
    src: /etc/nginx/sites-available/default
    dest: /etc/nginx/sites-enabled/default
    state: link
  notify: Restart Nginx

- name: Remove default Nginx welcome page link (if exists)
  ansible.builtin.file:
    path: /etc/nginx/sites-enabled/default_nginx.conf # Adjust if default symlink name is different
    state: absent
  ignore_errors: yes # 如果文件不存在,不报错,继续执行

- name: Ensure Nginx service is running and enabled on boot
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes

handlers:
– name: Restart Nginx
ansible.builtin.service:
name: nginx
state: restarted
“`

3. 运行 Playbook

在控制节点上,进入到 deploy_nginx.yml 文件所在的目录,并执行以下命令:

bash
ansible-playbook -i hosts.ini deploy_nginx.yml -k -K

  • -i hosts.ini: 指定 Inventory 文件。
  • deploy_nginx.yml: 指定要运行的 Playbook 文件。
  • -k: 提示输入 SSH 密码(如果未使用 SSH 密钥)。
  • -K: 提示输入 sudo 密码(用于 become: yes)。

运行后,Ansible 会连接到 webservers 组中的所有主机,并按照 Playbook 中定义的顺序执行任务。完成后,你可以通过浏览器访问 web1.example.comweb2.example.com,看到“Welcome to my Ansible deployed website!”的页面。

常用模块在 Playbook 中的应用

除了上面提到的模块,还有一些在自动化运维中非常实用的模块:

  • file 模块: 管理文件、目录和符号链接。
    “`yaml

    • name: Create a directory
      ansible.builtin.file:
      path: /opt/my_app
      state: directory
      mode: ‘0755’

    • name: Delete a file
      ansible.builtin.file:
      path: /tmp/old_file.txt
      state: absent
      “`

    • template 模块: 使用 Jinja2 模板引擎生成配置文件。比 copy 模块更灵活,可以根据变量动态生成文件内容。
      “`yaml
    • name: Configure database connection
      ansible.builtin.template:
      src: templates/database.ini.j2
      dest: /etc/my_app/database.ini
      “`
    • user / group 模块: 管理系统用户和组。
      “`yaml
    • name: Create a new user
      ansible.builtin.user:
      name: appuser
      state: present
      shell: /bin/bash
      groups: sudo
      append: yes

    • name: Ensure a group exists
      ansible.builtin.group:
      name: devops
      state: present
      “`

    • lineinfile / blockinfile 模块: 修改文件中特定行或插入/替换文件块。
      “`yaml
    • name: Ensure a specific line exists in a file
      ansible.builtin.lineinfile:
      path: /etc/hosts
      regexp: ‘^127.0.0.1’ # 匹配以127.0.0.1开头的行
      line: ‘127.0.0.1 localhost.localdomain localhost’
      state: present

    • name: Add a block of text to a file
      ansible.builtin.blockinfile:
      path: /etc/fstab
      block: |
      # Ansible managed block
      /dev/sdb1 /data ext4 defaults 0 0
      # End of Ansible managed block
      marker: “# {mark} ANSIBLE MANAGED BLOCK FOR DATA MOUNT”
      “`

第四章:高级特性与最佳实践

角色 (Roles) – 组织 Playbook

随着自动化任务的复杂性增加,单个 Playbook 会变得庞大且难以维护。Roles 提供了一种结构化的方式来组织 Playbook、变量、文件、模板和任务,使其更具可重用性和可读性。

Role 的标准目录结构:

roles/
└── my_webserver_role/
├── tasks/ # 定义此 Role 的任务
│ └── main.yml
├── handlers/ # 定义此 Role 的处理器
│ └── main.yml
├── templates/ # Jinja2 模板文件
├── files/ # 静态文件
├── vars/ # Role 级别的变量
│ └── main.yml
├── defaults/ # 默认变量,优先级最低
│ └── main.yml
├── meta/ # Role 的元数据(依赖项)
│ └── main.yml
└── README.md

如何使用 Role:

  1. 创建 Role 骨架:
    bash
    ansible-galaxy init my_webserver_role
  2. 填充内容: 将与 webserver 相关的任务、模板、变量等分别放入对应的子目录。
  3. 在 Playbook 中调用 Role:
    “`yaml

    • name: Deploy web servers with roles
      hosts: webservers
      become: yes
      roles:

      • my_webserver_role # 引用前面创建的 Role
        “`
        通过使用 Roles,可以轻松地在不同的 Playbook 中复用代码,提高模块化程度。

变量与事实 (Facts)

  • 变量优先级: Ansible 变量有严格的优先级顺序。理解这些优先级对于避免意外行为很重要。简而言之,命令行传递的变量 (-e) 优先级最高,然后是 Playbook 变量、Roles 变量、Inventory 变量,最低是 defaults 目录下的变量。
  • 事实 (Facts): Ansible 在执行 Playbook 前,会自动收集被管理节点的大量系统信息(如操作系统、内存、IP 地址等),这些信息被称为“事实”。你可以在任务中通过 ansible_facts 或直接引用,例如 {{ ansible_default_ipv4.address }}

条件语句 (Conditionals) 和循环 (Loops)

  • 条件语句 (when): 根据条件决定是否执行任务。
    “`yaml

    • name: Install Nginx only on Ubuntu servers
      ansible.builtin.apt:
      name: nginx
      state: present
      when: ansible_distribution == “Ubuntu”
      “`
  • 循环 (loopwith_items): 对列表中的每个元素重复执行任务。
    “`yaml

    • name: Create multiple users
      ansible.builtin.user:
      name: “{{ item }}”
      state: present
      loop:

      • alice
      • bob
      • charlie
        “`

Vault – 加密敏感数据

在 Playbook 中直接存储密码、API 密钥等敏感信息是不安全的。Ansible Vault 提供了强大的加密功能,可以安全地存储这些数据。

  1. 创建加密文件:
    bash
    ansible-vault create vars/secret_vars.yml

    输入并确认密码。文件内容将被加密。
  2. 编辑加密文件:
    bash
    ansible-vault edit vars/secret_vars.yml
  3. 在 Playbook 中引用:
    在 Playbook 中像普通变量一样引用加密文件中的变量即可。
    “`yaml

    • name: Deploy application with sensitive credentials
      hosts: app_servers
      vars_files:

      • vars/secret_vars.yml # 引用加密的变量文件
        tasks:
      • name: Login to Docker registry
        ansible.builtin.command: “docker login -u {{ docker_user }} -p {{ docker_password }}”
        “`
  4. 运行 Playbook 时提供 Vault 密码:
    bash
    ansible-playbook -i hosts.ini deploy_app.yml --ask-vault-pass
    # 或者使用密码文件:
    ansible-playbook -i hosts.ini deploy_app.yml --vault-password-file ~/.ansible_vault_pass

Ansible Galaxy – 共享和复用 Roles

Ansible Galaxy 是一个 Hub,用于查找、共享和下载 Ansible Roles。你可以使用 ansible-galaxy 命令行工具来管理这些 Roles。

“`bash

搜索 Role

ansible-galaxy search nginx

安装 Role

ansible-galaxy install geerlingguy.nginx
``
安装的 Roles 通常会放置在
~/.ansible/roles或项目根目录的roles` 文件夹中。

错误处理和幂等性 (Idempotency)

  • 错误处理: Ansible 默认在任务失败时停止 Playbook 执行。你可以使用 ignore_errors: yes 来忽略特定任务的错误,或使用 rescuealways 块来定义更复杂的错误处理逻辑。
  • 幂等性: Ansible 的大部分模块都设计为幂等的。这意味着无论执行多少次,它们都会使系统达到相同的期望状态,而不会产生不必要的副作用或错误。这是自动化运维中一个非常重要的原则,确保了重复执行的安全性。

结论

Ansible 凭借其无代理、易学易用和强大的特性,已成为自动化运维领域不可或缺的工具。通过本文的学习,您应该对 Ansible 的核心概念、安装配置、Ad-hoc 命令、Playbook 编写以及高级特性有了全面的理解。

自动化运维不仅能解放您的双手,让您从繁琐的重复性工作中解脱出来,还能提升系统的一致性、可靠性,并加速交付流程。现在,是时候将这些知识付诸实践,利用 Ansible 在您的 IT 环境中构建高效的自动化工作流了。从简单的配置任务开始,逐步深入到复杂的应用部署和系统管理,Ansible 将助您一臂之力,实现运维效率的飞跃。


滚动至顶部