前言
本文档系统梳理了自动化运维工具 Ansible 的核心概念、工作机制、安装配置及常用模块操作,涵盖从基础命令到主机清单(Inventory)变量管理的完整知识体系。适用于初学者快速上手和企业级批量服务器管理场景。
- Ansible 概述与运行机制
- Ansible 安装与免密 SSH 配置
- Ansible 基础命令及 13 个常用模块详解(command、shell、cron、user、group、copy、file、hostname、ping、yum、service、script、setup)
- Inventory 主机清单分组与变量配置(含端口、用户、密码、嵌套组等)
理论部分
1_概述和运行机制
Ansible 是一款基于 Python 开发的开源自动化运维工具,采用无代理(agentless)架构,通过 SSH 协议实现对远程主机的集中化管理。
2015 年被红帽收购,成为企业级自动化标准工具之一。
1.1 核心特性
- 无需客户端:被管理节点不需安装任何代理程序。
- 基于 SSH:默认使用 SSH(端口 22)进行安全通信。
- 声明式配置:使用 YAML 格式的 Playbook 定义目标状态。
- 幂等性设计:多数模块多次执行结果一致,避免重复操作。
- 高扩展性:支持自定义模块(Python)、插件及 API 集成。
1.2 工作机制
Ansible 控制端通过 SSH 将临时 Python 模块推送到被控节点 → 执行任务 → 返回结果 → 自动删除模块。整个过程无需持久化组件,轻量高效。
1.3 核心组成
| 组件 | 作用 |
|---|---|
| Inventory | 主机清单(/etc/ansible/hosts),定义被控主机及分组 |
| Modules | 功能单元(如 copy、yum),执行具体操作 |
| Plugins | 扩展功能(连接、回调、过滤器等) |
| Playbooks | YAML 文件,编排多步骤复杂任务 |
| Roles | 模块化组织 Playbook,提升复用性与可维护性 |
2_安装与连接原理
在控制端部署 Ansible 后,需通过 SSH 免密认证建立与被控节点的信任关系,这是实现自动化批量操作的前提。
2.1 安装方式
- 依赖 EPEL 源(Extra Packages for Enterprise Linux)
- 通过
yum install ansible一键安装 - 安装后生成默认目录
/etc/ansible/
2.2 连接机制
- 默认协议:SSH(端口 22)
- 认证方式:推荐基于密钥的免密登录
- 提权支持 :通过
become机制(sudo/su)执行特权命令 - 端口灵活性 :可通过 Inventory 变量指定非标准端口(如
ansible_port=2222)
⚠️ 被控节点必须安装 Python(2.7+ 或 3.5+),因 Ansible 模块以 Python 脚本形式运行。
3_模块化操作原理
Ansible 的所有操作均通过模块(Module) 实现。每个模块封装特定功能,具备幂等性、参数化和跨平台特性。
3.1 模块调用机制
shell
ansible <组名> -m <模块> -a '<参数>'
- 使用
-m <模块名>指定功能模块 - 使用
-a "<参数>"传递模块所需参数 - 若省略
-m,默认使用command模块
3.2 模块分类与作用
| 类别 | 模块示例 | 功能说明 |
|---|---|---|
| 命令执行 | command, shell, script |
在远程主机运行命令或脚本 |
| 系统管理 | user, group, cron, hostname |
管理用户、组、计划任务、主机名 |
| 文件操作 | copy, file |
复制文件、设置属性、创建链接 |
| 软件与服务 | yum, service |
安装软件包、控制系统服务 |
| 信息收集 | setup, ping |
获取主机 facts、测试连通性 |
command、shell、script区别
- command :直接执行命令,不经过 Shell ,所以不能用
|、>、$()这些符号。最安全,适合简单命令。 - shell :通过 Shell 执行,支持所有 Shell 功能(比如管道、变量、重定向),功能强,但可能有风险。
- script :把你本地的脚本文件自动传到远程机器上运行,适合复杂任务。
3.3 常用的参数
chdir:在远程主机上运行命令前,提前进入目录。creates:判断制定文件是否存在。如果存在,不执行后面的操作。removes:判断制定文件是否存在,如果存在,执行后面的操作。
例子:
shell
ansible all -m command -a "chdir=/home ls ./"
所有组 命令模块 执行 先进入/home 然后查看当前目录
3.4 幂等性原则
- 模块设计遵循"目标状态"理念(如
copy仅当内容变化才覆盖) - 避免重复执行导致副作用(如
yum安装已存在包时不报错) - 这是自动化可靠性的基石
简单理解:
- 幂等性意思是:同一个操作执行一次和执行多次,结果都一样,不会重复产生副作用。
- 比如"安装 nginx"如果是幂等的,那装过一次后,再运行也不会重新装或报错。
- 但
command/shell/script一般不幂等 ------你让它们"写一行日志",跑十次就写十行。专用模块(如yum、copy)才具备幂等性。
在 Ansible 的默认输出(使用 default callback 插件)中,任务执行结果会以不同颜色和状态词显示。以下是常见的状态及其含义、颜色(在支持 ANSI 色彩的终端中):
3.4 提示信息
✅ CHANGED(黄色)
- 含义:任务对目标主机进行了修改(如创建了文件、启动了服务等)。
- 颜色 :黄色(Yellow)
- 效果:表示系统状态发生了变更。
示例:首次安装软件包、写入新配置文件。
✅ OK(绿色)
- 含义 :任务成功执行,但没有做任何更改(幂等性体现)。
- 颜色 :绿色(Green)
- 效果:一切正常,无需操作。
示例:再次运行已配置好的任务,发现目标已符合预期。
❌ FAILED(红色)
- 含义:任务执行失败(命令返回非零、模块报错等)。
- 颜色 :红色(Red)
- 效果 :Playbook 默认在此处停止(除非设置了
ignore_errors: yes)。
⚠️ UNREACHABLE(红色)
- 含义:Ansible 无法连接到目标主机(SSH 失败、超时等)。
- 颜色 :红色(Red)
- 效果:主机不可达,后续任务跳过。
🔄 SKIPPED(蓝色或青色)
- 含义 :任务因
when条件不满足而被跳过。 - 颜色 :蓝色(Blue)或青色(Cyan)(取决于终端/版本)
- 效果:正常跳过,不算失败。
📦 CHANGED vs OK 的核心区别
| 状态 | 是否修改系统 | 幂等性体现 | 颜色 |
|---|---|---|---|
OK |
❌ 否 | ✅ 是 | 绿色 |
CHANGED |
✅ 是 | ❌ 首次运行 | 黄色 |
🔧 其他提示
- 如果你使用
--diff参数,CHANGED任务还会显示具体变更内容(如文件差异)。 - 在
ansible.cfg中可通过stdout_callback更换输出格式(如yaml、debug),颜色和样式会变化。 - 在 CI/日志环境中(无色彩终端),颜色会自动禁用,仅显示文字状态。
示例输出(带颜色示意)
bash
webserver : ok=2 changed=1 unreachable=0 failed=0 skipped=0
ok=2→ 两个任务无变更(绿色)changed=1→ 一个任务做了修改(黄色)
需要调整输出颜色或格式?可以配置 callback 插件。
实验部分
1_环境搭建
| 节点 | 主机名 | 角色 | IP 地址 | 用途 |
|---|---|---|---|---|
| node8 | ansible | 管理端 | 192.168.100.8 | 安装 Ansible,执行命令 |
| node9 | ansible_client1 | 被管理端 | 192.168.100.9 | Web 服务器(webservers 组) |
| node10 | ansible_client2 | 被管理端 | 192.168.100.10 | DB 服务器(dbservers 组) |
1.1_安装Ansible
① 安装 Ansible
- 在管理端执行:
shell
yum install -y epel-release
yum install -y ansible
epel-release:提供额外的 RPM 包源
ansible:主程序包,包含核心命令与模块
② 查看默认目录结构
shell
ls /etc/ansible/
输出应包含:
ansible.cfg:全局配置文件(通常无需修改)hosts:默认 Inventory 主机清单roles/:角色存放目录
1.2_配置主机清单
/etc/ansible/hosts
ini
[webservers]
192.168.100.9
[dbservers]
192.168.100.10
[webservers]:定义主机组名
192.168.100.9:组内主机 IP(也可用主机名,需配/etc/hosts)
1.3_配置SSH免密登录
- 生成 SSH 密钥(若未存在):
shell
ssh-keygen -t rsa
-t rsa:指定密钥类型为 RSA
- 使用
sshpass批量分发公钥(假设 root 密码为123456):
shell
sshpass -p '123456' ssh-copy-id root@192.168.100.9
sshpass -p '123456' ssh-copy-id root@192.168.100.10
sshpass:非交互式输入密码工具
ssh-copy-id:将本地公钥复制到远程主机的~/.ssh/authorized_keys
⚠️ 生产环境建议使用密钥认证,避免明文密码。
2_基础操作
2.1_命令通用格式
shell
ansible <组名|IP|all> -m <模块名> -a "<参数>"
若省略
-m,默认使用command模块
2.2_模块操作
① command 模块
- 查看模块帮助:
shell
ansible-doc -s command
- 执行命令示例:
shell
ansible 192.168.100.9 -m command -a 'date'
ansible webservers -m command -a 'date'
ansible all -m command -a 'date'
ansible all -a 'ls /' # 等价于 -m command
command是默认模块,不用-m command指定也可以。
- 常用参数:
chdir:先切换目录再执行命令creates:若文件存在则跳过执行
shell
ansible all -m command -a "chdir=/home ls ./"
❌ 不支持管道
|、重定向>、变量$()等 Shell 特性
② shell 模块
- 支持完整 Shell 功能:
shell
ansible dbservers -m shell -a 'echo 123456 | passwd --stdin test'
ansible dbservers -m shell -a 'echo $(ifconfig ens33 | awk "NR==2 {print \$2}")'
注意:
$需转义为\$,防止本地 Shell 提前解析
③ cron 模块
- 添加计划任务:
shell
ansible webservers -m cron -a 'minute="*/2" hour="21" weekday="5" job="/bin/echo $(date)-helloworld" name="test crontab"'
- 查看并删除:
shell
ansible webservers -a 'crontab -l'
ansible webservers -m cron -a 'name="test crontab" state=absent'
state=present(默认)表示添加,absent表示删除若任务无
name,删除时设name=None
④ user 模块
- 创建用户
shell
ansible dbservers -m user -a 'name="test01" state=present'
ansible dbservers -m user -a 'name="test01"'
state=present:表示创建(用户),缺省state值就是present。
- 删除用户:
shell
ansible dbservers -m user -a 'name="test01" state=absent'
ansible dbservers -m user -a 'name="test01" state=absent remove=yes'
state=absent:表示删除(用户)
remove=yes:同时删除家目录和邮件池,类似userdel -r。
- 指定属性:
shell
ansible dbservers -m user -a \
'name=test02 \
state=present \
system=yes \
uid=306 \
group=mysql \
shell=/usr/bin/bash \
home=/home/TEST02 \
move_home=yes \
comment="Manage MySQL user" \
password="$6$saltsalt123$PbfsKUWUdNC3prhSFt2D5u3fPUyE8gN9AzAzi7U3VePQgCtiB24Qar.ZNaGnDfKA08XyL1.jRgJefF70k7QCc1"'
关键参数
name=用户名:必填,指定用户名
state=present|absent:创建|删除
system=yes|no:是否为系统用户
uid=用户ID:指定用户UID
group=组名:指定基本组
shell=SHELL程序:默认使用的SHELL程序
home=家目录:指定用户的家目录
create_home=yes:如果没有家目录就创建一个(默认可缺省)
move_home=yes|no:如果该用户家目录已经存在,则把原来的家目录移动到新路径。
comment=注释信息:用户的注释信息
password=密码:用户密码,建议使用加密后的字符串。加密字符串可以用python -c "import crypt; print(crypt.crypt('你的密码', '\$6\$任意盐值'))",盐值用于防爆破,可以是任意字符,盐值不用记录。$6是 密码哈希的"标识符",告诉系统:这个密码是用 SHA-512 算法加密的。
⑤ group 模块
- 创建用户组:
shell
ansible dbservers -m group -a 'name=mysql gid=306 system=yes'
- 验证:
shell
ansible dbservers -a 'tail /etc/group'
ansible dbservers -a 'id test01'
⑥ copy 模块
- 复制文件:
shell
ansible dbservers -m copy -a 'src=/etc/fstab dest=/opt/fstab.bak owner=root mode=640'
- 写入内容(不使用
src):
shell
ansible dbservers -m copy -a 'content="helloworld" dest=/opt/hello.txt'
src与content互斥;dest必须是绝对路径
⑦ file 模块
- 修改属性:
shell
ansible dbservers -m file -a 'owner=test01 group=mysql mode=644 path=/opt/fstab.bak'
- 创建软链接:
shell
ansible dbservers -m file -a 'path=/opt/fstab.link src=/opt/fstab.bak state=link'
- 创建/删除文件:
shell
ansible dbservers -m file -a "path=/opt/abc.txt state=touch"
ansible dbservers -m file -a "path=/opt/abc.txt state=absent"
⑧ hostname 模块
- 修改主机名:
shell
ansible dbservers -m hostname -a "name=mysql01"
⑨ ping 模块
- 测试连通性:
shell
ansible all -m ping
成功返回
pong
⑩ yum 模块
- 安装/卸载软件:
shell
ansible webservers -m yum -a 'name=httpd'
ansible webservers -m yum -a 'name=httpd state=absent'
⑪ service/systemd 模块
- 管理服务状态:
shell
ansible webservers -m service -a 'enabled=true name=httpd state=started'
参数:
name、state(started/stopped/restarted)、enabled(开机自启)
⑫ script 模块
- 执行本地脚本(自动传到远程执行):
shell
vim test.sh
#!/bin/bash
echo "hello ansible from script" > /opt/script.txt
chmod +x test.sh
ansible webservers -m script -a 'test.sh'
ansible webservers -a 'cat /opt/script.txt'
⑬ setup 模块
- 收集主机信息(facts):
shell
ansible webservers -m setup
ansible dbservers -m setup -a 'filter=*ipv4'
filter支持通配符,用于筛选特定信息(如 IP、内存、CPU)
1.3_Inventory 主机清单高级配置
① 主机变量(单机级别)
ini
[webservers]
192.168.100.9 ansible_port=2222 ansible_user=root ansible_password=abc1234
ansible_port=2222:指定非标准 SSH 端口
② 组变量(组级别)
ini
[webservers:vars]
ansible_user=root
ansible_password=abc1234
③ 全局变量
ini
[all:vars]
ansible_port=22
④ 主机范围匹配
ini
[webservers]
192.168.10.1[2:5] # 表示 12,13,14,15
db-[a:f].example.org # 表示 db-a 到 db-f
⑤ 组嵌套
ini
[nginx]
192.168.10.20
192.168.10.21
[apache]
192.168.10.30
192.168.10.31
[webs:children]
nginx
apache
webs组包含nginx和apache两个子组
⑥ 常用 Inventory 变量表
| 变量名 | 说明 |
|---|---|
ansible_host |
节点真实 IP(当主机名非 IP 时使用) |
ansible_port |
SSH 端口,默认 22 |
ansible_user |
SSH 登录用户 |
ansible_password |
SSH 密码(未用密钥时) |
ansible_ssh_private_key_file |
私钥路径 |
ansible_become |
是否提权(等同 sudo) |
ansible_become_method |
提权方式(sudo/su) |
ansible_become_user |
提权到的目标用户 |
ansible_become_password |
提权密码 |
结语
Ansible 核心要点:
- 无代理架构:依赖 SSH,轻量高效。
- 模块化设计:13+ 常用模块覆盖系统管理全场景。
- YAML 编排:Playbook 实现复杂任务自动化。
- Inventory 灵活分组:支持变量、嵌套、范围匹配。
- 幂等性保障:多数模块具备"多次执行结果一致"特性。
!question\] 请问 Ansible 为什么不需要在被控端安装客户端? 因其通过 SSH 协议直接推送临时 Python 模块执行,任务结束后自动清理,无需常驻进程。 \[!question\] command 和 shell 模块有何区别? `command` 不解析 Shell 特性(如管道、变量),更安全;`shell` 调用远程 Shell,支持完整 Shell 语法,但有注入风险。 \[!question\] 如何实现不同主机使用不同 SSH 端口? 在 Inventory 中为主机指定 `ansible_port=端口号`,例如 `192.168.100.9:2222` 或 `192.168.100.9 ansible_port=2222`。 \[!question\] facts 信息有什么作用? `setup` 模块收集的 facts 可用于 Playbook 中动态决策(如根据内存大小调整 JVM 参数)。