Ansible 变量管理 #
变量概述 #
Ansible 变量用于存储和管理配置数据,可以在不同位置定义,具有不同的优先级和作用域。
text
┌─────────────────────────────────────────────────────────────┐
│ 变量来源 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 命令行 清单文件 Playbook │
│ ────────── ────────── ────────── │
│ -e var=value host_vars vars: │
│ group_vars vars_files: │
│ │
│ Facts 注册变量 魔法变量 │
│ ────────── ────────── ────────── │
│ ansible_facts register inventory_hostname │
│ result hostvars │
│ groups │
│ │
└─────────────────────────────────────────────────────────────┘
变量定义位置 #
1. 命令行变量 #
bash
# 单个变量
ansible-playbook site.yml -e "app_name=myapp"
# 多个变量
ansible-playbook site.yml -e "app_name=myapp app_port=8080"
# 变量文件
ansible-playbook site.yml -e @vars.yml
# JSON 格式
ansible-playbook site.yml -e '{"app_name": "myapp", "app_port": 8080}'
2. Inventory 变量 #
ini
# inventory/hosts
# 主机变量
web1 ansible_host=192.168.1.100 app_port=8080
# 组变量
[webservers:vars]
nginx_port=80
document_root=/var/www/html
# 全局变量
[all:vars]
ansible_python_interpreter=/usr/bin/python3
3. group_vars 和 host_vars #
text
inventory/
├── hosts
├── group_vars/
│ ├── all.yml # 所有主机的变量
│ ├── webservers.yml # webservers 组的变量
│ └── databases.yml # databases 组的变量
└── host_vars/
├── web1.yml # web1 主机的变量
└── db1.yml # db1 主机的变量
yaml
# inventory/group_vars/all.yml
---
ntp_servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
timezone: UTC
# inventory/group_vars/webservers.yml
---
nginx_port: 80
nginx_worker_processes: auto
document_root: /var/www/html
# inventory/host_vars/web1.yml
---
ansible_host: 192.168.1.100
nginx_server_name: web1.example.com
ssl_enabled: true
4. Playbook 变量 #
yaml
---
- name: Use playbook variables
hosts: webservers
vars:
app_name: myapp
app_port: 8080
vars_files:
- vars/app.yml
- vars/secrets.yml
vars_prompt:
- name: db_password
prompt: "Enter database password"
private: yes
tasks:
- name: Use variables
debug:
msg: "App {{ app_name }} on port {{ app_port }}"
5. Role 变量 #
text
roles/
└── nginx/
├── defaults/
│ └── main.yml # 默认变量(最低优先级)
└── vars/
└── main.yml # 角色变量(较高优先级)
yaml
# roles/nginx/defaults/main.yml
nginx_port: 80
nginx_user: www-data
nginx_worker_processes: auto
# roles/nginx/vars/main.yml
nginx_config_dir: /etc/nginx
nginx_log_dir: /var/log/nginx
变量优先级 #
优先级顺序(从低到高) #
text
1. role defaults (roles/x/defaults/main.yml)
2. inventory 文件或脚本 (inventory/hosts)
3. inventory group_vars/all (inventory/group_vars/all.yml)
4. inventory group_vars/* (inventory/group_vars/webservers.yml)
5. inventory host_vars/* (inventory/host_vars/web1.yml)
6. inventory host_vars/* (inventory/host_vars/web1.yml)
7. host facts
8. play vars
9. play vars_prompt
10. play vars_files
11. role vars (roles/x/vars/main.yml)
12. block vars
13. task vars
14. include_vars
15. role (and include_role) params
16. set_facts
17. registered vars
18. extra vars (命令行 -e)
优先级示例 #
yaml
# roles/nginx/defaults/main.yml
nginx_port: 80
# inventory/group_vars/webservers.yml
nginx_port: 8080
# site.yml
- hosts: webservers
vars:
nginx_port: 9000
tasks:
- debug:
msg: "{{ nginx_port }}" # 输出 9000
# 使用命令行
ansible-playbook site.yml -e "nginx_port=10080"
# 最终 nginx_port = 10080(最高优先级)
变量类型 #
基本类型 #
yaml
vars:
# 字符串
app_name: myapp
app_path: /var/www/app
# 数字
app_port: 8080
max_connections: 100
# 布尔值
ssl_enabled: true
debug_mode: false
# 列表
packages:
- nginx
- git
- curl
# 字典
database:
host: localhost
port: 3306
name: myapp
user: appuser
使用变量 #
yaml
tasks:
# 字符串
- name: Use string variable
debug:
msg: "App name is {{ app_name }}"
# 数字
- name: Use number variable
debug:
msg: "Port is {{ app_port }}"
# 布尔值
- name: Use boolean variable
debug:
msg: "SSL is {{ 'enabled' if ssl_enabled else 'disabled' }}"
# 列表
- name: Use list variable
debug:
msg: "Package: {{ item }}"
loop: "{{ packages }}"
# 字典
- name: Use dictionary variable
debug:
msg: "Database: {{ database.host }}:{{ database.port }}"
# 字典键访问
- name: Access dictionary key
debug:
msg: "Database name: {{ database['name'] }}"
Facts #
什么是 Facts? #
Facts 是 Ansible 自动收集的被管理节点信息。
yaml
tasks:
- name: Show all facts
debug:
var: ansible_facts
常用 Facts #
yaml
# 系统 Facts
ansible_facts['hostname'] # 主机名
ansible_facts['fqdn'] # 完全限定域名
ansible_facts['os_family'] # 系统家族 (Debian, RedHat)
ansible_facts['distribution'] # 发行版 (Ubuntu, CentOS)
ansible_facts['distribution_version'] # 版本号
ansible_facts['distribution_major_version'] # 主版本号
ansible_facts['kernel'] # 内核版本
# 网络 Facts
ansible_facts['default_ipv4']['address'] # IPv4 地址
ansible_facts['default_ipv4']['gateway'] # 网关
ansible_facts['default_ipv4']['interface'] # 网络接口
ansible_facts['interfaces'] # 所有网络接口列表
# 硬件 Facts
ansible_facts['memtotal_mb'] # 总内存 (MB)
ansible_facts['processor_cores'] # CPU 核心数
ansible_facts['processor_count'] # CPU 数量
ansible_facts['processor_vcpus'] # 虚拟 CPU 数
ansible_facts['mounts'] # 挂载点信息
# 时间 Facts
ansible_facts['date_time']['date'] # 日期
ansible_facts['date_time']['time'] # 时间
ansible_facts['date_time']['iso8601'] # ISO 格式时间
使用 Facts #
yaml
tasks:
- name: Install based on OS
apt:
name: nginx
state: present
when: ansible_facts['os_family'] == "Debian"
- name: Install based on memory
debug:
msg: "This server has plenty of RAM"
when: ansible_facts['memtotal_mb'] > 8192
- name: Configure based on CPU cores
lineinfile:
path: /etc/nginx/nginx.conf
line: "worker_processes {{ ansible_facts['processor_vcpus'] }};"
自定义 Facts #
yaml
# 在被管理节点创建自定义 Facts
# /etc/ansible/facts.d/custom.fact
[general]
role = web
environment = production
# 使用自定义 Facts
tasks:
- name: Use custom fact
debug:
msg: "Server role is {{ ansible_facts['ansible_local']['custom']['general']['role'] }}"
收集特定 Facts #
yaml
- hosts: all
gather_facts: no # 禁用自动收集
tasks:
- name: Gather only network facts
setup:
gather_subset:
- network
register: network_facts
- name: Gather only hardware facts
setup:
gather_subset:
- hardware
- name: Gather minimal facts
setup:
gather_subset:
- min
注册变量 #
基本使用 #
yaml
tasks:
- name: Run command
command: uptime
register: uptime_result
- name: Show result
debug:
msg: "Uptime: {{ uptime_result.stdout }}"
- name: Show all result data
debug:
var: uptime_result
注册变量结构 #
yaml
tasks:
- name: Run command
command: ls -la /tmp
register: result
# result 包含:
# result.stdout - 标准输出
# result.stderr - 标准错误
# result.rc - 返回码
# result.changed - 是否变更
# result.failed - 是否失败
# result.cmd - 执行的命令
# result.start - 开始时间
# result.end - 结束时间
# result.delta - 耗时
使用注册变量 #
yaml
tasks:
- name: Check if file exists
stat:
path: /etc/nginx/nginx.conf
register: file_stat
- name: Backup file if exists
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/nginx.conf.bak
when: file_stat.stat.exists
- name: Check service status
command: systemctl is-active nginx
register: service_status
changed_when: false
failed_when: false
- name: Start service if not running
service:
name: nginx
state: started
when: service_status.rc != 0
循环中的注册变量 #
yaml
tasks:
- name: Loop with register
command: "echo {{ item }}"
loop:
- one
- two
- three
register: loop_result
- name: Show loop results
debug:
msg: "{{ item.stdout }}"
loop: "{{ loop_result.results }}"
魔法变量 #
inventory_hostname #
yaml
tasks:
- name: Show inventory hostname
debug:
msg: "Inventory hostname: {{ inventory_hostname }}"
- name: Show inventory hostname short
debug:
msg: "Short name: {{ inventory_hostname_short }}"
hostvars #
访问其他主机的变量:
yaml
tasks:
- name: Access another host's variables
debug:
msg: "web1 IP: {{ hostvars['web1']['ansible_facts']['default_ipv4']['address'] }}"
- name: Access all hosts
debug:
msg: "Host: {{ item }}"
loop: "{{ groups['all'] }}"
- name: Get first web server IP
debug:
msg: "First web server: {{ hostvars[groups['webservers'][0]]['ansible_facts']['default_ipv4']['address'] }}"
groups #
yaml
tasks:
- name: Show all groups
debug:
var: groups
- name: Show webservers group
debug:
msg: "Webservers: {{ groups['webservers'] }}"
- name: Loop through group
debug:
msg: "Host: {{ item }}"
loop: "{{ groups['webservers'] }}"
group_names #
yaml
tasks:
- name: Show groups this host belongs to
debug:
msg: "{{ inventory_hostname }} is in groups: {{ group_names }}"
- name: Check if in production group
debug:
msg: "This is a production server"
when: "'production' in group_names"
play_hosts / ansible_play_hosts #
yaml
tasks:
- name: Show hosts in current play
debug:
msg: "Play hosts: {{ ansible_play_hosts }}"
- name: Show hosts that succeeded
debug:
msg: "Successful hosts: {{ ansible_play_hosts_all_success }}"
其他魔法变量 #
yaml
tasks:
# Playbook 目录
- name: Show playbook directory
debug:
msg: "Playbook dir: {{ playbook_dir }}"
# Inventory 目录
- name: Show inventory directory
debug:
msg: "Inventory dir: {{ inventory_dir }}"
# Ansible 版本
- name: Show Ansible version
debug:
msg: "Ansible version: {{ ansible_version }}"
# 角色名称
- name: Show role name
debug:
msg: "Role: {{ role_name }}"
when: role_name is defined
变量过滤器 #
字符串过滤器 #
yaml
vars:
my_string: "Hello World"
tasks:
- debug:
msg: "{{ my_string | upper }}" # HELLO WORLD
- debug:
msg: "{{ my_string | lower }}" # hello world
- debug:
msg: "{{ my_string | capitalize }}" # Hello world
- debug:
msg: "{{ my_string | replace('World', 'Ansible') }}" # Hello Ansible
- debug:
msg: "{{ my_string | split(' ') }}" # ['Hello', 'World']
- debug:
msg: "{{ my_string | truncate(5) }}" # He...
列表过滤器 #
yaml
vars:
my_list:
- 1
- 2
- 3
- 4
- 5
tasks:
- debug:
msg: "{{ my_list | min }}" # 1
- debug:
msg: "{{ my_list | max }}" # 5
- debug:
msg: "{{ my_list | sum }}" # 15
- debug:
msg: "{{ my_list | join(',') }}" # 1,2,3,4,5
- debug:
msg: "{{ my_list | first }}" # 1
- debug:
msg: "{{ my_list | last }}" # 5
- debug:
msg: "{{ my_list | length }}" # 5
- debug:
msg: "{{ my_list | random }}" # 随机元素
字典过滤器 #
yaml
vars:
my_dict:
name: John
age: 30
city: Beijing
tasks:
- debug:
msg: "{{ my_dict | dict2items }}" # 转换为列表
- debug:
msg: "{{ my_dict.keys() | list }}" # 键列表
- debug:
msg: "{{ my_dict.values() | list }}" # 值列表
类型转换 #
yaml
vars:
number: 100
string: "200"
tasks:
- debug:
msg: "{{ number | string }}" # "100"
- debug:
msg: "{{ string | int }}" # 200
- debug:
msg: "{{ string | float }}" # 200.0
- debug:
msg: "{{ number | to_json }}" # JSON 字符串
- debug:
msg: "{{ number | to_yaml }}" # YAML 字符串
默认值 #
yaml
vars:
defined_var: "value"
# undefined_var 未定义
tasks:
- debug:
msg: "{{ defined_var | default('default') }}" # value
- debug:
msg: "{{ undefined_var | default('default') }}" # default
- debug:
msg: "{{ undefined_var | default(omit) }}" # 省略参数
set_fact 和 include_vars #
set_fact #
动态设置变量:
yaml
tasks:
- name: Set a fact
set_fact:
app_version: "1.0.0"
app_config:
port: 8080
debug: false
- name: Use the fact
debug:
msg: "Version: {{ app_version }}"
- name: Set fact from command
shell: cat /etc/os-release | grep VERSION_ID | cut -d'"' -f2
register: os_version
- name: Set fact from result
set_fact:
os_version: "{{ os_version.stdout }}"
include_vars #
动态加载变量文件:
yaml
tasks:
- name: Load variables
include_vars:
file: vars/{{ environment }}.yml
name: env_vars
- name: Use loaded variables
debug:
msg: "DB Host: {{ env_vars.db_host }}"
- name: Load all vars from directory
include_vars:
dir: vars/
extensions: ['yml', 'yaml']
变量最佳实践 #
1. 使用有意义的变量名 #
yaml
# 好的命名
app_name: myapp
nginx_port: 80
database_host: localhost
# 不好的命名
n: myapp
p: 80
h: localhost
2. 分离敏感变量 #
yaml
# 使用 Vault 加密敏感变量
# vars/secrets.yml (加密)
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"
3. 使用默认值 #
yaml
# roles/nginx/defaults/main.yml
nginx_port: 80
nginx_user: www-data
nginx_worker_processes: auto
4. 组织变量文件 #
text
inventory/
├── group_vars/
│ ├── all.yml # 全局变量
│ ├── webservers.yml # Web 服务器变量
│ └── databases.yml # 数据库变量
└── host_vars/
├── web1.yml # 特定主机变量
└── db1.yml
5. 文档化变量 #
yaml
# vars/app.yml
---
# Application Configuration
# Author: DevOps Team
# Updated: 2024-01-15
app:
name: myapp # Application name
version: 1.0.0 # Application version
port: 8080 # Application port
debug: false # Debug mode (set to true in development)
database:
host: localhost # Database host
port: 3306 # Database port
name: "{{ app.name }}_db" # Database name
user: "{{ app.name }}" # Database user
password: "{{ vault_db_password }}" # Database password (encrypted)
下一步 #
现在你已经掌握了变量管理,接下来学习 Jinja2 模板 了解如何使用模板生成配置文件!
最后更新:2026-03-29