第八章:变量与 Facts
掌握 Ansible 变量的定义、使用和管理,以及 Facts 系统。
最后更新: 2024-01-22
页面目录
Ansible 变量与 Facts
变量和 Facts 是 Ansible 自动化中的核心概念,用于存储和访问动态数据。
变量基础
变量命名规则
# 合法的变量名
variable_name: value
my_variable: value
app_version: "1.0.0"
nginx_config_port: 80
# 不合法的变量名(包含特殊字符)
# 1-variable: value # 不能以数字开头
# my-variable: value # 不能包含连字符
# my.variable: value # 不能包含点
变量定义位置
| 位置 | 作用域 | 说明 |
|---|---|---|
Playbook vars |
Play | Play 级别变量 |
vars_files |
Play | 从文件加载变量 |
group_vars/ |
组 | 主机组级别变量 |
host_vars/ |
主机 | 单主机级别变量 |
命令行 -e |
全局 | 执行时传入变量 |
| 注册变量 | Task | 任务输出注册 |
| Facts | 主机 | 远程主机信息 |
Playbook 变量
vars 关键字
---
- name: Variables in playbook
hosts: webservers
vars:
app_name: myapp
app_version: "2.0.0"
app_port: 8080
db_host: 192.168.1.10
db_port: 3306
tasks:
- name: Display variables
debug:
msg: "{{ app_name }} v{{ app_version }}"
vars_files 加载变量文件
---
- name: Load variables from file
hosts: webservers
vars_files:
- vars/common.yml
- vars/{{ environment }}.yml
tasks:
- name: Use loaded variables
debug:
msg: "{{ app_name }}"
变量文件格式
# vars/common.yml
---
app_name: myapp
app_version: "2.0.0"
enable_cache: yes
# vars/production.yml
---
environment: production
db_host: prod-db.example.com
db_port: 3306
# vars/staging.yml
---
environment: staging
db_host: staging-db.example.com
db_port: 3306
Inventory 变量
组变量 (group_vars)
# group_vars/all.yml # 所有主机
# group_vars/webservers.yml # webservers 组
# group_vars/dbservers.yml # dbservers 组
# group_vars/all.yml
---
ansible_user: deploy
ansible_python_interpreter: /usr/bin/python3
ntp_server: pool.ntp.org
timezone: Asia/Shanghai
# group_vars/webservers.yml
---
nginx_version: "1.24.0"
app_port: 8080
max_connections: 1000
# group_vars/dbservers.yml
---
db_engine: mysql
db_version: "8.0"
db_port: 3306
db_buffer_size: 256M
主机变量 (host_vars)
# host_vars/web1.yml
---
nginx_port: 80
server_alias: web1.example.com
# host_vars/web2.yml
---
nginx_port: 8080
server_alias: web2.example.com
Inventory 内联变量
# inventory/hosts
[webservers]
web1 ansible_host=192.168.1.10 nginx_port=80
web2 ansible_host=192.168.1.11 nginx_port=8080
[webservers:vars]
http_port=80
注册变量
register 基本用法
tasks:
- name: Run command
command: uptime
register: uptime_result
- name: Display output
debug:
msg: "System uptime: {{ uptime_result.stdout }}"
注册变量结构
{
"changed": true,
"failed": false,
"rc": 0,
"stdout": "...",
"stdout_lines": ["..."],
"stderr": "",
"stderr_lines": [],
"msg": "",
"cmd": [...],
"start": "2024-01-01T10:00:00.000000Z",
"end": "2024-01-01T10:00:01.000000Z",
"delta": "0:00:01.000000"
}
实用示例
tasks:
# 命令结果检查
- name: Check if user exists
command: id deployuser
register: user_check
ignore_errors: yes
- name: Create user if not exists
user:
name: deployuser
comment: "Deploy User"
when: user_check.rc != 0
# 服务状态检查
- name: Get service status
command: systemctl is-active nginx
register: nginx_status
- name: Display status
debug:
msg: "Nginx is {{ nginx_status.stdout }}"
# 文件内容检查
- name: Read file content
command: cat /etc/os-release
register: os_info
- name: Check OS
debug:
msg: "{{ os_info.stdout_lines[0] }}"
Facts 系统
收集 Facts
# 默认自动收集
---
- name: Show facts
hosts: all
tasks:
- name: Display all facts
debug:
var: ansible_facts
常用 Facts 变量
| 变量 | 说明 |
|---|---|
ansible_facts.hostname |
主机名 |
ansible_facts.ipv4.address |
IPv4 地址 |
ansible_facts.os_family |
操作系统家族 |
ansible_facts.distribution |
发行版 |
ansible_facts.distribution_version |
发行版版本 |
ansible_facts.architecture |
系统架构 |
ansible_facts.memory_mb.total |
总内存(MB) |
ansible_facts.memory_mb.free |
可用内存(MB) |
ansible_facts.cpu_cores |
CPU 核心数 |
ansible_facts.virtualization_role |
虚拟化角色 |
ansible_facts.kernel |
内核版本 |
ansible_facts.python_version |
Python 版本 |
禁用 Facts 收集
---
- name: Fast playbook
hosts: all
gather_facts: no
选择性收集 Facts
---
- name: Selective facts
hosts: all
gather_facts:
- ansible_distribution
- ansible_memory_mb
- ansible_eth0
Facts 使用示例
tasks:
# 根据 OS 类型安装软件
- name: Install web server
package:
name: nginx
state: present
when: ansible_facts['os_family'] == "Debian"
- name: Install web server
package:
name: nginx
state: present
when: ansible_facts['os_family'] == "RedHat"
# 根据内存设置配置
- name: Set cache size based on memory
set_fact:
redis_max_memory: "{{ (ansible_facts['memory_mb']['total'] * 0.5)|int }}mb"
# 根据 IP 配置
- name: Configure bind address
template:
src: app.conf.j2
dest: /etc/myapp/app.conf
set_fact 模块
基本用法
tasks:
# 创建自定义变量
- name: Set custom fact
set_fact:
my_custom_var: "custom_value"
# 复杂数据结构
- name: Set complex fact
set_fact:
app_config:
name: myapp
version: "2.0"
port: 8080
# 基于其他变量计算
- name: Calculate derived value
set_fact:
cache_size: "{{ (ansible_facts.memory_mb.total * 0.6)|int }}"
变量优先级
┌─────────────────────────────────────────────────────────────────┐
│ 变量优先级(从低到高) │
├─────────────────────────────────────────────────────────────────┤
│ 1. 命令行 inventory hostname 变量 │
│ 2. 命令行 --extra-vars (最低) │
│ 3. inventory group_vars/all │
│ 4. inventory group_vars/群组名 │
│ 5. inventory host_vars/主机名 │
│ 6. playbook group_vars/群组名 │
│ 7. playbook host_vars/主机名 │
│ 8. 主机 fact │
│ 9. play vars │
│ 10. play vars_files │
│ 11. role defaults │
│ 12. inventory host_vars (tasks) │
│ 13. block vars (task blocks) │
│ 14. task vars │
│ 15. set_fact / register vars │
│ 16. 命令行 --extra-vars (最高) │
└─────────────────────────────────────────────────────────────────┘
变量操作
Jinja2 表达式
tasks:
# 字符串操作
- debug:
msg: "{{ 'hello' + ' ' + 'world' }}"
msg: "{{ 'hello' | upper }}"
msg: "{{ 'Hello World' | lower }}"
msg: "{{ 'Hello' | replace('Hello', 'Hi') }}"
msg: "{{ 'Hello World' | regex_replace('World', 'Ansible') }}"
# 数学运算
- debug:
msg: "{{ 10 + 5 }}"
msg: "{{ 10 - 5 }}"
msg: "{{ 10 * 2 }}"
msg: "{{ 10 / 3 }}"
msg: "{{ 10 // 3 }}"
msg: "{{ 10 % 3 }}"
msg: "{{ 2 ** 3 }}"
# 列表操作
- debug:
msg: "{{ [1, 2, 3] + [4, 5] }}"
msg: "{{ [1, 2, 3] | length }}"
msg: "{{ [3, 1, 2] | sort }}"
msg: "{{ [1, 2, 3] | first }}"
msg: "{{ [1, 2, 3] | last }}"
msg: "{{ [1, 2, 3, 4, 5] | random }}"
# 字典操作
- debug:
msg: "{{ {'a': 1, 'b': 2} | keys }}"
msg: "{{ {'a': 1, 'b': 2} | values }}"
msg: "{{ dict({'a': 1}) | combine({'b': 2}) }}"
条件表达式
tasks:
- debug:
msg: "{{ 'yes' if my_var else 'no' }}"
msg: "{{ 'yes' if my_var is defined and my_var else 'no' }}"
默认值处理
tasks:
# 使用 default 过滤器
- debug:
msg: "{{ undefined_var | default('default_value') }}"
msg: "{{ config.port | default(80) }}"
msg: "{{ db_host | default(groups['dbservers'][0]) }}"
# 多级默认值
- debug:
msg: "{{ (my_dict or {}).key | default('value') }}"
复杂变量示例
字典变量
# 定义
vars:
users:
alice:
name: Alice Wang
email: alice@example.com
groups: [wheel, developers]
bob:
name: Bob Li
email: bob@example.com
groups: [developers]
# 使用
tasks:
- name: Create users
user:
name: "{{ item.key }}"
comment: "{{ item.value.name }}"
groups: "{{ item.value.groups | join(',') }}"
loop: "{{ users | dict2items }}"
列表变量
# 定义
vars:
packages:
- name: nginx
version: "1.24.0"
- name: php-fpm
version: "8.1"
- name: mysql
version: "8.0"
# 使用
tasks:
- name: Install packages
apt:
name: "{{ item.name }}"
state: present
loop: "{{ packages }}"
特殊变量
| 变量 | 说明 |
|---|---|
inventory_hostname |
当前主机名 |
inventory_hostname_short |
短主机名 |
groups |
所有主机组列表 |
group_names |
当前主机所属组列表 |
play_hosts |
当前 Play 所有主机 |
ansible_play_hosts |
同上 |
ansible_play_batch |
当前批次主机 |
playbook_dir |
Playbook 目录 |
role_path |
当前 Role 路径 |
ansible_version |
Ansible 版本 |
下一步
现在你已经掌握了变量和 Facts。接下来让我们学习 Jinja2 模板引擎。