Salt 核心运维模块 saltutil 全解:同步、刷新、作业管理与密钥治理实战指南
2026/9/23 18:06:17 网站建设 项目流程
  • 运维
  • 配置管理
  • 后端

【免费下载链接】salt

Software to automate the management and configuration of infrastructure and applications at scale.

项目地址:https://gitcode.com/gh_mirrors/sa/salt
点击查看免费下载

导读

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_modulessalt://_modules刷新执行模块0.10.0
sync_statessalt://_states刷新执行模块0.10.0
sync_grainssalt://_grains刷新 pillar(间接刷新模块)0.10.0
sync_rendererssalt://_renderers刷新执行模块0.10.0
sync_returnerssalt://_returners刷新执行模块0.10.0
sync_utilssalt://_utils刷新执行模块2014.7.0
sync_beaconssalt://_beacons刷新 beacons2015.5.1
sync_log_handlerssalt://_log_handlers刷新执行模块2015.8.0
sync_pillarsalt://_pillar刷新 pillar(仅 masterless minion)2015.8.11, 2016.3.2
sync_sdbsalt://_sdb无(不触发刷新)2015.5.8, 2015.8.3
sync_proxymodulessalt://_proxy刷新执行模块2015.8.2
sync_enginessalt://_engines刷新执行模块2016.3.0
sync_cloudssalt://_cloud刷新执行模块2017.7.0
sync_thoriumsalt://_thorium刷新执行模块2018.3.0
sync_matcherssalt://_matchers刷新执行模块2019.2.0
sync_serializerssalt://_serializers刷新执行模块2019.2.0
sync_executorssalt://_executors刷新执行模块3000
sync_topssalt://_tops刷新环境缓存(仅 masterless minion)3007.0
sync_wrappersalt://_wrapper刷新执行模块(仅 masterless minion)3007.0
sync_output(别名sync_outputterssalt://_output刷新执行模块
sync_resourcessalt://_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(默认Falsesync_grainssync_pillarsync_allrefresh_grains独有,设为True时同时刷新 pillar 缓存。

1.3 底层同步机制

所有同步函数最终都汇聚到私有辅助函数_sync()(salt/modules/saltutil.py),它调用 salt/utils/extmods.py 中的salt.utils.extmods.sync()完成实际工作:

  1. 解析白名单/黑名单:字符串会被按逗号拆分,字典则按类型分别匹配;
  2. 通过fileclient.cache_dir()salt://_<form>下载文件到本地缓存,只匹配.py.pyx.so.zip后缀;
  3. 对比目标文件哈希(hash_type,默认取自 opts),有变化才覆盖写入,并将form.relname追加到返回列表;
  4. 若设置了clean_dynamic_modules: True(minion 配置项),会递归清理扩展模块目录中已从文件服务器消失的文件与空目录,保持两侧严格一致;
  5. 返回(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_pillarsync_topssync_wrapper在传统(非 masterless)minion 上执行会直接抛出CommandExecutionError,因为__opts__["file_client"] != "local"。其中sync_topsrefresh=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: True

1.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_grains

2.4refresh_beaconsrefresh_matchers

分别发送beacons_refreshmatchers_refresh事件,让 minion 重新加载 beacon 配置与匹配器(matchers)定义。若事件模块不可用(如某些 proxy 场景),会记录错误并返回False,等效于 no-op:

salt '*' saltutil.refresh_beacons salt '*' saltutil.refresh_matchers

2.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 的运行中作业信息。文档给出了完整输出示例(含argfunjidpidtgttgt_typeuser字段);若作业已完成则返回空字典。从源码看(salt/modules/saltutil.py),它先扫描running(),随后还会检查cachedir下的state_queuejob_queue排队目录——队列文件按queued_<timestamp>_<jid>.p命名,命中后返回带queued: Truepid: 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=12

4.3regen_keysrevoke_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 侧能力反调:runnerwheelcmdmmodule

这组函数允许运行在 master 之上的 minion(或在 master 上执行salt-call)反哺 master,把 master 侧能力以执行模块的形式暴露出来。

5.1runner <name>

在 master 上执行 runner 函数(自 2014.7.0 引入)。文档要求:必须通过"运行在 master 上的 minion"或"在 master 上执行 salt-call"来调用。支持argkwargfull_returnsaltenv(默认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.connected

5.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.4cmdcmd_iter

假设当前 minion 同时也是 master,执行一条完整的 salt 命令并聚合所有目标 minion 的返回。参数包括tgtfunarg(元组)、timeouttgt_type(目标匹配类型,默认glob;2017.7.0 起由expr_form更名而来)、ret(returner)、kwargssh(是否走 salt-ssh),另支持batchsubset模式(源码_exec分别切换到client.cmd_batchclient.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

updateopts['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

七、实战场景速查

  1. 发布新自定义模块salt '*' saltutil.sync_all一键同步所有扩展类型;只同步执行模块用salt '*' saltutil.sync_modules,指定环境saltenv=dev,多环境saltenv=base,dev
  2. 自定义模块只改了一行:不想同步时仅重载——salt '*' saltutil.refresh_modules;同步并刷新——salt '*' saltutil.sync_utils
  3. 修改了 pillar 数据salt '*' saltutil.refresh_pillar;需要同步_pillar自定义模块(masterless minion)——salt '*' saltutil.sync_pillar
  4. 业务代码临时变更 grainssalt '*' saltutil.refresh_grains refresh_pillar=False只刷 grains 不动 pillar。
  5. highstate 卡住排查salt '*' saltutil.is_running 'state.*'定位;确认 jid 后salt '*' saltutil.term_job <jid>;紧急情况salt '*' saltutil.kill_all_jobs
  6. minion 证书过期/更换salt '*' saltutil.regen_keys,随后在 master 重新salt-key -a
  7. master 侧运维操作:在 master 本机salt-call saltutil.runner jobs.list_jobssalt my-local-minion saltutil.wheel key.list_all
  8. 长期运行 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.

项目地址:https://gitcode.com/gh_mirrors/sa/salt
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询