type
Post
status
Published
date
Feb 12, 2025
slug
summary
本文全面解析Ansible自动化运维工具,涵盖六大核心概念(Modules、Plugins、Collections、Playbook、Inventory、Roles)、运行原理与幂等性机制、与Puppet/Chef/Terraform的横向对比,以及从安装配置到Ad-Hoc命令与Playbook实战的完整操作指南。附带使用Ansible自动化创建Azure AKS集群并部署容器化应用的真实示例(含多环境Inventory、K8s资源模板、滚动更新与销毁流程),适合希望落地IAC理念的运维工程师与开发者。
tags
Infrastructure
category
DevOps
icon
password
wordCount
7070
最近一直在做infrastructure相关的工作,主要包括Azure Cloud, AWS Cloud相关的部署,其中使用的是就是Ansible — 一个现代化的自动化运维工具。Ansible贯彻了IAC(Infrastructure As Code)理念,所有的资源都会定义在代码里面,还可以通过不同环境部署灵活部署不同资源,在可维护性,自动化,安全性,可扩展性上都有很多优势,今天特意写一个文章来记录一下我对于Ansible的理解
什么是Ansible
Ansible 是 Red Hat 旗下的开源自动化运维工具,用一句话概括:用代码描述你的基础设施,然后让机器自己搞定剩下的事。它诞生于 2012 年,名字来源于科幻小说《安德的游戏》中一种能跨越光年瞬间通信的设备——寓意很明确:无论服务器在天涯海角,Ansible 都能瞬间触达。
Ansible 的核心哲学是 简单。不需要在目标机器上安装任何 agent,只要有 SSH 就行。Playbook 用 YAML 编写,运维工程师和开发者都能秒懂。这也是它能在 Puppet、Chef、SaltStack 等一众竞品中脱颖而出的原因——低门槛 + 高天花板。
一个灵魂拷问: 如果你现在还在手动 SSH 到每台服务器上敲命令、改配置、重启服务……那你可能需要认真考虑一下 Ansible 了。想象一下,100 台服务器统一升级 JDK 版本,手动操作可能需要一个下午加一杯咖啡(和一堆 typo),而 Ansible 只需要一条命令、几秒钟。
Ansible vs 其他自动化工具
特性 | Ansible | Puppet | Chef | Terraform |
架构 | 无Agent(Agentless) | 需要Agent | 需要Agent | 无Agent |
配置语言 | YAML | Puppet DSL | Ruby DSL | HCL |
学习曲线 | ⭐ 低 | ⭐⭐⭐ 高 | ⭐⭐⭐ 高 | ⭐⭐ 中 |
核心定位 | 配置管理 + 应用部署 | 配置管理 | 配置管理 | 基础设施编排 |
幂等性 | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
社区生态 | Galaxy(海量 Role) | Forge | Supermarket | Registry |
运行原理
Ansible 的运行原理出奇地直白,核心流程可以用一张图概括:
执行步骤拆解:
- 读取 Inventory:Ansible 首先从主机清单中获取目标机器的地址、分组和连接信息
- 解析 Playbook:按顺序解析 YAML 中定义的 Play 和 Task
- 生成 Python 脚本:根据 Task 调用的 Module,在控制节点上生成对应的 Python 脚本
- 传输到目标机器:通过 SSH(Linux)或 WinRM(Windows)将脚本推送到远程主机的临时目录
- 远程执行:在目标机器上执行脚本,收集执行结果
- 返回 JSON 结果:模块执行完毕后,以 JSON 格式返回执行状态(changed / ok / failed)
- 清理临时文件:删除远程主机上的临时脚本
关键特性:幂等性(Idempotency)
同一个 Playbook 跑 1 次和跑 100 次的最终结果是一样的。Ansible 会先检测当前状态,只有当实际状态与期望状态不一致时才执行变更。这意味着你可以放心地反复执行同一个 Playbook,不用担心把系统搞崩。
核心概念
理解 Ansible,本质上就是理解下面这五个核心概念。它们之间的关系就像一出戏剧:Inventory 是演员表,Modules 是基本动作,Plugins 是幕后特效,Playbook 是剧本,Roles 是角色分工。
Modules
Module 是 Ansible 的最小执行单元,每个 Module 负责完成一个具体的任务。Ansible 内置了数千个模块,覆盖了你能想到的几乎所有运维场景。
常用模块速查表:
模块 | 用途 | 示例 |
command | 执行简单命令(不经过 Shell) | command: whoami |
shell | 执行 Shell 命令(支持管道、重定向) | shell: cat /etc/hosts \| grep db |
copy | 将文件从控制节点复制到目标机器 | copy: src=app.conf dest=/etc/app/ |
template | 使用 Jinja2 模板渲染配置文件 | template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf |
yum / apt | 包管理 | yum: name=nginx state=present |
service | 管理系统服务 | service: name=nginx state=started enabled=yes |
file | 管理文件和目录 | file: path=/data state=directory mode=0755 |
user | 管理用户账号 | user: name=deploy state=present |
docker_container | 管理 Docker 容器 | docker_container: name=myapp image=myapp:latest |
所有模块返回 JSON 格式的数据,你可以用
register 关键字捕获返回值,在后续的 Task 中作为条件判断或变量使用。Plugins
Plugin 是 Ansible 的扩展机制,用于增强或改变 Ansible 的核心行为。如果 Module 是「做什么」,那 Plugin 就是「怎么做」。
常见 Plugin 类型:
- Connection Plugins:定义如何连接到目标主机(
ssh、winrm、docker、local)
- Callback Plugins:定义执行结果的输出格式(默认终端输出、JSON、Slack 通知等)
- Lookup Plugins:从外部数据源获取数据(文件、环境变量、HashiCorp Vault 等)
- Filter Plugins:在 Jinja2 模板中对变量进行转换(
to_json、regex_replace等)
- Inventory Plugins:动态生成主机清单(从 AWS EC2、Azure、GCP 等云平台自动发现主机)
Collections
Collection 是 Ansible 2.9+ 引入的内容分发与命名空间机制,把 Modules、Plugins、Roles、Playbook 甚至文档打包成一个可版本化、可分发的单元。你可以把它理解为 Ansible 世界的 npm 包 / Maven artifact——有统一的命名空间(
namespace.collection_name)、语义化版本号,以及一键安装的体验。在 Ansible 2.9 之前,所有内置模块都塞在
ansible-base 里,一更新就是几千个模块一起发版,维护成本爆炸。Collection 的出现让模块和插件可以独立发布、独立升级,社区贡献者也能更快地迭代自己的内容。Collection 的内部结构:
常用 Collection 速查表:
Collection | 用途 | 典型模块 |
ansible.builtin | Ansible 内置核心模块 | copy、template、service、debug |
azure.azcollection | Azure 云资源管理 | azure_rm_aks、azure_rm_resourcegroup |
AWS 云资源管理 | ec2_instance、s3_bucket | |
kubernetes.core | Kubernetes 资源编排 | k8s、k8s_info、helm |
community.general | 社区通用模块集合 | docker_container、ufw、nmcli |
community.mysql | MySQL 管理 | mysql_db、mysql_user |
community.postgresql | PostgreSQL 管理 | postgresql_db、postgresql_user |
安装与使用:
在 Playbook 中引用 Collection 模块时,使用完全限定名称(FQCN):
FQCN vs 短名: Ansible 官方推荐始终使用 FQCN(如
azure.azcollection.azure_rm_resourcegroup),因为当多个 Collection 包含同名模块时,短名会产生歧义。本文示例中的 azure.azcollection.azure_rm_aks 就是 FQCN 写法。你可以在 Ansible Galaxy 上浏览和搜索所有公开的 Collection,也可以搭建私有 Galaxy 服务器来托管企业内部的 Collection。
Playbook
Playbook 是 Ansible 的核心配置文件,用 YAML 编写,定义了「在哪些机器上、按什么顺序、执行哪些任务」。一个 Playbook 可以包含多个 Play,每个 Play 针对一组主机执行一系列 Task。
Play 级别的执行顺序(务必记住):
pre_tasks→ 2.pre_tasks 的 handlers→ 3.roles→ 4.tasks→ 5.tasks 的 handlers→ 6.post_tasks→ 7.post_tasks 的 handlers
Playbook 完整关键字速查表:
Play 级别关键字:
关键字 | 说明 | 示例值 |
hosts | 目标主机或主机组 | webservers、all、web1:&dbservers |
become | 是否提权 | yes / no |
become_user | 提权后切换的用户 | root、postgres |
vars | 直接定义变量 | app_port: 8080 |
vars_files | 从 YAML 文件加载变量 | • vars/prod.yml |
vars_prompt | 运行时交互式输入变量 | 密码、确认信息等 |
environment | 为 Task 设置系统环境变量 | JAVA_HOME: /usr/lib/jvm/java-11 |
serial | 滚动更新批次 | 1、"30%"、[1, 5, "100%"] |
strategy | 执行策略 | linear(默认,逐步)、free(各主机独立推进) |
max_fail_percentage | 允许的最大失败比例 | 10(超过 10% 失败则中止) |
any_errors_fatal | 任一主机失败是否终止全部 | true / false |
gather_facts | 是否自动收集主机 Facts | yes / no(关闭可加速执行) |
connection | 连接方式 | ssh、local、docker、winrm |
pre_tasks | 在 roles 和 tasks 之前执行 | 前置检查、环境准备 |
post_tasks | 在 tasks 和 handlers 之后执行 | 通知、清理、验证 |
roles | 引用角色 | • role: nginx |
Task 级别关键字:
关键字 | 说明 | 示例 |
tags | 给 Task 打标签,运行时用 --tags / --skip-tags 过滤 | tags: [deploy, config] |
when | 条件判断 | when: ansible_os_family == "RedHat" |
loop | 循环遍历列表 | loop: ["nginx", "redis", "java"] |
register | 捕获 Task 返回结果到变量 | register: cmd_result |
notify | 状态变更时触发 Handler | notify: restart nginx |
ignore_errors | 忽略错误继续执行 | ignore_errors: yes |
changed_when | 自定义 changed 判断条件 | changed_when: false |
failed_when | 自定义失败判断条件 | failed_when: result.rc != 0 |
retries / delay / until | 重试机制 | retries: 5 delay: 10 until: result.status == 200 |
delegate_to | 将 Task 委派到其他主机执行 | delegate_to: localhost |
run_once | 整个 Play 只执行一次 | run_once: true(如数据库迁移) |
block / rescue / always | 异常处理(类似 try-catch-finally) | 见下方示例 |
no_log | 隐藏日志中的敏感信息 | no_log: true(如密码传输) |
Block 异常处理示例:
Inventory
Inventory(主机清单)告诉 Ansible 「你要管理哪些机器」。它可以是一个简单的 INI 文件,也可以是动态生成的。
静态 Inventory 示例:
分环境 Inventory 配置
真实项目中,你通常有 dev / staging / production 多套环境,每套环境的主机、变量、密钥都不同。Ansible 的最佳实践是每个环境一个 Inventory 目录,配合
group_vars 和 host_vars 实现环境隔离。推荐目录结构:
inventory/dev/hosts.ini(开发环境,单节点):
inventory/staging/hosts.ini(预发布环境):
inventory/production/hosts.ini(生产环境,多节点 + 高可用):
group_vars 分环境变量对比:
变量 | dev | staging | production |
app_debug | true | true | false |
app_replicas | 1 | 2 | 4 |
jvm_heap | 512m | 1g | 4g |
db_host | staging-db1 | prod-db-master | |
ssl_enabled | false | true | true |
log_level | DEBUG | INFO | WARN |
inventory/dev/group_vars/all.yml 示例:
inventory/production/group_vars/all.yml 示例:
运行时通过
-i 指定环境:变量优先级(从低到高):
role defaults → inventory group_vars/all → inventory group_vars/<group> → inventory host_vars/<host> → playbook vars → playbook vars_files → role vars → extra vars (-e)生产实践中,把通用默认值放
group_vars/all.yml,环境差异放各环境目录,运行时紧急覆盖用 -e。动态 Inventory:在云环境中,服务器随时会增减。Ansible 支持通过脚本或 Inventory Plugin 动态获取主机列表,例如从 AWS EC2、Azure、GCP、阿里云等平台实时拉取。
Roles
Role 是 Ansible 的最佳实践组织方式,它将 Playbook 拆分成可复用、可共享的组件。把 Role 想象成乐高积木——每块积木专注做一件事,拼在一起就能搭出整个系统。
标准 Role 目录结构:
在 Playbook 中调用 Role:
你可以在 Ansible Galaxy 上找到社区贡献的数万个 Role,覆盖从 Docker 安装到 Kubernetes 集群搭建的各种场景。别重复造轮子——先看看 Galaxy 上有没有现成的。
如何使用Ansible
安装 Ansible
Ansible 只需要安装在控制节点(你的工作机或 CI/CD 服务器)上,目标机器不需要装任何东西。
Linux(推荐)
macOS
Windows
Ansible 控制节点不原生支持 Windows。但你可以通过以下方式曲线救国:
- WSL 2(Windows Subsystem for Linux):在 WSL 中安装 Ubuntu,再装 Ansible ✅ 推荐
- Docker:运行一个装有 Ansible 的容器
- Cygwin:理论上可以,但坑多,不推荐
验证安装:
配置 Ansible
Ansible 的配置按优先级从高到低依次为:
ANSIBLE_*环境变量
- 当前目录下的
ansible.cfg
- 用户主目录下的
~/.ansible.cfg
- 全局配置
/etc/ansible/ansible.cfg
推荐在项目根目录放一个
ansible.cfg:安全提醒:
host_key_checking = False 只适合开发和测试环境。生产环境请保持开启,并使用 ssh-keyscan 提前收集目标主机的指纹。运行 Ansible
Ansible 提供两种运行方式:Ad-Hoc 命令(一次性任务)和 Playbook(编排任务)。
Ad-Hoc 命令
适合快速执行简单的一次性操作,语法:
实用示例:
Playbook 运行
进阶玩法:Ansible + CI/CD
在真实项目中,Ansible 通常不会手动运行,而是集成到 CI/CD 流水线中:
- GitLab CI / GitHub Actions:代码合并到 main 分支后自动触发 Ansible 部署
- Jenkins:通过 Ansible Plugin 在流水线中调用 Playbook
- AWX / Ansible Tower:Red Hat 提供的 Web UI 管理平台,支持权限控制、任务调度、审计日志
示例
来看一个贴近实际工作的完整示例:用 Ansible 自动化创建 Azure AKS 集群,并将容器化应用部署到 Kubernetes 上,支持 dev / staging / production 三套环境。
这个示例覆盖了云原生部署的完整链路:创建 Azure 资源(Resource Group + AKS)→ 获取 kubeconfig → 部署 K8s 资源(Namespace、Deployment、Service、Ingress)→ 健康检查 → 通知。
前置依赖: 需要安装 Azure Ansible Collection 和相关 Python 库:
ansible-galaxy collection install azure.azcollectionpip install azure-identity azure-mgmt-containerservice kubernetes完整项目目录结构
多环境 Inventory 配置
由于 AKS 操作全部在控制节点通过 Azure API 完成,Inventory 只需要
localhost,环境差异全靠 group_vars 区分。inventory/dev/hosts.yml:
inventory/dev/group_vars/all.yml:
inventory/staging/group_vars/all.yml:
inventory/production/group_vars/all.yml:
分环境关键变量对比:
变量 | dev | staging | production |
aks_node_count | 1 | 2 | 3 |
aks_node_vm_size | Standard_B2s | Standard_D2s_v3 | Standard_D4s_v3 |
app_replicas | 1 | 2 | 4 |
SPRING_PROFILES_ACTIVE | dev | staging | production |
LOG_LEVEL | DEBUG | INFO | WARN |
aks_availability_zones | 未设置 | 未设置 | [1, 2, 3] |
site.yml —— 总入口
playbooks/aks-provision.yml —— 创建 AKS 集群
roles/azure-resource-group/tasks/main.yml
roles/azure-aks/tasks/main.yml
playbooks/aks-deploy.yml —— 部署应用到 AKS
roles/k8s-app/tasks/main.yml —— K8s 资源部署
roles/k8s-app/templates/deployment.yml.j2
roles/k8s-app/templates/service.yml.j2
playbooks/aks-destroy.yml —— 销毁集群
执行部署
Ansible vs Terraform 部署 AKS 的边界:
Terraform 更擅长「基础设施声明式管理」(创建/销毁 AKS、VNet、NSG 等),Ansible 更擅长「应用层编排」(K8s 资源部署、配置渲染、健康检查、通知)。
生产中两者经常搭配使用:Terraform 建集群 → Ansible 部署应用。本示例为了演示 Ansible 的完整能力,把两部分都用 Ansible 实现了。
写在最后
Ansible 的魅力在于它把复杂的基础设施管理变成了可读、可版本控制、可复用的代码。IAC 不只是一个技术理念,更是一种运维文化的转变——从「手工作坊」到「工业化生产」。
回顾一下我们学到了什么:
- Ansible 的无Agent架构让它部署成本极低,SSH 就是全部
- Playbook + Role 的组合让自动化任务既灵活又可复用
- 幂等性保证了操作的安全可重复
- Inventory 支持静态和动态,完美适配云环境
未来展望: 随着云原生和混合云架构的普及,Ansible 的角色只会越来越重要。Red Hat 正在将 AI 能力融入 Ansible——Ansible Lightspeed 借助大语言模型,能根据自然语言描述自动生成 Playbook。想象一下,未来你只需要说「帮我在三台服务器上部署 Redis 集群」,AI 就能帮你写好整个 Playbook。那一天,可能比你想象的更近。
参考文章
有关Ansible安装或者使用上的问题,欢迎您在底部评论区留言,一起交流~
.jpg?table=block&id=30552c4c-a1ae-813c-ac6a-da331f2db2f4&t=30552c4c-a1ae-813c-ac6a-da331f2db2f4)