Inventory 与 Ad-hoc 命令
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read469 words

Inventory 与 Ad-hoc 命令

核心问题:Ansible 怎么知道要管理哪些服务器?在写 Playbook 之前,怎么快速测试连通性和执行一次性命令?


Ansible 工作原理

Ansible 是无 Agent 的推模型:控制节点通过 SSH 连接到被管节点,推送 Python 模块执行任务,执行完毕后模块自动删除。被管节点只需要:

  1. SSH 可达(默认端口 22)
  2. Python 3.x 已安装(大多数现代 Linux 自带)
graph LR CTRL["控制节点
(你的笔记本/跳板机)
ansible-playbook 运行在这里"] A["被管节点 A
web-01"] B["被管节点 B
web-02"] C["被管节点 C
db-01"] CTRL -->|SSH + Python 模块| A CTRL -->|SSH + Python 模块| B CTRL -->|SSH + Python 模块| C

Inventory 文件

Inventory 是 Ansible 的"花名册",告诉 Ansible 有哪些主机、如何分组。

INI 格式(最常用)

# inventory/hosts.ini
# 单独列出主机
web-01.example.com
web-02.example.com
# 分组
[webservers]
web-01.example.com ansible_user=ubuntu
web-02.example.com ansible_user=ubuntu ansible_port=2222
[databases]
db-01.example.com ansible_user=admin
db-02.example.com ansible_user=admin
# 组的组(父组)
[production:children]
webservers
databases
# 组变量
[webservers:vars]
ansible_ssh_private_key_file=~/.ssh/prod_key
http_port=80

YAML 格式(推荐,结构更清晰)

# inventory/hosts.yml
all:
children:
webservers:
hosts:
web-01.example.com:
ansible_user: ubuntu
ansible_port: 22
web-02.example.com:
ansible_user: ubuntu
vars:
http_port: 80
deploy_dir: /var/www/html
databases:
hosts:
db-01.example.com:
ansible_user: admin
ansible_port: 22
vars:
pg_version: "15"

Inventory 中的连接变量

变量 说明 示例
ansible_host 实际 IP(主机名只是别名) ansible_host=10.0.1.100
ansible_user SSH 登录用户名 ansible_user=ubuntu
ansible_port SSH 端口 ansible_port=2222
ansible_ssh_private_key_file SSH 私钥路径 ~/.ssh/id_rsa
ansible_password SSH 密码(不推荐,用密钥)
ansible_become 是否使用 sudo ansible_become=true
ansible_become_user sudo 目标用户 ansible_become_user=root
ansible_python_interpreter Python 路径 /usr/bin/python3

动态 Inventory

当服务器列表频繁变动(自动扩缩容、云环境),静态 INI 文件很难维护。动态 Inventory 是一个可执行脚本,输出 JSON 格式的主机列表。

AWS EC2 动态 Inventory

# 安装 amazon.aws 集合
ansible-galaxy collection install amazon.aws
# 配置 aws_ec2.yml
# inventory/aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- ap-southeast-1
filters:
instance-state-name: running
"tag:Env": production
keyed_groups:
- key: tags.Role
prefix: role
- key: placement.availability_zone
prefix: az
hostnames:
- private-ip-address   # 使用私有 IP
# 测试动态 Inventory
ansible-inventory -i inventory/aws_ec2.yml --list
# 使用动态 Inventory 执行
ansible -i inventory/aws_ec2.yml role_webserver -m ping

ansible.cfg 配置文件

# ansible.cfg(放在项目根目录,优先级高于全局配置)
[defaults]
inventory       = inventory/hosts.yml
remote_user     = ubuntu
private_key_file = ~/.ssh/prod_key
host_key_checking = False       # 首次连接不提示 known_hosts
stdout_callback = yaml          # 更可读的输出格式
callbacks_enabled = timer       # 显示任务耗时
[privilege_escalation]
become      = True
become_method = sudo
become_user = root

Ad-hoc 命令

Ad-hoc 命令是不写 Playbook、直接在命令行执行单个模块的方式。适合: - 快速测试连通性 - 紧急修复单台服务器 - 一次性查询

基本语法

ansible <主机/组> -i <inventory> -m <模块> -a "<参数>"

常用 Ad-hoc 命令速查

# ① 测试连通性(ping 模块)
ansible all -m ping
# web-01.example.com | SUCCESS => {"ping": "pong"}
# ② 查看系统信息(gather_facts)
ansible webservers -m setup -a "filter=ansible_distribution*"
# ③ 执行 Shell 命令(避免生产环境常规使用)
ansible webservers -m shell -a "df -h"
ansible webservers -m shell -a "systemctl status nginx"
# ④ 安装软件包
ansible webservers -m apt -a "name=nginx state=present" --become
# ⑤ 复制文件
ansible webservers -m copy -a "src=./nginx.conf dest=/etc/nginx/nginx.conf" --become
# ⑥ 重启服务
ansible webservers -m service -a "name=nginx state=restarted" --become
# ⑦ 批量创建用户
ansible all -m user -a "name=deploy state=present shell=/bin/bash" --become
# ⑧ 限制主机(-l 参数)
ansible webservers -l web-01.example.com -m ping
# ⑨ 并发控制(默认 5 个并发)
ansible all -m ping -f 10   # 10 个并发
# ⑩ 检查模式(不实际执行,只报告变更)
ansible webservers -m apt -a "name=nginx state=present" --check

Inventory 主机模式

# 所有主机
ansible all -m ping
# 指定组
ansible webservers -m ping
# 多个组
ansible 'webservers:databases' -m ping
# 排除某组
ansible 'all:!databases' -m ping
# 两组的交集
ansible 'webservers:&production' -m ping
# 通配符
ansible 'web-*' -m ping
# 正则(~ 开头)
ansible '~web-[0-9]+' -m ping

快速排错

错误 原因 解决
UNREACHABLE! Connection timed out 防火墙或 SSH 端口不对 检查安全组、ansible_port 变量
Permission denied (publickey) SSH 密钥不对 检查 ansible_ssh_private_key_file
Python not found Python 未安装 ansible_python_interpreter=/usr/bin/python3 或先安装 Python
sudo: no tty present sudo 需要密码 配置 NOPASSWD 或传 --ask-become-pass
[WARNING] No inventory was parsed inventory 路径错误 检查 -i 参数或 ansible.cfg 中的路径

下一节Playbook 结构与常用模块