pillar 是 salt 中唯一推荐用于分发敏感配置数据的机制,它天然隔离、可加密、按 minion id 精确匹配,但必须配合 saltutil.refresh_pillar 才能生效,且绝不能把密码写进 grains。

直接结论:Pillar 是 Salt 中唯一推荐用于分发敏感配置数据的机制,它天然隔离、可加密、按 Minion ID 精确匹配,但必须配合 saltutil.refresh_pillar 才能生效,且绝不能把密码写进 Grains。
为什么 Pillar 能安全分发敏感数据
Pillar 数据在 Master 端编译,每个 Minion 只能拿到自己被 top.sls 匹配到的那一部分;传输过程使用独立加密 session(不同于 state 通信),即使网络被监听也无法解密原始内容;更重要的是,Minion 无权修改自己的 Pillar —— 它只能读,且读到的内容由 Master 全权控制。
对比 Grains 就很危险:grains.setval、/etc/salt/grains 文件、甚至 minion 配置里都能随意改 Grains 值,任何有本地权限的用户都能伪造或泄露敏感字段。官方文档明确警告:Grains 不适合存密码或密钥。
如何定义并刷新一个基础 Pillar
核心三步:配置目录 → 编写 SLS → 刷新生效。不重启 master,也不依赖 minion 配置。
-
pillar_roots必须在/etc/salt/master中声明,例如:pillar_roots: base: - /srv/pillar -
/srv/pillar/top.sls决定谁用什么数据:base: 'web01.example.com': - secrets.db -
/srv/pillar/secrets.db.sls存真实敏感值(YAML 格式):database: user: app_user password: 's3cr3t!2026'
- 执行刷新命令才能让 Minion 看到新值:
salt 'web01.example.com' saltutil.refresh_pillar - 验证是否生效:
salt 'web01.example.com' pillar.get database:password(返回s3cr3t!2026)
如何避免常见 Pillar 失效问题
最常踩的坑不是写错 YAML,而是忽略 Pillar 的“惰性加载”特性:不手动刷新,pillar.items 看起来是新的,但 pillar.get 或 state 渲染时仍用旧缓存。
- 修改
top.sls或任意 .sls 后,必须运行saltutil.refresh_pillar,saltutil.sync_all不起作用 - 如果用了
pillar_opts: True,Master 配置会自动注入到 Pillar 的master键下,容易和自定义 key 冲突,调试时建议先关掉 - 路径中含
__env__(如/srv/__env__/pillar)只在 Pillar 编译期替换为实际pillarenv,若没设pillarenv参数,默认还是base,别误以为会自动识别环境名 - 使用
extra_minion_data_in_pillar模块时,include: *在某些 YAML 解析器里会被当成锚点报错,稳妥写法是include: none或显式列出键名
生产环境必须考虑的加密与隔离
纯明文 Pillar 在多人协作或 Git 管理时风险极高。Salt 原生支持 GPG 加密,但关键点在于:加密只对 Pillar 生效,且必须在 Master 端解密 —— 这意味着 GPG 密钥不能放在 minion 上,也不能用 minion 的公钥加密。
典型做法是:
- 用 Master 的 GPG 私钥加密敏感字段,例如:
gpg --encrypt --recipient 'salt-master@company.com' --armor secrets.db.sls
- 在
/etc/salt/master开启解密:decrypt_pillar: True decrypt_pillar_default: gpg decrypt_pillar_renderers: - gpg
- 确保
gpg命令可用,且 Master 的 GPG keyring 中有对应私钥(gpg --list-secret-keys可查)
更复杂的场景(比如不同业务线各自管理密钥)需要结合外部 Pillar(ext_pillar)或 SDB,但那已超出 Pillar 本体范畴 —— Pillar 的定位始终是“安全通道”,不是“密钥管理系统”。











