当你需要管理 2 台服务器时,手动 SSH 上去敲命令还能接受。但当服务器变成 20 台、200 台时,逐台登录操作就是一场灾难。Ansible 就是为解决这个问题而生——通过 SSH 批量控制远程主机,无需在目标机器上安装任何 Agent,开箱即用。
本文从零开始,带你完成 Ansible 的安装、配置、SSH 密钥认证,并通过 4 个核心模块的实战演练,让你快速上手批量管理服务器。
一、安装 Ansible
Ansible 在 EPEL 源中,CentOS/RHEL 系统需要先配置 EPEL 源:
# 配置 EPEL 源(以 CentOS 7 为例)vi /etc/yum.repos.d/epel.repo[epel]name=epelbaseurl=https://mirrors.aliyun.com/epel/7/x86_64/gpgcheck=0
# 安装 Ansibleyum install ansible -y# 验证安装ansible --version
其他系统安装方式:
Ubuntu/Debian:
apt install ansiblepip 安装(推荐获取最新版):
pip install ansible
二、目录结构与配置文件
核心文件一览
| 路径 | 说明 |
|---|---|
/etc/ansible/ansible.cfg | 主配置文件,控制 Ansible 的工作行为 |
/etc/ansible/hosts | 主机清单(Inventory),定义被管理的服务器 |
/etc/ansible/roles/ | 存放 Roles 的目录 |
核心程序
| 命令 | 用途 |
|---|---|
ansible | 主程序,执行临时命令(Ad-Hoc) |
ansible-playbook | 执行 Playbook(剧本) |
ansible-doc | 查看模块文档 |
ansible-galaxy | 下载/管理社区 Roles |
ansible-vault | 加密敏感文件(密码、密钥等) |
ansible-console | 交互式执行命令的控制台 |
ansible.cfg 关键配置
默认配置文件大部分保持默认即可,但建议修改以下 3 项:
[defaults]# 1. 关闭主机密钥检查(否则首次连接每台主机都要手动确认)host_key_checking = False# 2. 开启日志记录(方便排查问题)log_path = /var/log/ansible.log# 3. 将默认模块改为 shell(command 模块不支持管道、重定向等功能)module_name = shell
| 配置项 | 默认值 | 说明 |
|---|---|---|
inventory | /etc/ansible/hosts | 主机清单文件路径 |
remote_tmp | ~/.ansible/tmp | 远程主机临时文件目录 |
forks | 5 | 并发执行的主机数 |
remote_port | 22 | SSH 连接端口 |
ask_pass | True | 是否提示输入 SSH 密码 |
sudo_user | root | 默认 sudo 用户 |
三、主机清单(Inventory)
主机清单是 Ansible 的核心概念之一,它定义了你要管理哪些服务器,以及如何对它们分组。
基本格式
主机清单遵循 INI 文件风格:
# /etc/ansible/hosts[webserver] # 中括号中的字符为组名192.168.1.10192.168.1.11:2222 # 非标准 SSH 端口[appserver]192.168.1.10 # 同一主机可以属于多个组192.168.1.[20:30] # 连续 IP 的简写方式(20~30)[dbserver]db-node[01:03].example.com # 主机名也支持列表写法
常用主机模式
# 操作所有主机ansible all -m ping# 操作指定组ansible webserver -m ping# 操作多个组(并集)ansible 'webserver:appserver' -m ping# 操作交集(同时属于两个组的主机)ansible 'webserver:&appserver' -m ping# 排除某个组ansible 'all:!dbserver' -m ping
四、SSH 认证:密码 vs 密钥
Ansible 通过 SSH 连接远程主机,有两种认证方式。
方式一:密码认证(临时使用)
# -k 选项提示输入 SSH 密码ansible webserver -m ping -kSSH password:192.168.1.10 | SUCCESS => {"changed": false,"ping": "pong"}
密码认证要求所有被管理主机的密码相同,且每次都要输入,不推荐生产使用。
方式二:密钥认证(生产推荐)
第一步:在 Ansible 管理机上生成密钥对
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa第二步:将公钥分发到所有被管理主机
ssh-copy-id 192.168.1.10ssh-copy-id 192.168.1.11# ... 对每台被管理主机执行
第三步:验证免密连接
# 不再需要 -k 选项ansible webserver -m ping192.168.1.10 | SUCCESS => {"changed": false,"ping": "pong"}192.168.1.11 | SUCCESS => {"changed": false,"ping": "pong"}
批量分发密钥的技巧: 当主机很多时,可以用
sshpass配合循环来批量分发:for ip in 10 11 12; do sshpass -p 'your_password' ssh-copy-id -o StrictHostKeyChecking=no 192.168.1.$ipdone
补充:sudo 提权
有时需要以普通用户 SSH 登录,再通过 sudo 执行特权操作:
# -u 指定登录用户,-b 启用 sudo 提权,-K 输入 sudo 密码ansible webserver -m ping -u deploy -k -b -K
如果在目标机器上配置了
NOPASSWD,则不需要-K选项。
五、核心模块实战
ansible-doc:查看模块文档
在使用任何模块之前,都可以用 ansible-doc 查看用法:
# 查看模块详细文档ansible-doc copy# 查看简要用法(推荐)ansible-doc -s copy# 列出所有可用模块ansible-doc -l
5.1 ping 模块 — 连通性测试
最简单的模块,用于验证 Ansible 能否正常连接到目标主机:
ansible webserver -m ping192.168.1.10 | SUCCESS => {"changed": false,"ping": "pong"}
返回
pong表示连接成功。注意:这不是 ICMP ping,而是 Ansible 通过 SSH 连接并执行 Python 代码来验证连通性。
5.2 shell 模块 — 执行 Shell 命令
shell 模块用于在远程主机上执行 Shell 命令,支持管道、重定向、变量等所有 Shell 特性。
示例 1:执行基本命令
ansible webserver -m shell -a 'echo 123456 | passwd --stdin deploy'192.168.1.10 | CHANGED | rc=0 >>Changing password for user deploy.passwd: all authentication tokens updated successfully.
示例 2:单引号 vs 双引号(重要)
# 单引号:变量在远程主机上解析(正确)ansible webserver -m shell -a 'echo $HOSTNAME'192.168.1.10 | CHANGED | rc=0 >>web1192.168.1.11 | CHANGED | rc=0 >>web2# 双引号:变量在本机解析(通常不是你想要的)ansible webserver -m shell -a "echo $HOSTNAME"192.168.1.10 | CHANGED | rc=0 >>ansible-server192.168.1.11 | CHANGED | rc=0 >>ansible-server
记住: Ansible 命令中的
-a参数,用单引号包裹可以防止本机 Shell 提前展开变量。
示例 3:切换目录 + 重定向
# chdir 参数:先 cd 到指定目录再执行命令ansible webserver -m shell -a 'chdir=/data echo "hello ansible" > test.log'# 验证ansible webserver -m shell -a 'cat /data/test.log'192.168.1.10 | CHANGED | rc=0 >>hello ansible
示例 4:使用 sed 修改文件
ansible webserver -m shell -a 'sed -i "s/old_text/new_text/" /data/test.log'Ansible 会提示建议使用
replace、lineinfile或template模块替代sed,这些模块具备幂等性,多次执行结果一致。
shell vs command 模块
| 特性 | command(默认) | shell |
|---|---|---|
管道 \| | 不支持 | 支持 |
重定向 >>> | 不支持 | 支持 |
变量 $VAR | 不支持 | 支持 |
通配符 * | 不支持 | 支持 |
| 安全性 | 更安全(不经过 Shell 解释) | 注意命令注入风险 |
这就是为什么建议在
ansible.cfg中把默认模块改为shell——command 模块限制太多,日常使用不方便。
5.3 script 模块 — 远程执行本机脚本
script 模块可以在远程主机上执行 Ansible 管理机上的脚本,无需事先将脚本复制过去。
# 在管理机上编写脚本cat > /server/scripts/hello.sh << 'EOF'#!/bin/bashecho"hello world from $(hostname)"EOFchmod +x /server/scripts/hello.sh# 在所有 webserver 上执行ansible webserver -m script -a '/server/scripts/hello.sh'192.168.1.10 | CHANGED => {"changed": true,"rc": 0,"stdout": "hello world from web1\r\n", ...}
适用场景: 临时需要在远程主机执行一段逻辑,但不想把脚本复制过去。常驻脚本推荐用
copy模块先分发再执行。
5.4 copy 模块 — 文件分发
将管理机上的文件复制到远程主机,支持设置权限、属主、备份等。
| 参数 | 说明 |
|---|---|
src | 管理机上的源文件路径 |
dest | 远程主机的目标路径(必填) |
owner | 设置文件属主 |
group | 设置文件属组 |
mode | 设置文件权限 |
backup | 目标文件已存在时是否备份(yes/no) |
content | 直接指定文件内容(与 src 二选一) |
示例 1:复制文件并设置权限
ansible webserver -m copy -a 'src=/etc/fstab dest=/data/fstab.bak owner=deploy mode=0644 backup=yes'192.168.1.10 | CHANGED => {"changed": true,"dest": "/data/fstab.bak","owner": "deploy","mode": "0644", ...}
backup=yes 的效果:如果目标文件已存在且内容不同,会自动备份为
文件名.日期时间.bak,防止覆盖丢失。
示例 2:直接生成文件内容
ansible webserver -m copy -a 'content="hello ansible\nwelcome\n" dest=/data/greeting.txt'# 验证ansible webserver -a 'cat /data/greeting.txt'192.168.1.10 | CHANGED | rc=0 >>hello ansiblewelcome
content参数适合生成简短的配置文件或标记文件,复杂模板推荐用template模块。
六、补充:更多常用模块速览
除了上面详细讲解的 4 个模块,以下模块在日常运维中也非常高频:
| 模块 | 用途 | 示例 |
|---|---|---|
yum / apt | 软件包管理 | ansible all -m yum -a 'name=nginx state=present' |
systemd / service | 服务管理 | ansible all -m systemd -a 'name=nginx state=started enabled=yes' |
file | 文件/目录管理 | ansible all -m file -a 'path=/data state=directory mode=0755' |
lineinfile | 修改文件中的某一行 | ansible all -m lineinfile -a 'path=/etc/hosts line="192.168.1.10 web1"' |
user | 用户管理 | ansible all -m user -a 'name=deploy state=present' |
cron | 定时任务管理 | ansible all -m cron -a 'name="sync time" minute="*/5" job="/sbin/ntpdate ntp.aliyun.com"' |
fetch | 从远程主机拉取文件到管理机 | ansible all -m fetch -a 'src=/var/log/messages dest=/tmp/' |
template | 使用 Jinja2 模板生成配置文件 | 在 Playbook 中使用 |
unarchive | 解压文件到远程主机 | ansible all -m unarchive -a 'src=app.tar.gz dest=/opt/' |
七、Ansible 命令选项速查
ansible <主机模式> [-m 模块] [-a '参数']| 选项 | 说明 |
|---|---|
-m module | 指定模块(默认 command) |
-a 'args' | 模块参数 |
-k | 提示输入 SSH 密码 |
-u user | 指定远程登录用户 |
-b | 启用 sudo 提权 |
-K | 提示输入 sudo 密码 |
-C | 检查模式(只检查不执行) |
-v / -vv / -vvv | 显示详细过程(v 越多越详细) |
--list-hosts | 显示匹配的主机列表 |
-T timeout | 设置连接超时时间 |
--version | 显示版本信息 |
八、新手避坑指南
首次连接报 host_key 错误 — 在
ansible.cfg中设置host_key_checking = False。command 模块不支持管道和重定向 — 改用
shell模块,或修改默认模块为 shell。双引号导致变量在本机展开 —
-a参数用单引号包裹。执行命令提示 Permission denied — 检查 SSH 密钥是否分发,或使用
-k输入密码。sudo 报错 "a password is required" — 加上
-K选项,或在目标机配置NOPASSWD。模块不知道怎么用 — 先跑一次
ansible-doc -s 模块名,养成查文档的习惯。copy 模块覆盖了重要文件 — 加上
backup=yes参数,自动备份原文件。
写在最后
本文覆盖了 Ansible 入门的完整路径:
安装部署 + 3 项关键配置修改
主机清单的格式、分组与主机模式
SSH 密码认证与密钥认证的完整流程
sudo 提权的使用方法
4 大核心模块深度实战(ping / shell / script / copy)
shell vs command 对比、单引号 vs 双引号的区别
常用模块速览 + 命令选项速查 + 新手避坑指南
这是 Ansible 自动化的第一课。 掌握了 Ad-Hoc 命令后,接下来将进入更强大的领域:
Playbook — 将操作编排成可复用的剧本
Roles — 项目级别的组织方式,代码复用的最佳实践
变量与模板 — 让同一套 Playbook 适配不同环境
关注本公众号,Ansible 系列持续更新,每篇都是从零到生产的完整闭环。
夜雨聆风