1. 变量
Ansible利用变量存储可重复使用的值,可以简化项目的创建和维护,减少错误数量。
1.1 变量名称
由字符串组成,必须以字母开头,并且只能含有字母、数字和下划线,和其它编程语言很类似。
1.2 常见变量
- 要创建的用户
- 要安装的软件包
- 要重新启动的服务
- 要删除的⽂件
- 要从互联网检索的存档
1.3 定义变量
在不同位置定义变量具有不同的优先级,优先级规则是:越具体越优先,就近优先(离 task 越近,优先级越高)。

以下是一些常见定义位置的示例(优先级从低到高):
- 在清单中定义的组变量
bash
[webservers] # 主机组
web1.example.com # 主机1
web2.example.com # 主机2
[webservers:vars] # 组变量
nginx_port=8080
package_name=nginx
- 在清单或 playbook 所在目录的 group_vars 子目录中定义的组变量
- 在清单中定义的主机变量
bash
# 清单定义的主机变量 http_port
[webservers]
web1.example.com http_port=80
web2.example.com http_port=8080
- 在清单或 playbook 所在目录的 host_vars 子目录中定义的主机变量
- 在运行时中发现的主机事实(由 setup 模块自动收集)
- playbook 中的 play 变量 (vars 关键字和 vars_files 指令)
bash
# var 关键字(内联定义)
---
- hosts: localhost
vars:
app_name: "my_application"
app_port: 8080
tasks:
- debug:
msg: "Deploying {{ app_name }} on port {{ app_port }}"
# vars_files 指令 (从外部文件加载)
---
- hosts: localhost
vars_files:
- vars/settings.yml # 加载外部变量文件
tasks:
- debug:
msg: "Deploying {{ app_name }} on port {{ app_port }}"
# vars/settings.yml
---
app_name: "my_application"
app_port: 8080
- 任务变量
- 在命令行中定义的额外变量,使用 --extra-vars 或 -e 选项定义(优先级最高)
bash
# 此处仅为示例 xxx.yaml 和 varname=var 需替换为真实的
ansible-navigator run xxx.yaml -e "varname=var"
# 示例
# 单个变量
ansible-playbook deploy.yml -e "package_to_install=apache2"
# 列表
ansible-playbook deploy.yml -e '{"packages_to_remove": ["old_app1", "old_app2"]}'
# 变量文件(需创建一个临时变量文件 vars_file.yml)
ansible-playbook deploy.yml -e "@vars_file.yml"
建议选择全局唯一的变量名称。如果不同级别有相同名称的变量,优先级高的变量会覆盖优先级低的。
1.4 清单变量
分类:主机变量 (用于特定主机),组变量,前者优先级高。
定义方法:
1)在清单文件中定义。
2)在与 playbook 相同的工作目录中创建 group_vars (存放组变量文件)和 host_vars(存放主机变量文件)两个目录。
推荐使用 group_vars 和 host_vars 目录来管理变量,而不是写在清单文件中。
示例的项目架构:
bash
my_ansible_project/
├── inventory.ini
├── host_vars/
│ └── web1.example.com.yml
├── group_vars/
│ └── webservers.yml
└── site.yml
对应的项目文件:
文件 group_vars/webservers.yml 内容
bash
---
# 适用于所有 webservers 组主机的变量
firewall_package: ufw
common_packages:
- vim
- git
- htop
文件 host_vars/web1.example.com.yml 内容
bash
---
# 仅适用于 web1.example.com 的特定变量
host_specific_setting: "This is only for web1"
nginx_sites_enabled:
- host1.example.com
- admin.example.com
1.5 使用字典定义变量
Ansible的模块也是采用的字典,有层级关系,更直观。以定义用户信息为例:
bash
# 扁平化变量(难以管理)
# 注意变量名不要重复
user_alice_name: alice
user_alice_uid: 1234
user_alice_groups: developers
user_alice_home: /home/alice
user_bob_name: bob
user_bob_uid: 1235
user_bob_groups: bob
user_bob_home: /home/bob
# 使用字典变量(推荐)
users:
alice:
name: alice
uid: 1234
groups: developers
home: /home/alice
bob:
name: bob
uid: 1235
groups: bob
home: /home/bob
使用方法
对于上一示例,想要访问 alice 的 uid可采用以下两种方式:
bash
# 等价的
users.alice.uid
users['alice']['uid'] # Python语法
尽管两种都有效,但是建议Ansible项目的所有文件采用一致的一种语法。
1.6 变量使用
将变量名称放在双花括号**{{ 变量名称 }}**中,任务执行时,Ansible 会将其替换为对应的值。
注意:变量名称和双花括号之间有空格。
强烈建议 :使用引号,如"{{ 变量名称 }}",防止 Ansible 当作YAML字典处理。
1.7 捕获命令输出
使用 register关键字将一个任务的输出捕获到一个变量中。这个变量是一个复杂的字典,包含了命令执行的结果、标准输出、标准错误和返回码等。
bash
- name: register_test
hosts: localhost
tasks:
- name: check file
ansible.builtin.command: ls /etc/hostname
register: file_check
2. Vault
对于配置远程服务器需要访问的密码或 API 密钥等敏感数据 ,如果以纯文本形式存储在变量清单或其它 Ansible 文件中,安全风险极高。推荐使用随 Ansible 提供的Ansible Vault ,它可以加密和解密任何由Ansible使用的结构化数据文件,通过 ansible-vault 命令行工具创建、编辑、加密、解密和查看文件。
可类比 K8s 的ConfigMap (存放非机密信息)和 Secret(存放机密信息)。
Vault 使用 AES256 对称加密算法来保护文件,加密和解密都使用同一个密码(Vault密码)作为密钥。
2.1 使用方法
2.1.1 创建加密文件
默认使用编辑器 vi 打开文件
bash
ansible-vault create filename.yml
2.1.2 查看加密文件
bash
ansible-vault view filename.yml
2.1.3 编辑加密文件
bash
ansible-vault edit filename.yml
2.1.4 加密现有文件
使用 --output=OUTPUT_FILE 选项,可将加密文件保存为新的名称。
bash
ansible-vault encrypt filename.yml
2.1.5 解密现有文件
解密单个文件时,可使用 --output 选项以其他名称保存解密的文件。
bash
ansible-vault decrypt filename.yml
2.1.6 更改加密文件密码
使用 ansible-vault rekey filename 命令更改加密文件的密码。执行后,它会先要求输入当前密码,然后提示输入新密码,也可以使用 --new-vault-password-file 选项直接指定包含新密码的文件。
bash
ansible-vault rekey filename.yml
ansible-vault rekey --new-vault-password-file=new_password.txt filename.yml
2.2 运行 Vault 加密的文件的 playbook
需要向 ansible-playbook 命令提供其加密密码,有以下三种方式:
1)交互方式,根据提示输入密码(需要禁用 artifact 工件,具体原因后期介绍工件时解释)
bash
ansible-navigator run -m stdout \
--playbook-artifact-enable false filename.yml \
--vault-id @prompt
2)指定 Vault 密码文件(最安全)
密码必须在该文件中存储为一行字符串。
bash
ansible-navigator run -m stdout filename.yml \
--vault-password-file=vault-pw-file
建议:设置密码文件的权限为 600,确保只有所有者可读;
将密码文件存储在安全的位置,不要纳入版本控制系统。
3)使用 $ANSIBLE_VAULT_PASSWORD_FILE 环境变量
bash
# 设置环境变量
export ANSIBLE_VAULT_PASSWORD_FILE=~/path/to/vault-password-file
# 运行 playbook(无需额外指定密码文件参数)
ansible-navigator run -m stdout filename.yml
补充:可以通过 ansible-navigator 使用多个 Ansible Vault 密码,将多个 --vault id 或 --vault-password-file 选项传递给 ansible-navigator 命令。
3. Facts(事实)
Ansible 事实是 Ansible 从受管节点自动探查到的变量,由 ansible.builtin.setup 模块调取,其中包含的信息存储到可重复使用的变量中。
以下仅列举部分(使用 Python 语法表述字典),根据变量名称也可大致知道表述的内容。
事实描述 | 变量 |
---|---|
短主机名称 | ansible_facts['hostname'] |
完全限定的域名 | ansible_facts['fqdn'] |
主要 IPv4 地址(基于路由) | ansible_facts['default_ipv4']['address'] |
所有网络接口的名称列表 | ansible_facts['interfaces'] |
特定网络接口的详细信息(eth0) | ansible_facts['interfaces']['eth0'] |
网络接口的 IP 地址配置 | ansible_facts['interfaces']['eth0']['ipv4']['address'] |
磁盘分区的大小(/dev/vda1) | ansible_facts['devices']['vda']['partitions']['vda1']['size'] |
DNS 服务器列表 | ansible_facts['dns']['nameservers'] |
当前运行的内核版本 | ansible_facts['kernel'] |
操作系统版本 | ansible_facts['distribution_version'] |
总内存大小(MB) | ansible_facts['memtotal_mb'] |
可用内存大小(MB) | ansible_facts['memfree_mb'] |
【提问】Linux 中使用什么命令查看磁盘的使用情况?
答:df命令
对于大型的集群系统,在执行play,task之前,需要先知道受管节点的配置情况(收集事实),软硬件环境和配置情况会通过变量引用成为代码的一部分。
3.1 查看事实
运行一个收集事实并使用ansible.builtin.debug 模块显示,以下示例会显示事实的全部内容。只需要特定信息时,只选择特定变量即可。
bash
# fact_test.yml
---
- name: Fact dump
hosts: all
# gather_facts: true # 默认为true
tasks:
- name: Print all facts
ansible.builtin.debug:
var: ansible_facts
bash
# 运行该playbook
ansible-navigator run -m stdout fact_test.yml
# 内容会很多

3.2 关闭事实
为 play 禁用事实收集,将gather_facts 关键字设置为 no。可以加快 playbook 的运行速度,或者在受控节点不支持 setup 模块时使用。
即使在 play 设置 gather_facts 为 no 的情况下,任务仍可以通过设置 ansible.builtin.setup 模块手动收集事实。
bash
---
- name: Play with manual fact gathering
hosts: all
gather_facts: no # 关闭自动收集
tasks:
- name: Manually collect only disk facts
ansible.builtin.setup: # 设置 ansible.builtin.setup 模块
gather_subset:
- network

3.3 事实子集
模块默认收集全部事实,但可以通过配置仅收集事实的子集。子集的具体内容可以参考 Ansible 官方文档或使用 ansible-doc setup 命令查看。
bash
---
- name: Various fact gathering examples
hosts: all
tasks:
- name: Collect all facts (default behavior)
ansible.builtin.setup:
gather_subset:
- all
- name: Collect network-related facts
ansible.builtin.setup:
gather_subset:
- network
- name: Collect hardware and network facts
ansible.builtin.setup:
gather_subset:
- hardware
- network
- name: Collect all facts except network
ansible.builtin.setup:
gather_subset:
- "!network"
- name: Collect minimal fact set
ansible.builtin.setup:
gather_subset:
- min

3.3 自定义事实
管理员可以使用自定义事实定义受管主机的特定值。自定义事实存储在受管节点的本地文件中。
自定义事实可以在 INI 或 JSON 格式(效率高,语法麻烦)的文件中静态定义 ,也可以通过可执行脚本在运行时动态生成。
ansible.builtin.setup 模块会自动从受管节点的 /etc/ansible/facts.d 目录中收集自定义事实,文件的扩展名必须为 .fact。
注意: 自定义事实不支持 YAML 格式。
4. 魔法变量
有些变量不由 ansible.builtin.setup 模块收集,但有用,此时就需要魔法变量,它是一种特殊的变量,可以获取与特定受管主机相关的信息。
使用场景:在一个任务中需要访问其他受管主机的信息。
常用魔法变量
变量名称 | 描述 |
---|---|
hostvars | 包含所有受管主机的非事实变量 |
hostvars[inventory_hostname] | 当前主机的所有变量(包括事实和自定义变量) |
group_names | 列出当前受管主机所属的所有组 |
groups | 列出 inventory 中所有组和对应的主机 |
inventory_hostname | 在 inventory 中定义的主机名(可能与事实主机名不同) |
如有问题或建议,欢迎在评论区中留言~