1. 什么是 Ansible?
Ansible 是一款基于 Python 开发的开源自动化运维工具,采用 无代理(Agentless) 架构,通过 SSH 协议远程管理服务器。它使用 YAML 编写剧本(Playbook),实现配置管理、应用部署、任务编排等自动化操作。
相比 Puppet、SaltStack 等工具,Ansible 的核心优势在于:
相比 Puppet、SaltStack 等工具,Ansible 的核心优势在于:
- 零安装:被管理节点无需安装任何客户端,只需开启 SSH 即可。
- 易上手:使用人类可读的 YAML 语法,学习曲线平缓。
- 幂等性:重复执行同一任务不会产生副作用,结果保持一致。
- 模块化:内置上千个模块,覆盖系统、网络、云平台等场景。
下面从架构、配置语言、学习曲线、适用场景等维度,对 Ansible、Puppet 与 SaltStack 进行对比:
| 对比维度 | Ansible | Puppet | SaltStack |
|---|---|---|---|
| 架构 | 无代理(Agentless),基于 SSH 推送 | 有代理(Agent),C/S 架构,客户端定期拉取 | 有代理(Agent),C/S 架构,支持主从与无主模式 |
| 配置语言 | YAML(Playbook) | 自定义 DSL(Puppet 语言) | YAML + Jinja2(SLS 文件) |
| 学习曲线 | 平缓,易上手 | 较陡峭,需学习 DSL | 中等,需理解事件驱动模型 |
| 执行模式 | 推送式(Push) | 拉取式(Pull) | 推送式(Push)为主,也支持拉取 |
| 适用场景 | 应用部署、配置管理、临时任务编排 | 大规模服务器配置管理与合规审计 | 大规模基础设施管理、实时监控与事件驱动自动化 |
| 性能 | 中等,SSH 并发受限制 | 较高,代理常驻内存 | 高,ZeroMQ 消息队列并发能力强 |
各工具优缺点简要说明:
- Ansible:优点是无代理、上手快、幂等性好,适合中小规模环境快速落地;缺点是执行依赖 SSH 并发,大规模节点下性能不如代理型工具,且无守护进程导致实时性较弱。
- Puppet:优点是代理常驻、拉取模式适合海量节点,配置管理成熟、合规审计能力强;缺点是需学习专属 DSL,架构较重,临时任务编排不如 Ansible 灵活。
- SaltStack:优点是基于 ZeroMQ 的并发性能极高,支持事件驱动与实时监控,适合大规模动态基础设施;缺点是需部署代理,架构相对复杂,运维成本高于 Ansible。
2. 环境准备与安装
2.1 控制节点要求
Ansible 控制节点需要一台安装了 Python 3.8+ 的 Linux/macOS 机器(Windows 可通过 WSL 使用)。被管理节点只需支持 SSH 和 Python 2.7 或 3.5+ 即可。
2.2 安装 Ansible
以 Ubuntu/Debian 为例:
sudo apt update
sudo apt install -y ansible
使用 pip 安装(可指定版本):
pip install ansible==2.16.0
验证安装:
ansible --version
2.3 配置 SSH 免密登录
生成密钥并分发到被管理节点:
ssh-keygen -t rsa -b 4096
ssh-copy-id user@192.168.1.101
ssh-copy-id user@192.168.1.102
3. 核心概念详解
3.1 控制节点与被管理节点
- 控制节点(Control Node):运行 Ansible 命令的机器,负责下发任务。
- 被管理节点(Managed Node):通过 SSH 接受指令的目标服务器。
3.2 Inventory(主机清单)
Inventory 定义了被管理节点的分组信息,默认位于 /etc/ansible/hosts,也可自定义路径。示例:
[web_servers]
192.168.1.101
192.168.1.102
[db_servers]
db1.example.com ansible_user=root
[all:vars]
ansible_python_interpreter=/usr/bin/python3
3.3 Playbook(剧本)
Playbook 是 Ansible 的核心配置文件,使用 YAML 语法描述自动化任务。一个最简单的 Playbook:
---
- name: 安装 Nginx
hosts: web_servers
become: yes
tasks:
- name: 安装 nginx 包
apt:
name: nginx
state: present
3.4 Module(模块)
模块是 Ansible 执行任务的最小单元。常用模块包括:
command/shell:执行命令copy/file:文件操作apt/yum:软件包管理service:服务管理user/group:用户与组管理
3.5 Task(任务)
Task 是 Playbook 中的最小执行单元,每个 Task 调用一个模块完成具体操作。
3.6 Role(角色)
Role 是 Ansible 组织 Playbook 的高级方式,将任务、变量、模板等按功能模块化,便于复用和团队协作。
4. 第一个 Playbook 实战
5. 综合实战:部署 Nginx + MySQL + 应用服务
前面我们分别学习了变量、模板、条件、循环和 handlers,本节将它们整合到一个完整的 Playbook 中,实现「Nginx + MySQL + 应用服务」的一键部署。
5.1 项目结构与变量定义
首先创建项目目录并定义变量文件 vars.yml:
mkdir -p deploy-demo/templates
cd deploy-demo
vars.yml:
---
app_name: myapp
app_port: 8080
db_name: myapp_db
db_user: app_user
db_password: "{{ vault_db_password }}" # 生产环境建议用 Vault 加密
nginx_port: 80
server_name: example.com
packages:
- nginx
- mysql-server
- python3-pymysql
5.2 编写模板文件
创建 Nginx 站点模板 templates/nginx.conf.j2:
server {
listen {{ nginx_port }};
server_name {{ server_name }};
location / {
proxy_pass http://127.0.0.1:{{ app_port }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
创建应用配置模板 templates/app.conf.j2:
[app]
name = {{ app_name }}
port = {{ app_port }}
[database]
host = 127.0.0.1
name = {{ db_name }}
user = {{ db_user }}
password = {{ db_password }}
5.3 完整 Playbook
创建 deploy.yml,综合运用变量、模板、条件、循环与 handlers:
---
- name: 综合部署 Nginx + MySQL + 应用服务
hosts: web_servers
become: yes
vars_files:
- vars.yml
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
- name: restart mysql
service:
name: mysql
state: restarted
tasks:
- name: 安装基础软件包(循环)
apt:
name: "{{ item }}"
state: present
update_cache: yes
loop: "{{ packages }}"
- name: 确保 MySQL 服务已启动
service:
name: mysql
state: started
enabled: yes
- name: 创建应用数据库(条件判断)
mysql_db:
name: "{{ db_name }}"
state: present
when: ansible_os_family == "Debian"
- name: 创建数据库用户(条件判断)
mysql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
priv: "{{ db_name }}.*:ALL"
state: present
when: ansible_os_family == "Debian"
- name: 渲染 Nginx 配置(模板)
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: restart nginx
- name: 渲染应用配置(模板)
template:
src: app.conf.j2
dest: /opt/{{ app_name }}/app.conf
notify: restart nginx
- name: 启动 Nginx 服务
service:
name: nginx
state: started
enabled: yes
5.4 运行与验证
# 语法检查
ansible-playbook --syntax-check deploy.yml
# 干跑模式
ansible-playbook -C deploy.yml
# 正式执行
ansible-playbook -i hosts deploy.yml
预期运行结果(节选):
PLAY [综合部署 Nginx + MySQL + 应用服务] *****************************
TASK [安装基础软件包(循环)] ****************************************
ok: [192.168.1.101]
TASK [创建应用数据库(条件判断)] ************************************
changed: [192.168.1.101]
TASK [渲染 Nginx 配置(模板)] ***************************************
changed: [192.168.1.101]
RUNNING HANDLER [restart nginx] **************************************
changed: [192.168.1.101]
PLAY RECAP ************************************************************
192.168.1.101 : ok=8 changed=5 unreachable=0 failed=0
验证服务是否正常:
curl -I http://192.168.1.101
mysql -u app_user -p -e "SHOW DATABASES;"
5.5 常见错误排查
| 错误现象 | 可能原因 | 解决方法 |
|---|---|---|
FAILED! => "msg": "Can't connect to local MySQL server" | MySQL 未启动或未安装 | 先执行 service mysql start,确认 packages 中包含 mysql-server |
"msg": "Access denied for user 'app_user'@'localhost'" | 数据库用户密码不匹配 | 检查 vars.yml 中 db_password 与 mysql_user 是否一致 |
"msg": "template source file not found" | 模板路径错误 | 确认 templates/ 目录与 Playbook 同级,文件名拼写正确 |
"msg": "handler 'restart nginx' was not defined" | handlers 拼写或缩进错误 | 检查 handlers 是否与 tasks 同级,名称是否与 notify 一致 |
"msg": "The loop variable 'item' is already in use" | 循环变量冲突 | 使用 loop_control: loop_var: pkg 自定义循环变量名 |
"msg": "Unsupported parameters for (mysql_db) module" | 缺少 python3-pymysql | 在 packages 中加入 python3-pymysql 并重新执行 |
4.1 编写第一个 Playbook
创建 first-playbook.yml:
---
- name: 我的第一个 Playbook
hosts: all
become: yes
tasks:
- name: 确保 NTP 服务已安装
apt:
name: ntp
state: present
- name: 启动并设置开机自启
service:
name: ntp
state: started
enabled: yes
4.2 运行 Playbook
ansible-playbook -i hosts first-playbook.yml
4.3 检查语法
ansible-playbook --syntax-check first-playbook.yml
4.4 干跑模式
ansible-playbook -C first-playbook.yml
5. 常用模块深入
5.1 文件操作模块
- name: 创建目录
file:
path: /opt/myapp
state: directory
mode: '0755'
- name: 复制配置文件
copy:
src: /local/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
5.2 软件包管理
- name: 安装多个软件包
apt:
name:
- git
- curl
- vim
state: present
update_cache: yes
5.3 服务管理
- name: 重启 Nginx 服务
service:
name: nginx
state: restarted
5.4 用户管理
- name: 创建部署用户
user:
name: deploy
groups: www-data
shell: /bin/bash
create_home: yes
6. 变量与模板
6.1 变量定义方式
变量可在 Inventory、Playbook、文件或命令行中定义:
---
- name: 使用变量
hosts: all
vars:
app_port: 8080
app_name: myapp
tasks:
- name: 输出变量
debug:
msg: "应用 {{ app_name }} 运行在端口 {{ app_port }}"
6.2 使用 Jinja2 模板
创建模板文件 nginx.conf.j2:
server {
listen {{ nginx_port }};
server_name {{ server_name }};
root /var/www/{{ app_name }};
}
在 Playbook 中渲染模板:
- name: 渲染 Nginx 配置
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: restart nginx
6.3 变量优先级
变量优先级从低到高为:Inventory 变量 → Playbook 变量 → 文件变量 → 命令行变量(-e)。
7. 条件与循环
7.1 条件判断
- name: 仅在 Debian 系统执行
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: 根据变量执行
command: echo "条件满足"
when: app_enabled and port > 1000
7.2 循环遍历
- name: 创建多个用户
user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- charlie
- name: 遍历字典
debug:
msg: "{{ item.key }} = {{ item.value }}"
loop: "{{ my_dict | dict2items }}"
8. Roles 角色化实战
8.1 创建 Role 结构
ansible-galaxy init nginx
生成的目录结构:
nginx/
├── defaults/ # 默认变量
├── files/ # 静态文件
├── handlers/ # 处理器
├── meta/ # 角色元数据
├── tasks/ # 主任务
├── templates/ # Jinja2 模板
├── tests/ # 测试
└── vars/ # 角色变量
8.2 编写 Role 任务
nginx/tasks/main.yml:
---
- name: 安装 Nginx
apt:
name: nginx
state: present
- name: 配置站点
template:
src: default.conf.j2
dest: /etc/nginx/conf.d/default.conf
notify: restart nginx
- name: 启动服务
service:
name: nginx
state: started
enabled: yes
8.3 在 Playbook 中引用 Role
---
- name: 部署 Web 服务器
hosts: web_servers
become: yes
roles:
- nginx
- { role: mysql, db_user: admin }
9. Ansible Galaxy 使用
Ansible Galaxy 是社区共享 Role 的平台,可快速获取现成角色:
# 搜索角色
ansible-galaxy search nginx
# 安装角色
ansible-galaxy install geerlingguy.nginx
# 安装到指定目录
ansible-galaxy install -r requirements.yml
10. 性能优化与最佳实践
10.1 开启 SSH 长连接
在 ansible.cfg 中配置:
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
10.2 并行执行
ansible-playbook -f 10 playbook.yml
10.3 使用 serial 滚动更新
- name: 滚动更新
hosts: web_servers
serial: 2
tasks:
- name: 更新应用
service:
name: myapp
state: restarted
10.4 最佳实践清单
- 使用
ansible-lint检查 Playbook 规范。 - 将敏感信息放入 Ansible Vault 加密。
- 使用
--check模式先行验证。 - 保持 Playbook 幂等性,避免重复执行副作用。
- 为每个 Role 编写 README 和默认变量。
11. Ansible Vault 加密
11.1 创建加密文件
ansible-vault create secrets.yml
11.2 编辑加密文件
ansible-vault edit secrets.yml
11.3 使用加密变量
- name: 使用加密变量
hosts: all
vars_files:
- secrets.yml
tasks:
- name: 输出密码
debug:
msg: "数据库密码是 {{ db_password }}"
运行 Playbook 时输入密码:
ansible-playbook --ask-vault-pass playbook.yml
12. 常见问题与排错
12.1 SSH 连接失败
# 测试连通性
ansible all -m ping
# 查看详细错误
ansible-playbook -vvv playbook.yml
12.2 权限不足
确保 Playbook 中使用了 become: yes,且被管理节点用户具有 sudo 权限。
12.3 模块不存在
检查 Ansible 版本与模块兼容性,使用 ansible-doc -l 查看可用模块。
13. 总结与进阶方向
通过本教程,你已经掌握了 Ansible 的核心概念、Playbook 编写、变量模板、条件循环、Roles 角色化以及性能优化等关键技能。接下来可以深入探索:
- Ansible Tower / AWX:企业级 Web 管理界面。
- Ansible Collections:模块化分发与复用。
- 动态 Inventory:对接云平台自动获取主机列表。
- 网络自动化:使用
ansible-network管理交换机路由器。
持续实践是精通 Ansible 的关键,建议从管理 2-3 台测试服务器开始,逐步扩展到生产环境。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2601_96632650/article/details/168453577




