Ansible变量全解析:定义、作用域与实战

Ansible 变量

定义变量规则

  • 变量名由字母、数字、下划线组成,且必须以字母开头。
  • 不能使用 Ansible 内置关键字作为变量名。

变量作用域与优先级

Ansible 变量可分为三个范围,优先级从高到低依次为:

  1. Global 范围(高):从命令行或 Ansible 配置中设置的变量。
  2. Play 范围(中):在 Play 及相关结构中设置的变量。
  3. Host 范围(低):在 Inventory、Facts 或 Register 中设置的变量,包括主机组和个别主机上定义的变量。

若变量重复定义,优先级高的将覆盖优先级低的。


定义变量的多种方式

Ansible 支持多种定义变量的方式,包括:

  1. 将模块执行结果注册为变量(register
  2. 直接定义字典类型的变量
  3. 在 Role 文件中定义变量
  4. 通过命令行传递变量
  5. 使用 with_items 迭代将多个任务结果赋值给一个变量
  6. 在 Inventory 中定义主机或主机组变量
  7. 使用内置变量
  8. 使用事实变量(Facts)

变量定义示例

使用 vars 定义变量

yml 复制代码
- name: test
  hosts: node1
  vars:
    - aa: 11
    - bb: 22
    - cc:
        a1: c31
        a2: c32
  tasks:
    - name: create debug1
      debug:
        msg: "{{ aa }}"

    - name: create debug2
      debug:
        msg: "{{ bb }}"

    - name: create debug3
      debug:
        msg: "{{ cc.a1 }}"

    - name: create debug4
      debug:
        msg: "{{ cc.a2 }}"

使用 vars_files 引入外部变量文件

yml 复制代码
- name: test1234
  hosts: node1
  vars_files: /home/student/ansible/var.yml
  tasks:
    - name: debug1
      debug:
        msg: "{{ aa }}"

    - name: debug2
      debug:
        msg: "{{ bb }}"

    - name: debug3
      debug:
        msg: "{{ cc.a1 }}"

    - name: debug4
      debug:
        msg: "{{ cc.a2 }}"

使用 register 注册变量

使⽤register选项,可以将当前task的输出结果赋值给⼀个变量。

yml 复制代码
- name: test a playbook
  hosts: node1
  tasks:
    - name: shell
      shell: "cat /tmp/zz"
      register: zz

    - name: create debug
      debug:
        var: zz

输出示例:

json 复制代码
"zz": {
  "changed": true,
  "cmd": "cat /tmp/zz",
  "delta": "0:00:00.005195",
  "end": "2020-07-29 10:06:17.704232",
  "failed": false,
  "rc": 0,
  "start": "2020-07-29 10:06:17.699037",
  "stderr": "",
  "stderr_lines": [],
  "stdout": "zz",
  "stdout_lines": ["zz"]
}

也可以提取特定字段:

yml 复制代码
- name: create debug
  debug:
    msg: "{{ zz.rc }}"

使用 set_fact 定义变量

set_fact和register的功能很相似,也是将值赋值给变量。它更像shell中变量的赋值⽅式,可以将某个变量的值赋值给另⼀个变量,也可以将字符串赋值给变量

通过'ansible node1 -m setup' 可以查询node1主机所有的事实变量

yml 复制代码
- name: test a playbook
  hosts: node1
  tasks:
    - name: hostname
      debug:
        msg: "{{ ansible_fqdn }}"
        
 #输出示例
  "msg": "node1.example.com"

使用事实变量(Facts)

yml 复制代码
- name: abc
  hosts: node1
  tasks:
    - name: test
      debug:
        msg: "The IPv4 address of {{ ansible_nodename }} is {{ ansible_ens160.ipv4.address }}"
        
#输出示例
 "msg": "the ipv4 address of node1.example.com is 172.16.30.10"

通过命令行传递变量

yml 复制代码
- name: test4
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: "My name is {{ name1 }}"

    - name: create debug2
      debug:
        msg: "My name is {{ name2 }}"

执行命令:

bash 复制代码
ansible-playbook d.yml -e 'name1=tom name2=marry'

#输出示例
"msg": "my name is tom"
"msg": "my name is marry"

在 Inventory 中定义变量

编辑 /host/student/ansible/inventory

shell 复制代码
node1
node2

[net]
node1
node2

[net:vars]
vars1='hello'
vars2='hi'

Playbook 示例:

yml 复制代码
- name: test5
  hosts: node1
  tasks:
    - name: create debug1
      debug:
        msg: "say {{ vars1 }}"

    - name: create debug2
      debug:
        msg: "say {{ vars2 }}"
        
 #输出示例
  "msg": "say hello"
  "msg": "say hi"

使用 group_varshost_vars

/home/student/ansible/ 下创建 host_vars 目录,并为主机定义变量:

yml 复制代码
# /home/student/ansible/host_vars/node1
vars1: groupvars1
vars2: groupvars2

或使用 YAML 文件:

yml 复制代码
# /host/student/ansible/host_vars/node1.yml
vars1: abc
vars2: bcd

Playbook

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: my name is {{vars1}}

    - name: create debug2
      debug:
        msg: my name is {{vars2}}
        
 #输出示例
 "msg": "my name is groupvars1"
 "msg": "my name is groupvars2"

删除/etc/ansible/host_vars/node1 保留/etc/ansible/host_vars/node1.yml,再次执行playbook

yml 复制代码
#输出示例
"msg": "my name is abc"
"msg": "my name is bcd"

若同时存在 node1node1.yml,则 node1 的优先级更高。


内置变量示例

ansible_version(ansible版本)

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: "{{ ansible_version }}"

输出:

json 复制代码
{
  "full": "2.9.18",
  "major": 2,
  "minor": 9,
  "revision": 18,
  "string": "2.9.18"
}

inventory_hostname(当前主机的主机名称)

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: "{{ inventory_hostname }}"

输出:

json 复制代码
"msg": "node1"

play_hosts(当前play所操作的所有主机的主机名列表)

yml 复制代码
- name: test
  hosts: net
  tasks:
    - name: create debug
      debug:
        msg: "{{ play_hosts }}"

输出:

json 复制代码
"msg": [
        "node1",
        "node2"
    ]
"msg": [
        "node1",
        "node2"
    ]

groups(获取到清单中"所有分组"的"分组信息")

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: "{{ groups }}"

输出:

json 复制代码
 "msg": {
        "all": [
            "node1",
            "node2"
        ],
        "net": [
            "node1",
            "node2"
        ],
        "ungrouped": []
    }

group_names(获取到当前主机所在分组的组名)

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: "{{ group_names }}"

输出:

json 复制代码
"msg": [
        "net"
    ]

inventory_diransible主机中清单文件的存放路径

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: create debug
      debug:
        msg: "{{ inventory_dir }}"

输出:

json 复制代码
"msg": "/home/student/ansible"

使用 with_items 迭代赋值

yml 复制代码
- name: test
  hosts: node1
  tasks:
    - name: abc
      shell:
        cmd: echo "{{ item }}"
      with_items:
        - haha
        - heihei
        - hehe
      register: hi_var

    - name: debug1
      debug:
        var: hi_var.results[0].stdout

    - name: debug2
      debug:
        var: hi_var.results[1].stdout

    - name: debug3
      debug:
        var: hi_var.results[2].stdout

输出:

json 复制代码
"hi_var.results[0].stdout": "haha"
"hi_var.results[1].stdout": "heihei"
"hi_var.results[2].stdout": "hehe"
yml 复制代码
   - name: abc
      shell:
        cmd: echo "{{item}}"
      with_items:
        - haha
        - heihei
        - hehe
      register: hi_var

    - name: debug1
      debug:
        msg: "{{hi_var}}"

输出:

json 复制代码
"msg": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo \"haha\"",
                "delta": "0:00:00.003206",
                "end": "2021-04-09 00:36:52.433624",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo \"haha\"",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "haha",
                "rc": 0,
                "start": "2021-04-09 00:36:52.430418",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "haha",
                "stdout_lines": [
                    "haha"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo \"heihei\"",
                "delta": "0:00:00.002276",
                "end": "2021-04-09 00:36:52.676159",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo \"heihei\"",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "heihei",
                "rc": 0,
                "start": "2021-04-09 00:36:52.673883",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "heihei",
                "stdout_lines": [
                    "heihei"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo \"hehe\"",
                "delta": "0:00:00.002589",
                "end": "2021-04-09 00:36:52.920442",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo \"hehe\"",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "hehe",
                "rc": 0,
                "start": "2021-04-09 00:36:52.917853",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "hehe",
                "stdout_lines": [
                    "hehe"
                ]
            }
        ]
    }

Ansible Vault 管理机密

Ansible Vault 用于加密敏感数据(如密码、API 密钥等),避免以明文形式存储。

使用ansible vault,可通过一个名为ansible-vault的命令行工具创建、编辑、加密、解密和查看文件。Ansible vault可以加密任何由ansible使用的结构化数据文件。这可能包括清单变量、playbook中含有的变量文件、在执行playbook时作为参数传递的变量文件,或者ansible角色中定义的变量。

创建加密文件

shell 复制代码
ansible-vault create test.yml
输入密码:redhat
确认密码:redhat

要创建新的加密文件,使用ansible-vault create filename命令,默认使用vi编辑

查看加密文件

shell 复制代码
ansible-vault view test.yml
Vault password:    #输入设置的密码redhat
---
- name: test1
  hosts: node1
  tasks: 
    - name: create user2
      user: 
        name: user2
        state: present

编辑加密文件

shell 复制代码
ansible-vault edit test.yml

加密现有文件

shell 复制代码
ansible-vault encrypt a.yml
输入密码:redhat
确认密码:redhat 

解密文件

shell 复制代码
# 直接解密,永久解密
ansible-vault decrypt test.yml

# 解密并另存为其他文件(原文件仍加密)
ansible-vault decrypt a.yml --output=a-secret.yml

使用密码文件加密/解密

shell 复制代码
# 加密
ansible-vault encrypt e.yml --vault-id secret.txt

# 执行 Playbook
ansible-playbook e.yml --vault-id secret.txt

修改加密文件的密码

shell 复制代码
ansible-vault  rekey  filename  #命令可以修改

ansible-vault rekey a.yml
输入旧密码
输入新密码
确认新密码

执行加密的 Playbook

shell 复制代码
# 使用提示输入密码
ansible-playbook --vault-id @prompt a.yml

# 使用交互式输入密码
ansible-playbook --ask-vault-pass a.yml

# 检查模式(Dry-run)
ansible-playbook --ask-vault-pass a.yml -C

Ansible 变量参考手册

一、 事实变量 (Facts)

这些变量通过 ansible.builtin.setup 模块收集自受控节点(Managed Node)。使用 ansible node1 -m setup 命令可以获取。

变量分类 变量名 描述 示例/备注
网络信息 ansible_default_ipv4.address 主IPv4地址 获取默认路由所使用的IP地址
ansible_<interface>.ipv4.address 指定网卡的IPv4地址 <interface> 替换为实际网卡名,如 ansible_eth0.ipv4.address
系统信息 ansible_fqdn 完全合格域名 (FQDN) node1.example.com
ansible_hostname 主机名称 (短名称) node1
ansible_memtotal_mb 总内存大小 (单位: MB) 1024 (表示 1GB 内存)
ansible_bios_version BIOS 版本号 xx.xx.xx
存储信息 ansible_devices.vda.size vda 硬盘的总容量 通常表示第一块虚拟磁盘
ansible_devices.vdb.size vdb 硬盘的总容量 通常表示第二块虚拟磁盘
ansible_lvm.vgs 逻辑卷管理器 (LVM) 中的卷组信息 返回一个字典结构,包含所有VG的详细信息

二、 内置变量 (Magic Variables)

这些变量由Ansible自动提供,无需收集,主要用于获取清单(Inventory)信息。

变量名 描述 示例/用途
groups 一个包含所有清单分组及其主机列表的字典。 groups['web'] 返回 [web1, web2]
groups.all 一个列表,包含所有清单中的主机。 groups.all 返回 [node1, node2, web1, db1]
group_names 当前正在执行任务的主机所属的组名列表。 在Playbook中用于条件判断: when: "'db' in group_names"
inventory_hostname 当前正在执行任务的主机在Ansible清单中定义的名字 可能不同于 ansible_hostname(系统实际主机名),特别是当你使用了别名时。
相关推荐
tyatyatya1 天前
Ansible自动化配置,从入门到实战
运维·自动化·ansible
課代表2 天前
Python 数据可视化:从单变量到多变量
开发语言·python·信息可视化·数据分析·变量·时间序列·文本分析
lbb 小魔仙2 天前
【Linux】Ansible 自动化运维实战:2000+ 节点配置标准化教程
linux·运维·ansible
扑火的小飞蛾5 天前
【Ansible学习笔记01】 批量执行 shell 命令
笔记·学习·ansible
oMcLin5 天前
如何在 Red Hat Linux 服务器上使用 Ansible 自动化部署并管理多节点 Hadoop 集群?
linux·服务器·ansible
linux修理工8 天前
vagrant ubuntu 22.04 ansible 配置
ubuntu·ansible·vagrant
biubiubiu07069 天前
Ansible自动化
运维·自动化·ansible
秋42710 天前
ansible配置与模块介绍
ansible
秋42710 天前
ansible剧本
linux·服务器·ansible
码农101号11 天前
Ansible - Role介绍 和 使用playbook部署wordPress
android·ansible