6.Ansible自动化之-管理变量和事实

发布于:2025-08-18 ⋅ 阅读:(18) ⋅ 点赞:(0)

6.管理变量和事实

实验环境

[bq@controller ~]$ mkdir web && cd web

[bq@controller web]$ cat > ansible.cfg <<'EOF'
[defaults]
remote_user = bq
inventory = ./inventory

[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
EOF

[bq@controller web]$ cat > inventory <<'EOF'
controller
node1
node2
node3
node4
EOF

管理 VARIABLES(变量)

变量简介

变量是 Ansible 中存储数据的 “容器”,可以在 playbook、命令中重复使用。比如我们可以用变量定义软件包名称(如package: httpd),之后在安装、启动服务时直接引用这个变量,避免重复写相同的值,既方便维护又减少出错。

变量命名规则
  • 只能包含字母、数字和下划线(比如my_var1是合法的,而my varmy.var$myvar都是非法的)
  • 必须以字母开头(不能以数字或下划线开头,如1var_var都是错误的)
变量范围和优先级

Ansible 的变量可以在不同位置定义,按生效范围分为 3 类,优先级从高到低如下:

范围 定义位置 说明
Global(全局) 命令行参数或 Ansible 配置文件 优先级最高,会覆盖其他范围的同名变量
Play(剧本) playbook 的varsvars_files 仅在当前 play 中生效,优先级高于主机范围变量
Host(主机) 清单、group_varshost_vars 针对具体主机或主机组生效,优先级最低,会被全局和剧本范围变量覆盖

简单说:如果在多个地方定义了同名变量,最终生效的是优先级高的那个。

Global scope(全局变量)

全局变量通过命令行的-e选项传递,临时生效,适用于单次执行的特殊需求。

命令语法
ansible [主机/组] -m [模块] -a "[模块参数]" -e "[变量=值]"

  • -m:指定使用的模块(如debug用于输出信息,yum用于管理软件包)
  • -a:指定模块的具体参数
  • -e:定义临时变量(键值对格式)

示例 1:用debug模块验证全局变量
通过-e定义变量package=httpd,并通过debug模块的msg参数输出变量值:

[bq@controller web]$ ansible node1 -m debug -a "msg={{ package }}" -e "package=httpd"
node1 | SUCCESS => {
    "msg": "httpd"  # 输出变量package的值为httpd
}

示例 2:用yum模块安装软件(引用全局变量)
通过-e定义变量package=httpd,并使用yum模块安装该软件包:

[bq@controller web]$ ansible node1 -m yum -a "name={{ package }} state=present" -e "package=httpd"
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Nothing to do",  # 若已安装则提示无需操作
    "rc": 0,
    "results": [
        "Installed: httpd"  # 若未安装则提示安装成功
    ]
}
Play scope(剧本变量)

剧本变量在 playbook 中定义,仅对当前 play 生效,适合在剧本内统一管理变量。

vars声明(直接在 play 中定义变量)

格式 1:键值对格式(推荐)
直接在 play 的vars下以变量名: 值的形式定义:

---
- name: 测试play中的vars声明  # play名称
  hosts: node1  # 目标主机
  vars:  # 定义变量
    user: joe  # 变量user的值为joe
    home: /home/joe  # 变量home的值为/home/joe
  tasks:  # 任务列表
    - name: 创建用户{{ user }}  # 任务名称,引用user变量
      user:  # user模块用于管理用户
        name: "{{ user }}"  # 用户名,引用user变量
        home: "{{ home }}"  # 家目录,引用home变量
        state: present  # 确保用户存在

    - name: 输出用户信息  # 第二个任务,调试变量
      debug:  # debug模块用于输出信息
        msg: |  # 多行消息
          用户名是 {{ user }}
          家目录是 {{ home }}
...

格式 2:列表格式(注意:Ansible 2.18 版本已移除)
早期版本支持以列表形式定义,每个变量作为列表元素:

---
- name: 测试play中的vars声明(列表格式)
  hosts: node1
  vars:  # 列表格式,每个变量是一个键值对
    - user: joe 
    - home: /home/joe 
  tasks:
    - name: 创建用户{{ user }}
      user:
        name: "{{ user }}"
        home: "{{ home }}"
        state: present

    - name: 输出用户信息
      debug:
        msg: |
          用户名是 {{ user }}
          家目录是 {{ home }}
vars_files声明(引用外部变量文件)

当变量较多时,可将变量存到外部文件,再通过vars_files引用,便于分类管理。

示例流程

  1. 创建变量文件存放目录vars
  2. vars目录下创建变量文件(如user1.yaml
  3. 在 playbook 中通过vars_files引用该文件

步骤详解

  1. 创建变量文件目录及文件:

    [bq@controller web]$ mkdir vars  # 创建存放变量文件的目录
    [bq@controller web]$ vim vars/user1.yaml  # 创建变量文件
    

    变量文件内容(YAML 格式):

    # vars/user1.yaml
    user: user1  # 定义变量user的值为user1
    home: /home/user1  # 定义变量home的值为/home/user1
    
  2. 编写引用变量文件的 playbook:

    ---
    - name: 测试vars_files引用外部变量
      hosts: node1
      vars_files:  # 引用外部变量文件
        - vars/user1.yaml  # 变量文件路径
      tasks:
        - name: 创建用户{{ user }}
          user:
            name: "{{ user }}"
            home: "{{ home }}"
            state: present
    
        - name: 输出用户信息
          debug:
            msg: >  # 单行消息(换行被忽略)
              用户名是 {{ user }} 家目录是 {{ home }}
    
变量引用注意事项

变量通过{{ 变量名 }}引用,但有一个重要规则:当变量作为值的第一个元素时,必须用引号包裹,否则会报错。

错误示例(变量作为值的第一个元素且未加引号):

---
- name: 测试变量引用错误案例
  hosts: node1
  vars:
    user: joe
  tasks:
    - name: 创建用户
      user:
        name: {{ user }}  # 错误:变量作为第一个元素,未加引号
        state: present

错误原因:YAML 语法会将{{ user }}识别为特殊结构,而非字符串,导致解析失败。

正确示例(加引号包裹):

name: "{{ user }}"  # 正确:用双引号包裹
# 或
name: '{{ user }}'  # 正确:用单引号包裹
Host scope(主机变量)

主机变量针对具体主机或主机组生效,优先级低于全局和剧本变量。推荐通过目录结构管理(而非直接写在清单中)。

不推荐:直接在清单文件中定义(旧做法)

在清单文件中同时定义主机和变量,会导致清单文件混乱,仅作了解:

示例清单文件

[servers]  # 主机组servers
node1 user=bq  # 给node1定义变量user=bq
node2  # 未单独定义,将使用组变量

[servers:vars]  # 给servers组定义变量
user=laowang  # 组内所有主机默认使用user=laowang(node1因单独定义而覆盖)

验证变量值

[bq@controller web]$ ansible servers -m debug -a 'var=user'  # 查看servers组的user变量
node1 | SUCCESS => {
    "user": "bq"  # node1使用自己的变量
}
node2 | SUCCESS => {
    "user": "laowang"  # node2使用组变量
}
推荐:通过目录结构定义(group_varshost_vars

通过group_vars(主机组变量)和host_vars(单主机变量)目录管理,结构清晰,是官方推荐的做法。

目录结构

工作目录/
├── inventory       # 主机清单
├── group_vars/     # 存放主机组变量(文件名=组名)
│   └── servers.yaml  # servers组的变量
└── host_vars/      # 存放单主机变量(文件名=主机名)
    └── node1.yaml    # node1的变量

示例 1:基础用法

  1. 准备清单文件:

    [bq@controller web]$ cat inventory 
    [servers]  # 定义主机组servers
    node1
    node2
    
  2. 创建组变量文件:

    [bq@controller web]$ mkdir group_vars  # 创建组变量目录
    [bq@controller web]$ vim group_vars/servers.yaml  # 定义servers组的变量
    user: laowang  # 组内所有主机默认user=laowang
    
  3. 创建主机变量文件:

    [bq@controller web]$ mkdir host_vars  # 创建主机变量目录
    [bq@controller web]$ vim host_vars/node1.yaml  # 定义node1的变量
    user: bq  # node1的user=bq(覆盖组变量)
    
  4. 验证变量值:

    [bq@controller web]$ ansible servers -m debug -a 'var=user'
    node1 | SUCCESS => {
        "user": "bq"  # node1使用主机变量
    }
    node2 | SUCCESS => {
        "user": "laowang"  # node2使用组变量
    }
    

示例 2:嵌套组变量
当主机属于多个嵌套组(如dc1dc2属于dc组),变量优先级为:主机变量 > 直接所属组变量 > 父组变量

  1. 清单文件(含嵌套组):

    [bq@controller web]$ cat inventory 
    [dc1]  # 子组dc1
    node1
    node2
    
    [dc2]  # 子组dc2
    node3
    node4
    
    [dc:children]  # 父组dc,包含dc1和dc2
    dc1
    dc2
    
  2. 定义各级变量:

    # 父组dc的变量
    [bq@controller web]$ echo "package: httpd" > group_vars/dc
    # 子组dc1的变量
    [bq@controller web]$ echo "package: httpd" > group_vars/dc1
    # 子组dc2的变量
    [bq@controller web]$ echo "package: apache" > group_vars/dc2
    # 主机node1的变量(覆盖所有组变量)
    [bq@controller web]$ echo "package: mariadb-server" > host_vars/node1.yaml
    
  3. 验证变量值:

    [bq@controller web]$ ansible all -m debug -a 'var=package'
    node1 | SUCCESS => { "package": "mariadb-server" }  # 主机变量优先级最高
    node2 | SUCCESS => { "package": "httpd" }          # 子组dc1变量
    node3 | SUCCESS => { "package": "apache" }         # 子组dc2变量
    node4 | SUCCESS => { "package": "apache" }         # 子组dc2变量
    
主机连接特殊变量

这些变量用于配置 Ansible 与受管主机的连接方式(如用户名、端口、提权等),常用变量如下:

变量名 功能说明
ansible_host 实际连接的主机地址(默认与清单中的主机名一致)
ansible_port SSH 端口(默认 22)
ansible_user SSH 连接用户名
ansible_ssh_pass SSH 密码(禁止明文存储,需用 Vault 加密)
ansible_become 是否启用提权(如sudo,默认false
ansible_become_method 提权方式(如sudosu,默认sudo
ansible_become_user 提权后的目标用户(默认root
ansible_become_pass 提权密码(禁止明文存储,需用 Vault 加密)

可在host_varsgroup_vars中定义这些变量,例如为node1指定连接用户:

# host_vars/node1.yaml
ansible_user: devops  # 连接node1时使用devops用户
ansible_become: True  # 自动提权
数组变量(复杂结构变量)

当需要存储一组相关数据(如多个用户的信息),可使用数组变量(类似字典或列表),避免定义大量零散变量。

数组变量的定义

零散变量定义(不推荐):

# 每个用户的信息分散成多个变量,难以管理
user1_first_name: Bob
user1_last_name: Jones
user1_home_dir: /users/bjones
user2_first_name: Anne
user2_last_name: Cook
user2_home_dir: /users/acook

数组变量定义(推荐):

# 用字典结构整合相关变量,键为用户名,值为该用户的详细信息
users:
  bjones:  # 第一个用户
    first_name: Bob
    last_name: Jones
    home_dir: /users/bjones
  acook:   # 第二个用户
    first_name: Anne
    last_name: Cook
    home_dir: /users/acook
数组变量的引用

有两种引用方式,推荐根据场景选择:

引用方式 语法示例 适用场景
.分隔符 users.bjones.first_name 键名不含特殊字符,且不与 Python 关键字冲突时
['']包裹 users['acook']['home_dir'] 键名含特殊字符,或与 Python 关键字(如copy)冲突时

示例 1:引用字典类型数组

---
- name: 测试字典类型数组变量
  hosts: node1
  vars: 
    users:  # 定义字典类型数组
      bq:
        user_name: bq
        home_path: /home/bq
      laowang:
        user_name: laowang
        home_path: /home/laowang
  tasks:
    - name: 创建用户{{ users.bq.user_name }}  # 用.分隔符引用
      user:
        name: '{{ users.bq.user_name }}'  # 变量作为第一个元素,加引号
        home: "{{ users.bq.home_path }}"

    - name: 输出laowang信息  # 用['']引用
      debug: 
        msg: >
          用户名是 {{ users['laowang']['user_name'] }}
          家目录是 {{ users['laowang']['home_path'] }}

示例 2:引用列表类型数组
数组也可以是列表(按索引访问,索引从 0 开始):

---
- name: 测试列表类型数组变量
  hosts: node1
  vars: 
    users:  # 列表类型数组(每个元素是一个字典)
      - user_name: bq1  # 第一个元素(索引0)
        home_path: /home/bq1
      - user_name: bq2  # 第二个元素(索引1)
        home_path: /home/bq2
  tasks:
    - name: 创建用户{{ users.0.user_name }}  # 用.加索引引用
      user:
        name: "{{ users.0.user_name }}"
        home: "{{ users.0.home_path }}"

    - name: 输出第二个用户  # 用[索引]引用
      debug: 
        msg: "{{ users[1].user_name }}"  # 索引1对应第二个元素
register语句(捕获任务输出)

register用于将任务的执行结果保存到变量中,方便后续任务使用(如判断任务是否成功、提取输出信息等)。

示例:安装httpd并捕获安装结果

---
- name: 安装软件并捕获结果
  hosts: node1
  tasks:
    - name: 安装httpd
      yum:
        name: httpd
        state: installed  # 确保软件已安装
      register: install_result  # 将结果保存到install_result变量

    - name: 输出安装结果
      debug: 
        var: install_result  # 打印变量内容(包含安装状态、变更信息等)

执行后可看到install_result包含的信息:如是否有变更(changed: true表示安装成功)、软件版本、执行日志等。

Magic 变量(Ansible 内置变量)

Magic 变量是 Ansible 自动生成的特殊变量,用于获取受管主机的清单信息,常用的有 4 个:

变量名 功能说明
inventory_hostname 清单中定义的当前主机名(可能与实际主机名不同)
group_names 当前主机所属的所有主机组列表
groups 清单中所有主机组及组内主机的信息(字典格式)
hostvars 所有受管主机的变量信息(可用于跨主机引用变量,如hostvars['node1']['user']

示例清单(用于测试 Magic 变量):

controller  # 单独主机

[webs]  # 网站服务器组
node1
node2

[dbs]   # 数据库服务器组
node3
node4

验证 Magic 变量

  1. inventory_hostname(当前主机名):

    [bq@controller web]$ ansible node1 -m debug -a 'var=inventory_hostname'
    node1 | SUCCESS => {
        "inventory_hostname": "node1"  # 清单中定义的主机名
    }
    
  2. group_names(所属组):

    [bq@controller web]$ ansible node1 -m debug -a 'var=group_names'
    node1 | SUCCESS => {
        "group_names": ["webs"]  # node1属于webs组
    }
    
  3. groups(所有组信息):

    [bq@controller web]$ ansible node1 -m debug -a 'var=groups'
    node1 | SUCCESS => {
        "groups": {
            "all": ["controller", "node1", "node2", "node3", "node4"],
            "dbs": ["node3", "node4"],
            "webs": ["node1", "node2"],
            "ungrouped": ["controller"]  # 未分组主机
        }
    }
    
  4. hostvars(跨主机变量):

    # 查看node3的所属组(需先收集过node3的变量)
    [bq@controller web]$ ansible node1 -m debug -a 'var=hostvars.node3.group_names'
    node1 | SUCCESS => {
        "hostvars.node3.group_names": ["dbs"]  # node3属于dbs组
    }
    

管理 SECRETS(敏感信息)

Ansible Vault 简介

Ansible 中可能需要使用密码、API 密钥等敏感信息,若明文存储会有安全风险。Ansible Vault 可加密这些敏感文件(如变量文件),只有知道密码的人才能解密使用。

ansible-vault命令(加密 / 解密工具)

ansible-vault用于管理加密文件,常用命令如下:

命令 功能说明 常用选项
create 创建新的加密文件 --vault-password-file:从文件读取密码
view 查看加密文件内容 同上
edit 编辑加密文件 同上
encrypt 加密已存在的明文文件 同上
decrypt 解密加密文件(会覆盖原文件) 同上
rekey 更改加密文件的密码 --new-vault-password-file:新密码文件

示例操作

  1. 设置默认编辑器(可选,默认用vi):

    [bq@controller web]$ export EDITOR=vim  # 临时设置为vim
    [bq@controller web]$ echo 'export EDITOR=vim' >> ~/.bashrc  # 永久生效(需重新加载)
    [bq@controller web]$ source ~/.bashrc  # 重新加载配置
    
  2. 创建加密文件(如secret.yaml,存储密码):

    [bq@controller web]$ ansible-vault create secret.yaml
    New Vault password: 123  # 输入密码(示例用123,实际需复杂密码)
    Confirm New Vault password: 123  # 确认密码
    

    输入内容(YAML 格式):

    password: redhat  # 敏感信息:密码为redhat
    
  3. 查看加密文件

    [bq@controller web]$ ansible-vault view secret.yaml
    Vault password: 123  # 输入创建时的密码
    password: redhat  # 解密后内容
    
  4. 从密码文件读取密码(避免每次输入):

    [bq@controller web]$ echo 123 > pass  # 创建密码文件(权限需设为600)
    [bq@controller web]$ chmod 600 pass  # 限制权限,仅所有者可读写
    [bq@controller web]$ ansible-vault view secret.yaml --vault-password-file=pass
    password: redhat  # 无需手动输入密码
    
  5. 在配置文件中指定密码文件(更便捷):

    [bq@controller web]$ vim ansible.cfg  # 编辑Ansible配置
    [defaults]
    vault_password_file = ./pass  # 指定密码文件路径
    

    之后操作加密文件无需指定--vault-password-file

    [bq@controller web]$ ansible-vault view secret.yaml  # 直接查看
    password: redhat
    
  6. 编辑加密文件

    [bq@controller web]$ ansible-vault edit secret.yaml  # 自动解密并编辑
    # 编辑后内容:password: redhat123(保存后自动重新加密)
    
  7. 解密文件(谨慎使用,会明文存储):

    [bq@controller web]$ ansible-vault decrypt secret.yaml
    Decryption successful  # 解密成功,原文件变为明文
    [bq@controller web]$ cat secret.yaml 
    password: redhat123  # 明文显示
    
  8. 重新加密文件

    [bq@controller web]$ ansible-vault encrypt secret.yaml
    Encryption successful  # 重新加密
    
  9. 更改密码

    [bq@controller web]$ ansible-vault rekey secret.yaml  # 交互式更改
    New Vault password: 456  # 新密码
    Confirm New Vault password: 456
    Rekey successful
    
综合案例:用加密变量配置数据库

目标:通过加密的变量文件配置 MySQL 用户,避免密码明文暴露。

步骤流程

  1. 创建加密的变量文件(存储数据库用户信息)
  2. 编写 playbook,引用加密变量文件
  3. 执行 playbook,使用加密密码配置数据库

步骤详解

  1. 创建加密变量文件

    [bq@controller web]$ mkdir vault  # 创建存放加密文件的目录
    [bq@controller web]$ ansible-vault create vault/mysql.yml  # 创建加密文件
    

    输入变量内容(数据库用户信息):

    user: bq  # 数据库用户名
    password: redhat  # 数据库密码(加密存储)
    host: '%'  # 允许所有主机连接
    priv: '*.*:ALL'  # 权限:所有库表的所有权限
    
  2. 编写 playbookplaybook.yaml):

    ---
    - name: 配置MariaDB服务器
      hosts: node1
      vars_files:
        - vault/mysql.yml  # 引用加密的变量文件
      tasks:
        - name: 安装MariaDB及依赖
          yum:
            name: 
              - mariadb-server  # 数据库服务
              - python3-PyMySQL  # Python连接MySQL的库
            state: present
    
        - name: 启动并启用MariaDB
          service:
            name: mariadb
            enabled: yes  # 开机自启
            state: started  # 启动服务
    
        - name: 创建数据库用户{{ user }}
          mysql_user:  # 管理MySQL用户的模块
            name: "{{ user }}"  # 引用加密变量中的用户名
            password: "{{ password }}"  # 引用加密变量中的密码
            host: "{{ host }}"  # 允许连接的主机
            priv: "{{ priv }}"  # 权限设置
            state: present  # 确保用户存在
    
  3. 执行 playbook

    # 若ansible.cfg未配置vault_password_file,需用--ask-vault-pass交互输入密码
    [bq@controller web]$ ansible-playbook playbook.yaml --ask-vault-pass
    Vault password: 123  # 输入加密文件的密码
    
  4. 验证结果(在 node1 上):

    [root@node1 ~]# mysql -u bq -predhat  # 使用加密变量中的用户名和密码登录
    Welcome to the MariaDB monitor.  # 登录成功,说明配置生效
    
变量管理推荐做法
  1. 敏感变量单独加密:将敏感信息(密码、密钥)放在独立文件中,用 Vault 加密;普通变量明文存储。
  2. 目录结构分类:通过group_varshost_vars按主机 / 组分类变量,每个主机 / 组可包含多个变量文件(如vars.yaml存普通变量,vault.yaml存加密变量)。

推荐目录结构示例

web/
├── ansible.cfg          # Ansible配置
├── inventory            # 主机清单
├── playbook.yaml        # 主剧本
├── group_vars/          # 组变量
│   ├── all.yaml         # 所有主机通用变量(普通)
│   └── servers.yaml     # servers组变量(普通)
├── host_vars/           # 主机变量
│   └── node1/
│       ├── vars.yaml    # node1的普通变量
│       └── vaults.yaml  # node1的敏感变量(加密)
└── vault/
    └── mysql.yml        # 数据库相关敏感变量(加密)

管理 FACTS(主机信息)

FACTS 介绍

FACTS是 Ansible 自动从受管主机收集的信息,相当于主机的 “体检报告”,包括主机名、IP 地址、操作系统、内存、磁盘等。这些信息会被存为变量,可在 playbook 中直接引用。

用途

  • 根据内核版本决定是否重启主机
  • 根据内存大小调整软件配置(如 MySQL 缓存)
  • 用主机 IP 地址自动填充配置文件
查看 FACTS 内容
查看所有 FACTS

通过debug模块打印ansible_facts变量(包含所有 FACTS):

---
- name: 打印所有FACTS信息
  hosts: node1
  tasks:
    - name: 输出所有FACTS
      debug:
        var: ansible_facts  # 所有FACTS都在ansible_facts变量中
查看单个 FACTS

直接引用具体的 FACTS 变量(如主机名、IP 地址):

---
- hosts: node1
  tasks:
    - name: 输出指定FACTS
      debug: 
        msg: >
          主机{{ ansible_fqdn }}的默认IPv4地址是{{ ansible_default_ipv4.address }}
          # ansible_fqdn:完全限定域名;ansible_default_ipv4.address:默认IPv4地址
常用 FACTS 变量
FACTS 描述 变量(新格式,Ansible 2.5+) 旧格式(兼容,不推荐)
短主机名 ansible_facts['hostname'] ansible_hostname
完全限定域名(FQDN) ansible_facts['fqdn'] ansible_fqdn
默认 IPv4 地址 ansible_facts['default_ipv4']['address'] ansible_default_ipv4['address']
所有网络接口 ansible_facts['interfaces'] ansible_interfaces
内核版本 ansible_facts['kernel'] ansible_kernel
DNS 服务器列表 ansible_facts['dns']['nameservers'] ansible_dns['nameservers']
/dev/vda1分区大小 ansible_facts['devices']['vda']['partitions']['vda1']['size'] ansible_devices['vda']['partitions']['vda1']['size']
setup模块(收集 FACTS)

setup模块用于手动收集 FACTS,支持过滤和限制收集范围,比自动收集更灵活。

命令语法
ansible [主机] -m setup -a "[选项]"

选项 功能说明
filter=Pattern 只收集匹配 Pattern 的 FACTS(支持通配符*
gather_subset=Subset 限制收集的 FACTS 类别(如!all禁用所有,network只收集网络信息)

示例

  1. 只收集默认 IPv4 信息:

    [bq@controller web]$ ansible node1 -m setup -a 'filter=ansible_default_ipv4'
    node1 | SUCCESS => {
        "ansible_facts": {
            "ansible_default_ipv4": {
                "address": "172.25.250.10",  # IPv4地址
                "gateway": "172.25.250.254",  # 网关
                "netmask": "255.255.255.0"  # 子网掩码
            }
        }
    }
    
  2. 只收集网络相关 FACTS:

    [bq@controller web]$ ansible node1 -m setup -a 'gather_subset=network'
    # 只输出网络相关的FACTS(如接口、IP、MAC等)
    
关闭 FACTS 收集

默认情况下,play 会自动收集 FACTS,但以下场景可关闭:

  • 不使用任何 FACTS,想加快 play 执行速度
  • 受管主机无法运行setup模块(如缺少依赖)
  • 需先安装软件再收集 FACTS

关闭方式

  1. 在 play 中设置:

    ---
    - name: 关闭自动FACTS收集
      hosts: node1
      gather_facts: no  # 关闭自动收集
    
  2. 在 Ansible 配置文件中全局设置:

    [defaults]
    gathering = explicit  # 全局关闭自动收集,需手动调用setup模块
    

手动收集:即使关闭自动收集,仍可通过setup模块手动收集:

tasks:
  - name: 手动收集FACTS
    setup:  # 显式调用setup模块收集FACTS

扩展练习:变量优先级验证

实验目标:验证不同位置定义的变量的优先级(从高到低)。

变量定义位置及值

定义位置 变量值 优先级(1 最高,10 最低)
命令行-e user1 1
task 中include_vars引用的文件 user2 2
task 中vars指令 user3 3
play 中vars_files引用的文件 user4 4
play 中vars指令 user5 5
host_vars目录中的主机文件 user6 6
清单文件中主机单独定义 user7 7
group_vars目录中的组文件 user8 8
group_vars/all文件 user9 9
清单文件中all:vars定义 user10 10

实验流程

  1. 准备环境(创建变量文件、目录、清单)
  2. 编写 playbook,引用不同位置的变量
  3. 执行 playbook,观察变量值的变化,验证优先级
步骤详解
  1. 环境准备

    # 创建变量文件
    [bq@controller web]$ echo "user: user2" > var2  # task中include_vars引用
    [bq@controller web]$ echo "user: user4" > var4  # play中vars_files引用
    
    # 创建host_vars和group_vars目录
    [bq@controller web]$ mkdir host_vars group_vars -p
    
    # 定义host_vars(主机变量)
    [bq@controller web]$ echo "user: user6" > host_vars/node1
    
    # 定义group_vars(组变量)
    [bq@controller web]$ echo "user: user8" > group_vars/servers  # 组变量
    [bq@controller web]$ echo "user: user9" > group_vars/all      # 所有组通用变量
    
    # 创建清单文件(含组变量和主机变量)
    [bq@controller web]$ cat > inventory << eof
    [servers]
    node1 user=user7  # 清单中主机单独定义变量
    [servers:vars]
    user=user10       # 清单中组变量
    [all:vars]
    user=user11       # 清单中所有主机的变量
    eof
    
  2. 编写 playbook(playbook.yaml

    ---
    - name: 验证变量优先级
      hosts: node1
      gather_facts: no  # 关闭FACTS收集,加快执行
      vars_files:
        - var4  # 引用var4文件(user=user4)
      vars: 
        user: user5  # play中vars定义(user=user5)
      tasks:
        - name: 输出当前user值(play级变量)
          debug:
            msg: hello {{ user }}  # 预期输出user5(当前最高优先级为play的vars)
    
        - name: 引用var2文件(user=user2)
          include_vars:
            file: var2  # 加载var2文件,变量变为user2
    
        - name: 输出当前user值(task的include_vars后)
          vars:
            user: user3  # task中vars定义(user=user3,优先级更高)
          debug:
            msg: hello {{ user }}  # 预期输出user3
    
  3. 执行 playbook 并观察结果

    # 带命令行变量执行(user=user1,优先级最高)
    [bq@controller web]$ ansible-playbook playbook.yaml -e "user=user1"
    

    预期输出

    • 第一个debug任务:hello user1(命令行变量优先级最高)
    • 第二个debug任务:hello user1(命令行变量覆盖 task 的 vars)

    若去掉命令行变量执行,结果会依次变为:

    • 第一个debughello user5(play 的 vars)
    • 第二个debughello user3(task 的 vars)

    以此类推,可逐步验证各位置变量的优先级。

如涉及版权问题请联系作者处理!!!


网站公告

今日签到

点亮在社区的每一天
去签到