Ansible库存管理Skill ansible-inventory

Ansible 库存管理技能用于管理Ansible自动化中的主机和组,以组织基础设施并跨环境应用配置。它支持INI和YAML格式,定义主机变量、组变量,实现动态库存和目录结构,优化DevOps工作流。关键词:Ansible、库存管理、主机分组、变量定义、动态库存、DevOps、自动化部署、基础设施即代码。

DevOps 0 次安装 0 次浏览 更新于 3/25/2026

名称: ansible-库存管理 用户可调用: false 描述: 在Ansible库存中管理主机和组,用于组织基础设施并跨环境应用配置。 允许工具: [Bash, Read]

Ansible 库存管理

管理Ansible库存中的主机和组,以实现组织化基础设施管理。

INI 格式库存

基本主机定义

# 简单主机列表
mail.example.com
web1.example.com
web2.example.com
db1.example.com

# 带别名的主机
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
db1 ansible_host=192.168.1.20

# 带连接参数的主机
app1 ansible_host=10.0.1.50 ansible_user=deploy ansible_port=2222
app2 ansible_host=10.0.1.51 ansible_user=deploy ansible_port=2222

组定义

[webservers]
web1.example.com
web2.example.com
web3.example.com

[databases]
db1.example.com
db2.example.com

[monitoring]
monitor1.example.com

[production:children]
webservers
databases

[staging:children]
staging-web
staging-db

[staging-web]
staging-web1.example.com
staging-web2.example.com

[staging-db]
staging-db1.example.com

主机变量

[webservers]
web1.example.com http_port=80 max_connections=1000
web2.example.com http_port=8080 max_connections=2000
web3.example.com http_port=80 max_connections=1500

[databases]
db1.example.com db_role=primary
db2.example.com db_role=replica

组变量

[webservers:vars]
nginx_version=1.21.0
app_environment=production
backup_enabled=true

[databases:vars]
postgresql_version=14
max_connections=200
shared_buffers=256MB

[production:vars]
monitoring_enabled=true
log_level=info

YAML 格式库存

基本YAML库存

---
all:
  hosts:
    mail.example.com:

  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 192.168.1.10
          http_port: 80
        web2.example.com:
          ansible_host: 192.168.1.11
          http_port: 8080
      vars:
        nginx_version: "1.21.0"
        app_environment: production

    databases:
      hosts:
        db1.example.com:
          ansible_host: 192.168.1.20
          db_role: primary
        db2.example.com:
          ansible_host: 192.168.1.21
          db_role: replica
      vars:
        postgresql_version: "14"
        max_connections: 200

    production:
      children:
        webservers:
        databases:
      vars:
        monitoring_enabled: true
        backup_enabled: true
        log_level: info

复杂YAML库存

---
all:
  vars:
    ansible_user: ansible
    ansible_become: yes
    ansible_become_method: sudo

  children:
    datacenters:
      children:
        us_east:
          children:
            us_east_web:
              hosts:
                web-us-east-1:
                  ansible_host: 10.10.1.10
                  datacenter: us-east-1
                  rack: A1
                web-us-east-2:
                  ansible_host: 10.10.1.11
                  datacenter: us-east-1
                  rack: A2
              vars:
                region: us-east
                availability_zone: us-east-1a

            us_east_db:
              hosts:
                db-us-east-1:
                  ansible_host: 10.10.1.20
                  db_role: primary
                  datacenter: us-east-1
                db-us-east-2:
                  ansible_host: 10.10.1.21
                  db_role: replica
                  datacenter: us-east-1
              vars:
                region: us-east

        us_west:
          children:
            us_west_web:
              hosts:
                web-us-west-1:
                  ansible_host: 10.20.1.10
                  datacenter: us-west-1
                  rack: B1
                web-us-west-2:
                  ansible_host: 10.20.1.11
                  datacenter: us-west-1
                  rack: B2
              vars:
                region: us-west
                availability_zone: us-west-1a

            us_west_db:
              hosts:
                db-us-west-1:
                  ansible_host: 10.20.1.20
                  db_role: primary
                  datacenter: us-west-1
              vars:
                region: us-west

主机模式和范围

数字范围

[webservers]
web[1:10].example.com

[databases]
db[01:05].example.com

[application]
app-[a:f].example.com
---
all:
  children:
    webservers:
      hosts:
        web[1:10].example.com:
    databases:
      hosts:
        db[01:05].example.com:
    application:
      hosts:
        app-[a:f].example.com:

多组

[webservers]
web[1:5].example.com

[loadbalancers]
lb[1:2].example.com

[frontend:children]
webservers
loadbalancers

[frontend:vars]
http_port=80
https_port=443

动态库存

基本动态库存脚本

#!/usr/bin/env python3
"""
Ansible的动态库存脚本
"""
import json
import sys
import argparse

def get_inventory():
    """返回库存数据结构"""
    inventory = {
        'webservers': {
            'hosts': ['web1.example.com', 'web2.example.com'],
            'vars': {
                'nginx_version': '1.21.0',
                'http_port': 80
            }
        },
        'databases': {
            'hosts': ['db1.example.com', 'db2.example.com'],
            'vars': {
                'postgresql_version': '14',
                'db_port': 5432
            }
        },
        'production': {
            'children': ['webservers', 'databases'],
            'vars': {
                'environment': 'production',
                'monitoring_enabled': True
            }
        },
        '_meta': {
            'hostvars': {
                'web1.example.com': {
                    'ansible_host': '192.168.1.10',
                    'http_port': 80
                },
                'web2.example.com': {
                    'ansible_host': '192.168.1.11',
                    'http_port': 8080
                },
                'db1.example.com': {
                    'ansible_host': '192.168.1.20',
                    'db_role': 'primary'
                },
                'db2.example.com': {
                    'ansible_host': '192.168.1.21',
                    'db_role': 'replica'
                }
            }
        }
    }
    return inventory

def get_host_vars(host):
    """返回特定主机的变量"""
    inventory = get_inventory()
    return inventory['_meta']['hostvars'].get(host, {})

def main():
    """主要执行"""
    parser = argparse.ArgumentParser(description='动态Ansible库存')
    parser.add_argument('--list', action='store_true', help='列出所有组')
    parser.add_argument('--host', help='获取特定主机的变量')
    args = parser.parse_args()

    if args.list:
        print(json.dumps(get_inventory(), indent=2))
    elif args.host:
        print(json.dumps(get_host_vars(args.host), indent=2))
    else:
        parser.print_help()
        sys.exit(1)

if __name__ == '__main__':
    main()

AWS EC2 动态库存

#!/usr/bin/env python3
"""
AWS EC2 动态库存 for Ansible
"""
import json
import boto3
from collections import defaultdict

def get_ec2_inventory():
    """获取EC2实例并构建库存"""
    ec2 = boto3.client('ec2')

    inventory = defaultdict(lambda: {'hosts': [], 'vars': {}})
    hostvars = {}

    # 获取所有运行中的实例
    response = ec2.describe_instances(
        Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]
    )

    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            instance_id = instance['InstanceId']
            private_ip = instance.get('PrivateIpAddress', '')
            public_ip = instance.get('PublicIpAddress', '')

            # 从标签获取实例名称
            name = instance_id
            for tag in instance.get('Tags', []):
                if tag['Key'] == 'Name':
                    name = tag['Value']
                    break

            # 构建主机变量
            hostvars[name] = {
                'ansible_host': public_ip or private_ip,
                'private_ip': private_ip,
                'public_ip': public_ip,
                'instance_id': instance_id,
                'instance_type': instance['InstanceType'],
                'availability_zone': instance['Placement']['AvailabilityZone']
            }

            # 按标签分组
            for tag in instance.get('Tags', []):
                key = tag['Key']
                value = tag['Value']

                if key == 'Environment':
                    group = f"env_{value}"
                    inventory[group]['hosts'].append(name)

                if key == 'Role':
                    group = f"role_{value}"
                    inventory[group]['hosts'].append(name)

                if key == 'Application':
                    group = f"app_{value}"
                    inventory[group]['hosts'].append(name)

            # 按实例类型分组
            type_group = f"type_{instance['InstanceType']}"
            inventory[type_group]['hosts'].append(name)

            # 按可用区分组
            az_group = f"az_{instance['Placement']['AvailabilityZone']}"
            inventory[az_group]['hosts'].append(name)

    # 添加元主机变量
    inventory['_meta'] = {'hostvars': hostvars}

    return dict(inventory)

if __name__ == '__main__':
    import sys
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('--list', action='store_true')
    parser.add_argument('--host')
    args = parser.parse_args()

    if args.list:
        print(json.dumps(get_ec2_inventory(), indent=2))
    elif args.host:
        inventory = get_ec2_inventory()
        print(json.dumps(inventory['_meta']['hostvars'].get(args.host, {}), indent=2))

库存插件配置

# inventory.aws_ec2.yml
---
plugin: amazon.aws.aws_ec2

regions:
  - us-east-1
  - us-west-2

filters:
  instance-state-name: running
  tag:Environment: production

keyed_groups:
  # 按实例类型分组
  - key: instance_type
    prefix: type
    separator: "_"

  # 按可用区分组
  - key: placement.availability_zone
    prefix: az

  # 按标签分组
  - key: tags.Role
    prefix: role

  - key: tags.Environment
    prefix: env

compose:
  ansible_host: public_ip_address | default(private_ip_address)
  datacenter: placement.availability_zone

hostnames:
  - tag:Name
  - instance-id

库存目录结构

组织化库存布局

inventory/
├── production/
│   ├── hosts.yml
│   ├── group_vars/
│   │   ├── all.yml
│   │   ├── webservers.yml
│   │   ├── databases.yml
│   │   └── loadbalancers.yml
│   └── host_vars/
│       ├── web1.example.com.yml
│       ├── web2.example.com.yml
│       └── db1.example.com.yml
├── staging/
│   ├── hosts.yml
│   ├── group_vars/
│   │   ├── all.yml
│   │   ├── webservers.yml
│   │   └── databases.yml
│   └── host_vars/
│       └── staging-web1.example.com.yml
└── development/
    ├── hosts.yml
    └── group_vars/
        └── all.yml

group_vars/all.yml

---
# 所有主机的变量
ansible_user: ansible
ansible_become: yes
ansible_become_method: sudo
ansible_python_interpreter: /usr/bin/python3

# 通用包
common_packages:
  - vim
  - htop
  - curl
  - wget
  - git

# NTP配置
ntp_servers:
  - 0.pool.ntp.org
  - 1.pool.ntp.org
  - 2.pool.ntp.org

# 监控
monitoring_enabled: yes
monitoring_endpoint: https://monitoring.example.com

# 日志记录
syslog_server: syslog.example.com
log_retention_days: 30

# 安全
security_ssh_port: 22
security_enable_firewall: yes
security_allowed_ssh_networks:
  - 10.0.0.0/8
  - 172.16.0.0/12

group_vars/webservers.yml

---
# Web服务器特定变量
nginx_version: "1.21.0"
nginx_worker_processes: auto
nginx_worker_connections: 1024

# SSL配置
ssl_enabled: yes
ssl_certificate_path: /etc/ssl/certs
ssl_key_path: /etc/ssl/private

# 应用设置
app_name: myapp
app_port: 3000
app_user: www-data
app_log_dir: /var/log/{{ app_name }}

# 性能调优
keepalive_timeout: 65
client_max_body_size: 10m
gzip_enabled: yes

# 负载均衡器配置
load_balancer_backend_timeout: 60
load_balancer_health_check: /health

# 备份设置
backup_enabled: yes
backup_schedule: "0 2 * * *"
backup_retention: 7

group_vars/databases.yml

---
# 数据库特定变量
postgresql_version: "14"
postgresql_port: 5432
postgresql_max_connections: 200
postgresql_shared_buffers: 256MB

# 数据目录
postgresql_data_dir: /var/lib/postgresql/{{ postgresql_version }}/main

# 备份配置
db_backup_enabled: yes
db_backup_schedule: "0 3 * * *"
db_backup_retention: 14
db_backup_dir: /backup/postgresql

# 复制
replication_enabled: yes
replication_user: replicator

# 性能调优
postgresql_effective_cache_size: 1GB
postgresql_work_mem: 4MB
postgresql_maintenance_work_mem: 64MB

# 监控
db_monitoring_enabled: yes
slow_query_log_enabled: yes
slow_query_threshold: 1000

host_vars/web1.example.com.yml

---
# web1的特定主机变量
ansible_host: 192.168.1.10

# 硬件规格
cpu_cores: 4
memory_gb: 8
disk_size_gb: 100

# 网络配置
primary_ip: 192.168.1.10
secondary_ip: 192.168.1.110
network_interface: eth0

# 角色特定覆盖
nginx_worker_processes: 4
app_instances: 2

# 监控
monitoring_tags:
  - production
  - web
  - critical

# 维护窗口
maintenance_window: "Sunday 02:00-04:00"

库存变量

变量优先级

# 从低到高优先级:
# 1. 角色默认值 (defaults/main.yml)
# 2. 库存文件或脚本组变量
# 3. 库存 group_vars/all
# 4. 剧本 group_vars/all
# 5. 库存 group_vars/*
# 6. 剧本 group_vars/*
# 7. 库存文件或脚本主机变量
# 8. 库存 host_vars/*
# 9. 剧本 host_vars/*
# 10. 主机事实 / 缓存的 set_facts
# 11. 剧本变量
# 12. 剧本 vars_prompt
# 13. 剧本 vars_files
# 14. 角色变量 (vars/main.yml)
# 15. 块变量 (仅适用于块中的任务)
# 16. 任务变量 (仅适用于任务)
# 17. include_vars
# 18. set_facts / 注册变量
# 19. 角色 (和 include_role) 参数
# 20. include 参数
# 21. 额外变量 (-e 在命令行中)

使用库存变量

---
- name: 部署应用
  hosts: webservers

  tasks:
    - name: 显示库存变量
      debug:
        msg: |
          主机: {{ inventory_hostname }}
          IP: {{ ansible_host }}
          环境: {{ app_environment }}
          端口: {{ http_port }}
          组: {{ group_names }}

    - name: 部署到正确环境
      template:
        src: app.conf.j2
        dest: /etc/app/config.yml
      vars:
        config_environment: "{{ app_environment }}"
        config_port: "{{ app_port }}"

连接变量

SSH 连接设置

[webservers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/web_key
web2 ansible_host=192.168.1.11 ansible_user=centos ansible_port=2222

[webservers:vars]
ansible_connection=ssh
ansible_become=yes
ansible_become_method=sudo
ansible_become_user=root
---
all:
  vars:
    ansible_connection: ssh
    ansible_user: ansible
    ansible_ssh_private_key_file: ~/.ssh/ansible_key
    ansible_become: yes
    ansible_become_method: sudo

  children:
    webservers:
      hosts:
        web1:
          ansible_host: 192.168.1.10
          ansible_port: 22
        web2:
          ansible_host: 192.168.1.11
          ansible_port: 2222

替代连接方法

---
all:
  children:
    windows_hosts:
      hosts:
        win1:
          ansible_host: 192.168.1.50
      vars:
        ansible_connection: winrm
        ansible_user: Administrator
        ansible_password: "{{ windows_password }}"
        ansible_winrm_transport: ntlm
        ansible_winrm_server_cert_validation: ignore

    containers:
      hosts:
        container1:
          ansible_connection: docker
          ansible_host: container_name

    local_tasks:
      hosts:
        localhost:
          ansible_connection: local
          ansible_python_interpreter: /usr/bin/python3

库存测试和验证

列出库存

# 列出所有主机
ansible-inventory -i inventory/production/hosts.yml --list

# 以YAML格式列出
ansible-inventory -i inventory/production/hosts.yml --list -y

# 显示库存图
ansible-inventory -i inventory/production/hosts.yml --graph

# 显示特定主机
ansible-inventory -i inventory/production/hosts.yml --host web1.example.com

验证主机组

# 列出组中的主机
ansible webservers -i inventory/production/hosts.yml --list-hosts

# 列出所有组
ansible all -i inventory/production/hosts.yml --list-hosts

# 测试连接性
ansible all -i inventory/production/hosts.yml -m ping

# 收集事实
ansible webservers -i inventory/production/hosts.yml -m setup

命令中的库存模式

# 单个主机
ansible web1.example.com -i inventory/production -m ping

# 多个主机
ansible web1.example.com,web2.example.com -i inventory/production -m ping

# 组中的所有主机
ansible webservers -i inventory/production -m ping

# 多组中的所有主机
ansible webservers:databases -i inventory/production -m ping

# 在组A但不在组B中的主机
ansible webservers:!staging -i inventory/production -m ping

# 在两个组中的主机
ansible webservers:&production -i inventory/production -m ping

# 通配符模式
ansible web*.example.com -i inventory/production -m ping

# 正则表达式模式
ansible ~web[0-9]+\.example\.com -i inventory/production -m ping

何时使用此技能

使用 ansible-inventory 技能当您需要时:

  • 将基础设施主机组织成逻辑组以进行自动化
  • 定义远程系统的连接参数和凭据
  • 构建多环境部署(开发、暂存、生产)
  • 实现基础设施即代码,使用版本控制的库存
  • 从云提供商或外部系统创建动态库存
  • 跨服务器组应用基于角色的配置
  • 在不同范围级别管理变量(全局、组、主机)
  • 实现具有父子关系的分层主机分组
  • 支持多个数据中心或区域部署
  • 创建可重用的库存模式以进行一致部署
  • 与外部CMDBs或资产管理系统集成
  • 在应用更改之前测试和验证基础设施组织
  • 记录基础设施拓扑和关系
  • 实施针对特定主机子集的定向部署
  • 支持使用库存模式和过滤器的复杂目标定位

最佳实践

  1. 使用版本控制 - 将库存文件保存在Git中以进行跟踪和协作
  2. 按环境组织 - 分离生产、暂存和开发库存
  3. 使用YAML格式 - 优先使用YAML而非INI以获得更好的结构和可读性
  4. 适当分组变量 - 使用 group_vars 共享设置,host_vars 进行特定覆盖
  5. 实施清晰的命名 - 为主机和组使用一致、描述性的名称
  6. 使用库存插件 - 为云环境利用动态库存
  7. 保护敏感数据 - 对密码和凭据使用 ansible-vault
  8. 记录库存结构 - 包括解释组织的README文件
  9. 测试库存更改 - 在应用更改之前使用 --list 和 --check
  10. 保持DRY - 使用变量继承避免重复
  11. 使用有意义的组 - 创建功能组(如webservers)和环境组(如production)
  12. 实施主机模式 - 为一致的命名方案使用范围
  13. 分离连接与配置 - 将 ansible_* 连接变量与应用程序配置分开
  14. 使用库存目录 - 将复杂库存结构为目录,而非单个文件
  15. 缓存动态库存 - 为云库存实现缓存以加快执行速度

常见陷阱

  1. 混合环境 - 将生产和开发主机放在同一库存中
  2. 硬编码凭据 - 以纯文本存储密码,而非使用保险库
  3. 不一致的命名 - 跨环境使用不同的命名方案
  4. 过于复杂的结构 - 创建太多嵌套组
  5. 缺少连接变量 - 需要时未定义 ansible_host 或 ansible_user
  6. 重复的主机定义 - 同一主机出现在多个库存文件中
  7. 无变量文档 - 未解释变量含义或其预期值
  8. 忽略变量优先级 - 不理解Ansible如何解决冲突
  9. 对云使用静态库存 - 未对AWS、Azure等使用动态库存
  10. 无库存验证 - 使用前未测试库存
  11. 糟糕的组组织 - 创建没有明确目的的组
  12. 缺少备份库存 - 未维护先前工作库存版本
  13. 假设组成员资格 - 未验证主机属于哪些组
  14. 过于宽泛的模式 - 使用匹配意外主机的通配符
  15. 无库存测试工作流 - 直接将库存更改应用到生产

资源