4. Inventory设计与分组:静态Inventory与动态Inventory、主机变量与组变量、环境分组(dev/staging/prod)
Inventory(清单)是 Ansible 管理主机的核心数据源,定义了哪些主机需要被管理、如何连接它们以及它们属于哪些逻辑分组。合理的 Inventory 设计直接决定了自动化任务的扩展性、可维护性和环境隔离能力。本章将深入讲解静态与动态 Inventory 的适用场景、变量继承机制以及基于环境的分组策略。
4.1 静态 Inventory 与动态 Inventory
Ansible 支持两种 Inventory 数据源:静态文件(INI 或 YAML 格式)和动态脚本(从外部系统实时获取主机列表)。
| 特性 | 静态 Inventory | 动态 Inventory |
|---|---|---|
| 数据来源 | 本地文件(hosts.ini / hosts.yml) | 外部 API、云平台、CMDB、脚本输出 |
| 变更频率 | 手动编辑,适合固定或少量主机 | 自动同步,适合弹性伸缩、容器化环境 |
| 可读性 | 高,直接查看文件即可 | 低,依赖脚本返回 JSON 格式 |
| 适用场景 | 开发环境、物理机、小规模集群 | 云环境(AWS/阿里云)、Kubernetes、大规模集群 |
| 执行方式 | ansible-playbook -i hosts.ini site.yml |
ansible-playbook -i ec2.py site.yml |
最佳实践: 对于 dev/staging 环境推荐使用静态 Inventory 以保证可追溯性;对于 prod 环境,如果使用云原生基础设施,优先采用动态 Inventory 避免主机列表与实际情况脱节。
4.2 主机变量与组变量
变量是 Inventory 中实现配置差异化的关键机制。Ansible 支持在主机级别和组级别定义变量,并遵循明确的优先级规则。
- 主机变量(host_vars): 定义在
host_vars/<hostname>.yml文件中,仅对单台主机生效。适用于 IP 地址、专属端口、特殊凭据等。 - 组变量(group_vars): 定义在
group_vars/<groupname>.yml文件中,对该组下所有主机生效。适用于通用配置参数、软件版本、环境标签等。 - 变量优先级: 主机变量 > 组变量 > Playbook 变量 > 角色默认变量。组变量中,子组变量优先级高于父组变量。
# 目录结构示例
inventory/
├── hosts.ini
├── group_vars/
│ ├── all.yml # 所有主机共享变量
│ ├── dev.yml # dev 组变量
│ ├── staging.yml # staging 组变量
│ └── prod.yml # prod 组变量
└── host_vars/
├── web01.dev.yml # 特定主机变量
└── db01.prod.yml
变量隔离技巧: 使用
group_vars/all.yml 存放全局默认值(如 NTP 服务器、DNS),使用环境级组变量覆盖差异项(如数据库连接串、日志级别),避免在 Playbook 中硬编码环境相关参数。
4.3 环境分组策略(dev / staging / prod)
环境分组是 Inventory 设计的核心实践,通过将主机按生命周期阶段分组,实现配置隔离、权限控制和发布流程的差异化。
4.4 环境分组 Inventory 示例
以下是一个基于 INI 格式的完整环境分组 Inventory 文件,展示了 dev、staging、prod 三个环境的主机定义和变量引用方式。
# inventory/hosts.ini
[dev:children]
dev-web
dev-db
[dev-web]
web01.dev ansible_host=10.0.1.10 ansible_user=devops
web02.dev ansible_host=10.0.1.11 ansible_user=devops
[dev-db]
db01.dev ansible_host=10.0.1.20 ansible_user=devops
[staging:children]
staging-web
staging-db
[staging-web]
web-stg1 ansible_host=10.0.2.10 ansible_user=deploy
web-stg2 ansible_host=10.0.2.11 ansible_user=deploy
[staging-db]
db-stg1 ansible_host=10.0.2.20 ansible_user=deploy
[prod:children]
prod-web
prod-db
[prod-web]
web-prd1 ansible_host=10.0.3.10 ansible_user=admin
web-prd2 ansible_host=10.0.3.11 ansible_user=admin
web-prd3 ansible_host=10.0.3.12 ansible_user=admin
[prod-db]
db-prd1 ansible_host=10.0.3.20 ansible_user=admin
db-prd2 ansible_host=10.0.3.21 ansible_user=admin
环境隔离注意事项: 生产环境(prod)应使用独立的 SSH 密钥、不同的连接用户(如 admin)以及更严格的 become 权限控制。建议在
group_vars/prod.yml 中设置 ansible_become: yes 和 ansible_become_method: sudo,而 dev 环境可以关闭提权以降低风险。
4.5 动态 Inventory 集成实践
当主机数量超过 100 台或频繁弹性伸缩时,动态 Inventory 是更优选择。以下是一个使用 AWS EC2 动态 Inventory 的典型配置流程。
- 下载官方动态脚本: 从 Ansible 官方仓库获取
aws_ec2.yml或ec2.py。 - 配置认证信息: 通过环境变量
AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY或 IAM 角色授权。 - 定义分组规则: 在动态 Inventory 配置文件中按 Tag 或 VPC 进行分组。
- 执行测试: 运行
ansible-inventory -i aws_ec2.yml --list验证返回的 JSON 结构。
# aws_ec2.yml 动态 Inventory 配置示例
plugin: aws_ec2
regions:
- us-east-1
- ap-southeast-1
filters:
tag:Environment:
- dev
- staging
- prod
keyed_groups:
- key: tags.Environment
prefix: env
separator: ""
- key: tags.Role
prefix: role
separator: ""
hostnames:
- tag:Name
- private-dns-name
compose:
ansible_host: private_ip_address
混合 Inventory 策略: 在大型组织中,可以同时使用静态和动态 Inventory。例如,基础架构层(负载均衡器、防火墙)使用静态 Inventory 保证稳定性,而计算节点使用动态 Inventory 适应弹性伸缩。通过
ansible-playbook -i static.ini -i dynamic.yml 同时加载多个 Inventory 源。
4.6 变量覆盖与优先级验证
理解变量优先级是避免配置冲突的关键。以下表格列出了从低到高的变量优先级顺序,实际使用时建议遵循“组变量定义通用值,主机变量定义特例值”的原则。
| 优先级 | 变量来源 | 示例 |
|---|---|---|
| 1(最低) | 角色默认变量(roles/xxx/defaults/main.yml) | nginx_port: 80 |
| 2 | Inventory 组变量(group_vars/all.yml) | ntp_server: pool.ntp.org |
| 3 | Inventory 环境组变量(group_vars/prod.yml) | log_level: warn |
| 4 | Playbook 变量(vars: 关键字) | vars: app_version: 2.1.0 |
| 5 | 主机变量(host_vars/web-prd1.yml) | ansible_host: 10.0.3.10 |
| 6(最高) | 命令行传递变量(-e 参数) | -e "app_version=2.2.0-rc1" |
健康度检查中的变量应用: 在配置环境一致性检查中,建议将期望的配置基线定义在
group_vars/prod.yml 中,然后通过 assert 模块对比实际值与期望值。如果某台主机需要例外,只需在 host_vars 中覆盖该主机的特定变量,无需修改 Playbook 逻辑。