第八章:变量与 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 模板引擎。

👉 Jinja2 模板引擎