一个很容易混淆的问题:
既然我可以用
vars_files直接加载 YAML 配置文件,把它变成 Ansible 变量,那为什么还要用from_yaml过滤器?这俩不是干的同一件事吗?
vars_files
vars_files 是 Ansible 提供的静态提前加载工具,它的作用非常明确:
在 Playbook 所有任务运行之前,把你控制节点本地的一个 YAML 文件,整个加载成 Ansible 变量。
举个最常见的例子,你本地提前写好了一个 nginx_vars.yml 配置文件:
# 你本地提前存在的配置文件
name: nginx
port: 8080
env: prod
然后你在 Playbook 的开头,用 vars_files 把它加载进来:
---
# 你的 Playbook
vars_files:
- nginx_vars.yml # 提前把这个本地文件加载进来
tasks:
- name: 输出配置
debug:
msg: "服务名是:{{ name }},端口是:{{ port }}"
所有任务都能直接用这个文件里的变量,因为在 Playbook 运行的最开始,这些变量就已经加载好了。
但它有两个非常明确的限制:
-
只能加载控制节点的本地文件:它读不了远程主机上的文件,也处理不了接口返回的字符串
-
必须提前存在:这个文件必须在 Playbook 运行之前就已经在你本地了,它处理不了运行时才拿到的动态内容
什么时候必须用 from_yaml
当你的 YAML 内容不是提前的本地文件 ,而是运行时才动态拿到的字符串 的时候,vars_files 就完全用不了了,这时候就必须用 from_yaml 过滤器。
简单来说,from_yaml 是一个动态解析工具:不管你的 YAML 内容是从哪来的,只要它是一段 YAML 格式的字符串,它就能把它解析成 Ansible 能直接用的变量。
场景 1:从配置中心拉动态配置
现在很多公司都用配置中心来统一管理应用配置,你需要调用接口来拉取配置,而不是提前把配置写到本地文件里。
tasks:
# 第一步:调用配置中心接口,拉取动态配置
- name: 从配置中心拉取 Nginx 配置
ansible.builtin.uri:
url: "https://config-center.example.com/api/get_config?app=nginx"
method: GET
register: api_response # 接口返回的内容,是一段 YAML 格式的字符串
# 这时候你没法用 vars_files!
# 因为这个 YAML 内容是任务运行到这一步才拿到的,不是你本地的文件
# 这时候你就需要用 from_yaml,把这个字符串解析成变量
- name: 解析接口返回的 YAML 配置
set_fact:
config: "{{ api_response.content | from_yaml }}"
# 现在你就能直接用配置里的字段了
- name: 输出解析后的配置
debug:
msg: "服务端口是:{{ config.port }},运行环境是:{{ config.env }}"
场景 2:读取远程主机的配置文件
如果你要读取远程受管主机 上的 YAML 配置文件,比如远程主机上有个 /opt/app/config.yml,你要解析它的内容来做后续判断,这时候 vars_files 也用不了,因为它只能读本地文件。
tasks:
# 第一步:把远程的文件读成字符串(slurp 模块会把文件转成 base64 编码)
- name: 读取远程主机的应用配置
ansible.builtin.slurp:
path: /opt/app/config.yml
register: remote_file
# 第二步:解码,然后用 from_yaml 解析成变量
- name: 解析远程的 YAML 配置
set_fact:
app_config: "{{ remote_file.content | b64decode | from_yaml }}"
# 现在你就能用远程配置里的字段了
- name: 判断应用环境
debug:
msg: "这是一台生产环境主机"
when: app_config.env == "prod"
Jinja2 过滤器
to_nice_json、to_nice_yaml 这些又是干嘛的
其实这些都是 Jinja2 的过滤器 ,你可以把它理解成 "数据加工工具":前面的变量是原材料,后面的过滤器是加工方法,用 | 把它们连起来,就能把原材料加工成你要的格式。
格式转换:把变量转成配置文件格式
最常用的就是格式转换类的过滤器,比如你要给程序生成一个 JSON 配置文件,或者给运维工具生成一个 YAML 配置,这时候就需要把 Ansible 的变量,转成对应的格式。
举个例子,你有一个 Ansible 的变量:
vars:
app_config:
name: nginx
port: 8080
env: prod
如果你用 to_nice_json 加工
最终会生成标准的、人类可读的 JSON 格式:
{{ app_config | to_nice_json }}
生成的内容就是:
{
"name": "nginx",
"port": 8080,
"env": "prod"
}
这就是 JSON 格式的样子,带大括号、双引号、缩进,所有程序都能直接读。
如果你用 to_nice_yaml 加工
最终会生成标准的 YAML 格式:
{{ app_config | to_nice_yaml }}
生成的内容就是:
name: nginx
port: 8080
env: prod
这就是 YAML 格式的样子,就是你平时写 Playbook 的那种格式,没有大括号,用冒号分隔,更简洁。
字符串解析:把文本转成变量
而from_yaml、from_json,就是反过来的加工:把一段 JSON/YAML 格式的文本,解析成 Ansible 能直接用的变量,这样你就能取里面的字段了。
最后总结:两个工具的核心区别
|--------------|-----------------|--------------------------|--------------------------|
| 工具 | 作用 | 适用场景 | 限制 |
| vars_files | 提前加载本地 YAML 文件 | 你提前就准备好本地配置文件的静态场景 | 只能加载本地提前存在的文件,无法处理动态内容 |
| from_yaml | 动态解析任意 YAML 字符串 | 运行时才拿到的动态内容:接口返回、远程文件读取等 | 没有限制,只要是 YAML 格式的字符串就能解析 |
这俩不是谁替代谁的关系,而是完全不同场景的互补工具:
-
如果你提前就有本地的配置文件,用
vars_files简单高效 -
如果你是运行时才拿到的动态 YAML 内容,用
from_yaml来解析