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 设计的核心实践,通过将主机按生命周期阶段分组,实现配置隔离、权限控制和发布流程的差异化。

环境分组 Inventory 架构图 Inventory 根目录 [dev] 开发环境 [staging] 预发布环境 [prod] 生产环境 [dev-web] [dev-db] [staging-web] [staging-db] [prod-web] [prod-db] web01 db01 web-stg1 db-stg1 web-prd1 db-prd1 变量继承路径 group_vars/all.yml → group_vars/dev.yml → host_vars/web01.dev.yml

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 的典型配置流程。

  1. 下载官方动态脚本: 从 Ansible 官方仓库获取 aws_ec2.yml 或 ec2.py。
  2. 配置认证信息: 通过环境变量 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 或 IAM 角色授权。
  3. 定义分组规则: 在动态 Inventory 配置文件中按 Tag 或 VPC 进行分组。
  4. 执行测试: 运行 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 逻辑。