- 运维
- 配置管理
- 后端
【免费下载链接】salt
Software to automate the management and configuration of infrastructure and applications at scale.
导读
saltutil是 SaltStack(本仓库 salt/modules/saltutil.py)中负责"管理 Salt 自身"的执行模块:从文件服务器同步自定义模块、刷新 minion 的 pillar/grains/beacons、查询与终止正在运行的作业、清理缓存、重建密钥,甚至允许运行在 master 上的 minion 反向调用 runner、wheel 和 salt 命令。本文基于官方 API 参考文档 doc/ref/modules/all/salt.modules.saltutil.rst(该文档通过automodule指令完整渲染本模块的全部函数签名与文档字符串),逐类讲解其全部功能、参数语义与底层实现,帮助你掌握用一条salt命令远程治理 minion 自身的完整能力。
说明:
saltutil全部函数都在 minion 侧执行(部分函数要求该 minion 位于 master 之上),通常通过salt '<target>' saltutil.<function>调用,也可在 minion 本机用salt-call saltutil.<function>调用。模块声明了__proxyenabled__ = ["*"](salt/modules/saltutil.py),因此也适用于所有 proxy minion。
一、自定义扩展模块同步体系:sync_*家族
Salt 允许用户在文件服务器的_modules、_states、_grains等特殊目录中放置自定义扩展模块,saltutil.sync_*系列函数负责把这些模块从 master 的文件服务器同步到 minion 的扩展模块目录,并(默认)触发对应的刷新动作。该文档以 doc/ref/modules/all/salt.modules.saltutil.rst 为入口,完整列出了所有同步函数。
1.1 同步函数总览
| 函数 | 同步源目录 | 默认 refresh 动作 | 引入版本 |
|---|---|---|---|
sync_modules | salt://_modules | 刷新执行模块 | 0.10.0 |
sync_states | salt://_states | 刷新执行模块 | 0.10.0 |
sync_grains | salt://_grains | 刷新 pillar(间接刷新模块) | 0.10.0 |
sync_renderers | salt://_renderers | 刷新执行模块 | 0.10.0 |
sync_returners | salt://_returners | 刷新执行模块 | 0.10.0 |
sync_utils | salt://_utils | 刷新执行模块 | 2014.7.0 |
sync_beacons | salt://_beacons | 刷新 beacons | 2015.5.1 |
sync_log_handlers | salt://_log_handlers | 刷新执行模块 | 2015.8.0 |
sync_pillar | salt://_pillar | 刷新 pillar(仅 masterless minion) | 2015.8.11, 2016.3.2 |
sync_sdb | salt://_sdb | 无(不触发刷新) | 2015.5.8, 2015.8.3 |
sync_proxymodules | salt://_proxy | 刷新执行模块 | 2015.8.2 |
sync_engines | salt://_engines | 刷新执行模块 | 2016.3.0 |
sync_clouds | salt://_cloud | 刷新执行模块 | 2017.7.0 |
sync_thorium | salt://_thorium | 刷新执行模块 | 2018.3.0 |
sync_matchers | salt://_matchers | 刷新执行模块 | 2019.2.0 |
sync_serializers | salt://_serializers | 刷新执行模块 | 2019.2.0 |
sync_executors | salt://_executors | 刷新执行模块 | 3000 |
sync_tops | salt://_tops | 刷新环境缓存(仅 masterless minion) | 3007.0 |
sync_wrapper | salt://_wrapper | 刷新执行模块(仅 masterless minion) | 3007.0 |
sync_output(别名sync_outputters) | salt://_output | 刷新执行模块 | — |
sync_resources | salt://_resources | 触发资源重新发现 | — |
1.2 统一参数语义
绝大多数sync_*函数共享同一组参数(以文档字符串为准):
saltenv:文件服务器环境(fileserver environment)。传逗号分隔列表可同步多个环境,例如saltenv=base,dev。若不传,则会读取 top file 中配置的所有环境;如果没有 top file,则默认同步base环境。这一逻辑由模块内的_get_top_file_envs()实现(salt/modules/saltutil.py):它实例化salt.state.HighState读取 top file,并将结果缓存在上下文键saltutil._top_file_envs(源码常量TOP_ENVS_CKEY)中以避免重复解析;若渲染 top file 失败会抛出CommandExecutionError。refresh(默认True):同步完成后是否刷新对应资源。文档明确说明:即使没有新模块被同步,也会执行刷新;设False可跳过。例如sync_modules的 refresh 会调用refresh_modules(),sync_grains的 refresh 会调用refresh_pillar()(因为 pillar 刷新内部会完成模块刷新)。extmod_whitelist/extmod_blacklist(默认None):逗号分隔的模块名单,按类型限定"只同步哪些"或"排除哪些"。对于sync_all,这两个参数则是字典形式,如extmod_whitelist={'modules': ['custom_module']}。clean_pillar_cache(默认False):sync_grains、sync_pillar、sync_all、refresh_grains独有,设为True时同时刷新 pillar 缓存。
1.3 底层同步机制
所有同步函数最终都汇聚到私有辅助函数_sync()(salt/modules/saltutil.py),它调用 salt/utils/extmods.py 中的salt.utils.extmods.sync()完成实际工作:
- 解析白名单/黑名单:字符串会被按逗号拆分,字典则按类型分别匹配;
- 通过
fileclient.cache_dir()从salt://_<form>下载文件到本地缓存,只匹配.py、.pyx、.so、.zip后缀; - 对比目标文件哈希(
hash_type,默认取自 opts),有变化才覆盖写入,并将form.relname追加到返回列表; - 若设置了
clean_dynamic_modules: True(minion 配置项),会递归清理扩展模块目录中已从文件服务器消失的文件与空目录,保持两侧严格一致; - 返回
(ret, touched):touched为真时,_sync会在cachedir/module_refresh下创建一个占位文件,作为"需要重载模块"的信号;同步 grains 时还会清除磁盘上的grains.cache.p(见_clear_grains_cache(),salt/modules/saltutil.py),防止grains_cache开启时读到过期数据(对应 tests/pytests/functional/modules/test_saltutil.py 中针对 issue #55667 的回归测试)。
1.4 特别注意事项
- masterless 限制:
sync_pillar、sync_tops、sync_wrapper在传统(非 masterless)minion 上执行会直接抛出CommandExecutionError,因为__opts__["file_client"] != "local"。其中sync_tops在refresh=True时还会先清除TOP_ENVS_CKEY缓存,再同步salt://_tops。 - state 中调用必须带 refresh:文档特别强调,如果用
module.runstate 调用sync_modules/sync_all,由于 SLS 渲染已完成,新同步的模块在本次运行中不可见,必须显式传refresh: True:
load_my_custom_module: module.run: - name: saltutil.sync_modules - refresh: True1.5 一键同步全部:sync_all
sync_all在一个调用里按依赖顺序同步所有扩展模块类型(salt/modules/saltutil.py):masterless minion 先同步 tops(因为它可能影响后续同步的环境选择),随后依次同步 clouds、beacons、modules、states、sdb、grains、renderers、returners、output、utils、log_handlers、executors、proxymodules、engines、thorium、serializers、matchers、resources;masterless minion 再追加 pillar 与 wrapper。refresh=True时最后统一执行一次refresh_pillar()(内部已完成模块刷新,避免重复刷新)。返回的字典以类型为键、以各自同步结果为值。
salt '*' saltutil.sync_all salt '*' saltutil.sync_all saltenv=dev salt '*' saltutil.sync_all saltenv=base,dev salt '*' saltutil.sync_all extmod_whitelist={'modules': ['custom_module']}1.6 查看已同步的扩展模块:list_extmods
list_extmods遍历cachedir/extmods目录,按模块类型分组列出所有已同步到本 minion 的外部模块名(文件去扩展名),便于核对哪些扩展确实已落地:
salt '*' saltutil.list_extmods二、运行时资源刷新:refresh_*家族
刷新类函数不涉及文件传输,而是向 minion 自身的事件总线发送事件,让 minion 内部重新加载对应数据。
2.1refresh_modules(异步与同步两种模式)
向 minion 发送module_refresh事件以重载执行模块与 grains。默认异步:salt '*' saltutil.refresh_modules立即返回。如需阻塞等待刷新完成,传async=False——此时函数会先挂起一个事件监听器,再触发携带notify: True的刷新事件,并阻塞等待MINION_MOD_REFRESH_COMPLETE事件(超时 30 秒)后返回(salt/modules/saltutil.py)。
2.2refresh_pillar
发送pillar_refresh事件,刷新 minion 内存中的 pillar 数据(详见文档引用的 pillar-in-memory 机制):
wait(默认False):设为True时阻塞等待刷新完成;timeout(默认30):wait=True时最多等待的秒数;clean_cache(默认True,3005 版本新增):清理 pillar 缓存(仅在pillar_cache开启时生效)。
salt '*' saltutil.refresh_pillar salt '*' saltutil.refresh_pillar wait=True timeout=60注意:本模块同时用pillar_refresh = salt.utils.functools.alias_function(refresh_pillar, "pillar_refresh")导出了别名(salt/modules/saltutil.py),文档页通过:exclude-members: pillar_refresh将别名排除在 API 列表之外,避免重复展示,但两者完全等价、均可调用。
2.3refresh_grains
刷新 minion 的 grains,但不从salt://_grains同步新模块;文档提醒:该过程会顺带重载可用执行模块(因为 grains 可能影响模块是否可用)。参数:
refresh_pillar(默认True):设为False阻止 pillar 一并刷新;clean_pillar_cache(默认False):设为True刷新 pillar 缓存。
实现上先清除磁盘 grains 缓存再刷新(salt/modules/saltutil.py),这正是 tests/pytests/functional/modules/test_saltutil.py 所覆盖的 #55667 回归场景。
salt '*' saltutil.refresh_grains2.4refresh_beacons与refresh_matchers
分别发送beacons_refresh与matchers_refresh事件,让 minion 重新加载 beacon 配置与匹配器(matchers)定义。若事件模块不可用(如某些 proxy 场景),会记录错误并返回False,等效于 no-op:
salt '*' saltutil.refresh_beacons salt '*' saltutil.refresh_matchers2.5refresh_resources
触发resource_refresh事件,minion 收到后基于当前 pillar 数据重新执行_discover_resources(),并将发现的资源重新注册到 master 的minion_resources缓存中——适用于需要动态上报托管资源的场景(通常与sync_resources配合,后者同步salt://_resources自定义资源模块后自动触发一次该刷新):
salt '*' saltutil.refresh_resources三、作业(Job)管理与进程信号控制
3.1 查询运行状态
running:返回 minion 上所有正在运行的 Salt 进程数据(含 jid、fun、pid、tgt 等字段),底层委托 salt/utils/minion.py 的running()实现。is_running <fun>:参数支持glob 通配,返回匹配函数名的运行作业。例如salt '*' saltutil.is_running state.highstate可判断 highstate 是否正在执行。
3.2 定位单个作业
find_job <jid>:返回指定 jid 的运行中作业信息。文档给出了完整输出示例(含arg、fun、jid、pid、tgt、tgt_type、user字段);若作业已完成则返回空字典。从源码看(salt/modules/saltutil.py),它先扫描running(),随后还会检查cachedir下的state_queue与job_queue排队目录——队列文件按queued_<timestamp>_<jid>.p命名,命中后返回带queued: True、pid: 0的结构,避免把排队中作业误报为"不存在"。find_cached_job <jid>:返回已缓存的作业结果。前提是 minion 配置了cache_jobs: True;否则返回提示信息"Local jobs cache directory not found; you may need to enable cache_jobs on this minion"。数据从cachedir/minion_jobs/<jid>/return.p读取并反序列化。
3.3 信号与终止
signal_job <jid> <sig>:向作业进程发送任意信号(如15即 SIGTERM)。若安装了psutil,会递归向进程的所有子进程发送;否则仅发送给主进程及其记录的child_pids。当目标进程已不存在时,会清理cachedir/proc/<jid>残留文件并返回提示。未安装 psutil 时记录警告,仍尝试以os.kill发送。term_job <jid>:等价于signal_job <jid> SIGTERM(终止单个作业)。term_all_jobs:向所有正在运行的作业发送 SIGTERM。kill_job <jid>:发送 SIGKILL(9)。注意源码顶部兼容 Win32:salt_SIGKILL在平台不支持SIGKILL时回退为SIGTERM(salt/modules/saltutil.py)。kill_all_jobs:向所有运行作业发送 SIGKILL。
salt '*' saltutil.running salt '*' saltutil.is_running state.highstate salt '*' saltutil.find_job 20160503150049487736 salt '*' saltutil.term_job 20160503150049487736 salt '*' saltutil.kill_all_jobs四、缓存清理与密钥管理
4.1clear_cache
强制删除 minion 的所有缓存(遍历整个cachedir)。文档给出了明确的安全警告:最安全的清缓存方式是先停止 minion、删除缓存文件、再重启 minion。执行时若某个文件删除失败会立即返回False。该函数自 2014.7.0 引入。
4.2clear_job_cache
按时间阈值清理作业缓存目录cachedir/minion_jobs下超过指定小时数的子目录(目录 mtime 早于now - hours * 3600即被整目录删除),默认hours=24,自 2018.3.0 引入。适合在长期运行的 minion 上回收磁盘空间:
salt '*' saltutil.clear_cache salt '*' saltutil.clear_job_cache hours=124.3regen_keys与revoke_auth
regen_keys:删除pki_dir(通常为/etc/salt/pki/minion)下的所有密钥文件,随后重建与 master 的请求通道(ReqChannel)以强制重新生成 minion 密钥。典型用途是重命名/迁移 minion 或重置认证,执行后 minion 需重新在 master 上被接受。revoke_auth:minion 主动向 master 发送revoke_auth请求,让 master 撤销它自己的密钥。文档特别提醒:该命令执行后 minion 会话被吊销,可能无法把执行结果返回给 master。可选参数preserve_minion_cache(默认False):设为True时 master 保留该 minion 的缓存。实现会遍历master_uri_list(多 master 场景)逐个发送请求,任一通道超时则整体返回False。
salt '*' saltutil.regen_keys salt '*' saltutil.revoke_auth salt '*' saltutil.revoke_auth preserve_minion_cache=True五、Master 侧能力反调:runner、wheel、cmd与mmodule
这组函数允许运行在 master 之上的 minion(或在 master 上执行salt-call)反哺 master,把 master 侧能力以执行模块的形式暴露出来。
5.1runner <name>
在 master 上执行 runner 函数(自 2014.7.0 引入)。文档要求:必须通过"运行在 master 上的 minion"或"在 master 上执行 salt-call"来调用。支持arg、kwarg、full_return、saltenv(默认base)、jid等参数;runner 函数若接受saltenv参数会自动注入;对state.orchestrate/state.orch/state.sls会注入orchestration_jid以衔接编排作业。
salt master_minion saltutil.runner jobs.list_jobs salt master_minion saltutil.runner test.arg arg="['baz']" kwarg="{'foo': 'bar'}"5.2wheel <name> [args]
在 master 上执行 wheel 模块函数(自 2014.7.0 引入),要求目标 minion与 master 位于同一主机。文档明确指出:若对非本机 minion 调用,将得到"空"返回——远程 minion 无法访问 wheel 函数及其返回数据。
salt my-local-minion saltutil.wheel key.accept jerry salt my-local-minion saltutil.wheel minions.connected5.3 权限对齐细节(源码级补充)
从源码看,runner/wheel在 minion 进程内执行 master 侧函数,而自 3006 起 master 默认以salt用户运行(见_master_user_runas注释中的 issue #67716)。为让 master 侧函数(如 git_pillar/gitfs 缓存、pki 目录访问)以 master 配置用户而非 root 执行,模块实现了完整的降权运行链路(salt/modules/saltutil.py):
_master_user_runas()校验opts["user"]是否为真实账号——因为state.orchestrate会把发布用户(如sudo_<login>)写入__opts__['user'],这类"伪用户"会被pwd.getpwnam校验拦截并跳过降权(issue #69600);_client_cmd_as()用fork上下文创建子进程,在子进程中执行chugid降权,并通过队列回传结果;子进程刻意不守护化(daemon 进程不允许再派生子进程,会影响编排中的parallel: True状态);父进程同时监听结果队列与子进程存活,子进程异常退出(os._exit、OOM、libgit2 段错误)时抛出CommandExecutionError而非永久阻塞;_align_runas_environment()在降权后修正HOME/USER/LOGNAME,并刷新 libgit2/pygit2 的全局配置搜索路径,避免 gitfs/git_pillar 读取到 root 的/root/.gitconfig而出错。
5.4cmd与cmd_iter
假设当前 minion 同时也是 master,执行一条完整的 salt 命令并聚合所有目标 minion 的返回。参数包括tgt、fun、arg(元组)、timeout、tgt_type(目标匹配类型,默认glob;2017.7.0 起由expr_form更名而来)、ret(returner)、kwarg、ssh(是否走 salt-ssh),另支持batch与subset模式(源码_exec分别切换到client.cmd_batch与client.cmd_subset)。cmd_iter以生成器逐批产出返回,适合流式处理。cmd在返回为空且配置文件为 minion 时,还会尝试读取同目录的master配置重试一次。
5.5mmodule <saltenv> <fun>
加载指定环境下的 minion 模块,使该环境的 pillar 在渲染时能使用其自定义_modules中的函数。实现依赖单例类_MMinion(salt/modules/saltutil.py):按saltenv缓存MasterMinion实例,构建时将file_roots中该环境的_modules目录注入module_dirs并重新生成模块,同时保存/恢复全局__grains__保证调用上下文仍是 minion 视角:
salt '*' saltutil.mmodule base test.ping六、minion 自升级:update
update从opts['update_url']更新 minion 自身(文档示例指向 Broadcom 提供的官方构建源https://packages.broadcom.com/artifactory/saltproject-generic/windows/)。前提与限制(源码可印证,salt/modules/saltutil.py):
- 依赖
eskyPython 模块(模块头声明:depends: - esky,未安装则返回"Esky not available as import"); - minion 必须运行bdist_esky 构建(否则返回
"Minion is not running an Esky build"); - 必须配置
update_url; - 版本号可选,缺省时通过
app.find_update()查找最新版;文档提醒 2014-8-11 起 esky 存在缺陷:只能下载安装 update_url 中的最新版本; - 更新完成后按
update_restart_services配置逐个service.restart重启服务,并返回Updated from <旧版本> to <新版本>及重启结果。
salt '*' saltutil.update salt '*' saltutil.update 0.10.3七、实战场景速查
- 发布新自定义模块:
salt '*' saltutil.sync_all一键同步所有扩展类型;只同步执行模块用salt '*' saltutil.sync_modules,指定环境saltenv=dev,多环境saltenv=base,dev。 - 自定义模块只改了一行:不想同步时仅重载——
salt '*' saltutil.refresh_modules;同步并刷新——salt '*' saltutil.sync_utils。 - 修改了 pillar 数据:
salt '*' saltutil.refresh_pillar;需要同步_pillar自定义模块(masterless minion)——salt '*' saltutil.sync_pillar。 - 业务代码临时变更 grains:
salt '*' saltutil.refresh_grains refresh_pillar=False只刷 grains 不动 pillar。 - highstate 卡住排查:
salt '*' saltutil.is_running 'state.*'定位;确认 jid 后salt '*' saltutil.term_job <jid>;紧急情况salt '*' saltutil.kill_all_jobs。 - minion 证书过期/更换:
salt '*' saltutil.regen_keys,随后在 master 重新salt-key -a。 - master 侧运维操作:在 master 本机
salt-call saltutil.runner jobs.list_jobs或salt my-local-minion saltutil.wheel key.list_all。 - 长期运行 minion 磁盘回收:
salt '*' saltutil.clear_job_cache hours=24;彻底清理salt '*' saltutil.clear_cache(先停 minion 更安全)。
八、延伸阅读
- 模块完整源码:salt/modules/saltutil.py
- 底层文件同步实现:salt/utils/extmods.py
- 官方 API 文档页:doc/ref/modules/all/salt.modules.saltutil.rst
- 功能级测试(含 grains 缓存回归):tests/pytests/functional/modules/test_saltutil.py
- 与模块加载机制相关的集成测试:tests/integration/loader/test_ext_modules.py
- 运维
- 配置管理
- 后端
【免费下载链接】salt
Software to automate the management and configuration of infrastructure and applications at scale.
相关推荐
Sway 如何用 [test(should_revert)] 编写预期回滚的单元测试?
Sway 如何用 test should_revert 编写预期回滚的单元测试? 在 Sway 中给"本应失败"的代码路径写单元测试时(断言应当不成立、合约调用
运维配置管理后端Salt 执行模块 gpg 完全指南:密钥链管理、加密签名与信任模型实战
Salt 执行模块 gpg 完全指南:密钥链管理、加密签名与信任模型实战 本文围绕 Salt 的 gpg 执行模块( salt/modules/gpg.py h
运维配置管理后端Salt macOS keychain 模块实战指南:用 Salt 管理 macOS 钥匙串中的证书
Salt macOS keychain 模块实战指南:用 Salt 管理 macOS 钥匙串中的证书 Salt 的 keychain 执行模块( salt/mo
运维配置管理后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考