第四章:主机清单管理

深入了解 Ansible Inventory 主机清单的配置和使用。

最后更新: 2024-01-18
页面目录

Ansible 主机清单管理

主机清单(Inventory)是 Ansible 管理的基础,定义了要管理的主机及其分组信息。

Inventory 概述

┌─────────────────────────────────────────────────────────────────┐
│                      Inventory 结构                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Inventory                                                        │
│  ├── Static Inventory (静态清单)                                 │
│  │   ├── INI 格式                                                │
│  │   └── YAML 格式                                                │
│  └── Dynamic Inventory (动态清单)                                │
│      ├── AWS EC2                                                 │
│      ├── VMware                                                  │
│      ├── OpenStack                                               │
│      └── Custom Scripts                                          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

静态 Inventory (INI 格式)

基本结构

# inventory/hosts

# 单个主机
web1 ansible_host=192.168.1.10

# 带端口
web2 ansible_host=192.168.1.11 ansible_port=2222

# 带 SSH 用户和密钥
web3 ansible_host=192.168.1.12 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa

# 主机组
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
web3 ansible_host=192.168.1.12

# 数据库组
[dbservers]
db1 ansible_host=192.168.2.10
db2 ansible_host=192.168.2.11

# 应用组
[appservers]
app1 ansible_host=192.168.3.10
app2 ansible_host=192.168.3.11

# 负载均衡器
[lb]
lb1 ansible_host=192.168.0.10
lb2 ansible_host=192.168.0.11

主机变量

# 为单个主机定义变量
[webservers]
web1 ansible_host=192.168.1.10 nginx_port=80
web2 ansible_host=192.168.1.11 nginx_port=8080

组变量

# 方式一:直接在组内定义变量
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11

[webservers:vars]
http_port=80
max_connections=1000
ansible_user=deploy

# 方式二:所有主机通用变量
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_connection=ssh

嵌套组(Children)

# 生产环境
[production:children]
webservers
dbservers
appservers
lb

[production:vars]
environment=production
ntp_server=ntp.production.local

# 测试环境
[staging:children]
web_staging
db_staging

[staging:vars]
environment=staging
ntp_server=ntp.staging.local

静态 Inventory (YAML 格式)

基本结构

# inventory/hosts.yml
all:
  hosts:
    web1:
      ansible_host: 192.168.1.10
    web2:
      ansible_host: 192.168.1.11
    db1:
      ansible_host: 192.168.2.10

带主机变量

# inventory/hosts.yml
all:
  vars:
    ansible_user: deploy
    ansible_python_interpreter: /usr/bin/python3
  
  children:
    webservers:
      hosts:
        web1:
          ansible_host: 192.168.1.10
          nginx_port: 80
        web2:
          ansible_host: 192.168.1.11
          nginx_port: 8080
      vars:
        http_port: 80
    
    dbservers:
      hosts:
        db1:
          ansible_host: 192.168.2.10
        db2:
          ansible_host: 192.168.2.11
      vars:
        db_port: 3306

嵌套组

# inventory/hosts.yml
all:
  children:
    production:
      children:
        webservers:
          hosts:
            web1:
            web2:
        dbservers:
          hosts:
            db1:
            db2:
      vars:
        environment: production
    
    staging:
      children:
        web_staging:
          hosts:
            web-staging1:
        db_staging:
          hosts:
            db-staging1:
      vars:
        environment: staging

主机范围(Patterns)

数字范围

# 连续主机
[webservers]
web[1:5].example.com
# 等价于:
# web1.example.com, web2.example.com, web3.example.com, web4.example.com, web5.example.com

字母范围

# 字母主机
[dbservers]
db-[a:d].example.com
# 等价于:
# db-a.example.com, db-b.example.com, db-c.example.com, db-d.example.com

组合使用

# 复杂模式
[webservers]
web[01:10]-v[1:3].example.com

动态 Inventory

动态 Inventory 可以从外部数据源(如云平台、CMDB)获取主机列表。

AWS EC2 动态清单

安装 EC2 插件

# 安装 boto3
pip install boto3 botocore

配置文件

# ec2.ini
[ec2]
regions = us-east-1,us-west-2
vpc_destination_variable = ip_address
destination_format = {0}:{1}
destination_format_tags = name

[credentials]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY

使用动态清单

# 使用 EC2 动态清单
ansible-playbook -i ec2.py site.yml

# 或者使用插件
ansible-playbook -i aws_ec2.yml site.yml

YAML 配置(推荐)

# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
  - us-west-2
filters:
  tag:Environment: production
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: tags.Role
    prefix: role
  - key: instance_type
    prefix: type

VMware 动态清单

# vmware.yml
plugin: community.vmware.vmware_vm_inventory
strict: False
hostname: vcenter.example.com
username: admin@vsphere.local
password: Secret123
validate_certs: False
properties:
  - name
  - guest.ipAddress
  - config.name
  - config.annotation
  - summary.runtime.powerState
hostnames:
  - config.name
filters:
  - summary.runtime.powerState == "poweredOn"
groups:
  poweredon: True

自定义动态清单脚本

脚本模板

#!/usr/bin/env python3
# inventory/custom.py

import json
import sys
import os

def get_inventory():
    inventory = {
        '_meta': {
            'hostvars': {}
        },
        'all': {
            'hosts': []
        },
        'webservers': {
            'hosts': []
        },
        'dbservers': {
            'hosts': []
        }
    }
    
    # 从外部数据源获取主机
    # 例如从 API、数据库等
    hosts = [
        {'name': 'web1', 'ip': '192.168.1.10', 'group': 'webservers'},
        {'name': 'web2', 'ip': '192.168.1.11', 'group': 'webservers'},
        {'name': 'db1', 'ip': '192.168.2.10', 'group': 'dbservers'},
    ]
    
    for host in hosts:
        inventory['all']['hosts'].append(host['name'])
        inventory[host['group']]['hosts'].append(host['name'])
        inventory['_meta']['hostvars'][host['name']] = {
            'ansible_host': host['ip']
        }
    
    return inventory

if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == '--list':
        print(json.dumps(get_inventory()))
    elif len(sys.argv) > 1 and sys.argv[1] == '--host':
        print(json.dumps({}))
    else:
        print(json.dumps({}))

使用自定义脚本

# 添加执行权限
chmod +x inventory/custom.py

# 测试清单
./inventory/custom.py --list

# 使用
ansible-playbook -i inventory/custom.py site.yml

目录式 Inventory

将 Inventory 相关文件分散到目录中,便于管理大量主机。

目录结构

inventory/
├── hosts.ini              # 主清单文件
├── group_vars/            # 组变量目录
   ├── all.yml            # 所有主机的通用变量
   ├── webservers.yml      # webservers 组变量
   └── dbservers.yml       # dbservers 组变量
└── host_vars/             # 主机变量目录
    ├── web1.yml            # web1 主机变量
    └── web2.yml            # web2 主机变量

hosts.ini

# inventory/hosts.ini
[webservers]
web1
web2

[dbservers]
db1
db2

[production:children]
webservers
dbservers

组变量文件

# inventory/group_vars/all.yml
---
ansible_user: deploy
ansible_python_interpreter: /usr/bin/python3
ntp_server: pool.ntp.org

# inventory/group_vars/webservers.yml
---
nginx_version: "1.24.0"
app_port: 8080
max_connections: 1000

# inventory/group_vars/dbservers.yml
---
db_port: 3306
db_version: "8.0"
db_name: myapp_production

主机变量文件

# inventory/host_vars/web1.yml
---
nginx_port: 80
server_name: web1.example.com

# inventory/host_vars/web2.yml
---
nginx_port: 8080
server_name: web2.example.com

Inventory 命令

查看 Inventory

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

# 列出所有主机(树形结构)
ansible-inventory -i inventory/hosts --tree

# 列出主机的详细信息
ansible-inventory -i inventory/hosts --host web1

# 列出所有组
ansible-inventory -i inventory/hosts --graph

验证 Inventory

# 验证 Inventory 格式
ansible-inventory -i inventory/hosts --validate

# 测试主机连接
ansible all -i inventory/hosts -m ping

Inventory 变量速查

连接变量

变量 说明 示例
ansible_host SSH 主机名/IP 192.168.1.10
ansible_port SSH 端口 22
ansible_user SSH 用户名 root
ansible_password SSH 密码 secret
ansible_ssh_private_key_file SSH 私钥路径 ~/.ssh/id_rsa
ansible_ssh_common_args SSH 额外参数 -o StrictHostKeyChecking=no

SSH 连接变量(高级)

变量 说明 示例
ansible_ssh_pipelining 启用管道 True
ansible_ssh_executable SSH 可执行文件路径 /usr/bin/ssh

远程执行变量

变量 说明 示例
ansible_python_interpreter Python 解释器路径 /usr/bin/python3
ansible_become 是否启用提权 True
ansible_become_method 提权方法 sudo
ansible_become_user 提权用户 root
ansible_become_password 提权密码 secret

Windows 连接变量

变量 说明 示例
ansible_connection 连接类型 winrm
ansible_port WinRM 端口 5986
ansible_winrm_transport 认证方式 ntlm
ansible_winrm_server_cert_validation 证书验证 ignore

最佳实践

1. 使用目录结构管理 Inventory

inventory/
├── hosts.ini
├── group_vars/
   └── all.yml
└── host_vars/

2. 分离不同环境

inventory/
├── development/
├── staging/
└── production/

3. 使用 Vault 加密敏感变量

# 加密敏感文件
ansible-vault encrypt inventory/group_vars/all/vault.yml

# 编辑加密文件
ansible-vault edit inventory/group_vars/all/vault.yml

4. 使用动态 Inventory

# 使用云平台动态清单
ansible-playbook -i ec2.py site.yml

下一步

现在你已经掌握了 Inventory 管理。接下来让我们学习 Playbook 的基础知识。

👉 Playbook 基础