尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Salt 资源体系中的 SSH 状态执行:`salt.resources.ssh.modules.state` 模块深入解析

发布时间:2026/9/25 16:11:33

资讯中心
01
ARTICLE

Salt 资源体系中的 SSH 状态执行:`salt.resources.ssh.modules.state` 模块深入解析

Salt 资源体系中的 SSH 状态执行:`salt.resources.ssh.modules.state` 模块深入解析
运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载salt.resources.ssh.modules.state是 Salt 资源Resources子系统为ssh资源类型提供的状态模块覆盖层。它在管理 minion 进程内完整复刻 salt-ssh 的状态执行管线为通过 SSH 纳管的远程主机提供state.highstate、state.sls与state.apply三个状态入口。本文以 关联文档Sphinx autodoc 存根所指向的 模块源码 为骨架结合 ssh 资源模块、资源架构文档 与 单元测试讲清它的编译—打包—执行三段式管线、每个配置参数与 CLI 用法的含义以及它在 minion 侧运行的原理与边界条件。读完本文你将掌握如何在 Salt 资源模型下对 SSH 纳管主机应用状态并理解其底层调用链与容错设计。一、定位状态模块覆盖层与编译—打包—执行三段式管线salt/resources/ssh/modules/state.py是ssh资源类型的执行模块覆盖execution-module override模块头部的 docstring 明确给出了它的设计目标Implementsstate.highstate,state.sls, andstate.applyfor SSH resources by replicating the salt-ssh state-execution pipeline on the managing minion.它不做任何远程状态求值而是把 salt-ssh 在 master 上做的那套工作整体搬到管理 minion的进程里执行共分三个环节编译Compile通过管理 minion 的RemoteClient/FSClient从 master 读取 state 与 pillar 文件以SSHHighState完成 highstate 编译。资源 IDresource ID被用作 top-file 的匹配目标因此只有映射到该资源 ID 的 state 会被编译。打包Packageprep_trans_tar把编译出的 low state、所有被引用的salt://文件以及渲染后的 pillar 打包进一个传输 tar 包salt_state.tgz。执行Execute将 tar 通过 SCP 推送到远端主机的thin_dir再经由 salt-thin 束调用state.pkg远端以结构化 JSON 返回执行结果。这与 master 上直接执行salt-ssh state.highstate的效果一致区别在于发起者这里 salt-ssh 的发起者不是 master而是管理 minion 自身runs from the managing minions process so the salt-ssh initiator is the minion, not the master。从资源子系统全局看见 架构文档Salt 资源体系由三方构成master 持有 SRNSalt Resource Name形如type:id到管理 minion 的注册表管理 minion承载连接管线、每个资源的 grains 与 per-resource 执行/状态加载器——本模块正是管理 minion 侧针对ssh类型的状态加载器实现资源类型则是定义能对资源做什么操作的 Python 包。因此本模块的价值在于把远程主机抽象成一级资源让运维人员可以用统一的资源目标语法如Tssh:node1对其施加状态管理而无须关心底层是 proxy 还是 SSH 直连。为什么放在salt/resources/ssh/modules/目录下模块源码的注释解释了加载门控机制文件名必须是state.py与 slot 名一致目录位置salt/resources/ssh/modules/决定它只会在ssh 每资源加载器per-resource loader中被加载不会污染其他资源类型__func_alias__ {apply_: apply}保证apply_以apply的公开名字暴露因为apply是 Python 关键字无法直接作为函数名。__virtual__与资源接口ssh 资源类型本身在 salt/resources/ssh/init.py 中通过__virtual__()做门控仅当 minion 的PATH中存在ssh二进制时才加载if not salt.utils.path.which(ssh)。每个 ssh 资源对应一台可 SSH 访问的远端主机因为同类型资源共享同一个加载器一个管理 500 台 SSH 主机的 minion 只需要一个加载器而不是 500 个各自持有一对密钥的 proxy 进程——这是该设计在资源消耗上的显著收益。二、配置Pillar 声明主机与连接参数全表ssh 资源的声明位于管理 minion 的 Pillar 中默认顶层键为resources可通过 minion 配置项resource_pillar_key覆盖见 配置文档。ssh 资源模块 docstring 给出的标准声明如下resources: ssh: hosts: web-01: host: 192.168.1.10 user: root priv: /etc/salt/ssh_keys/web-01 web-02: host: 192.168.1.11 user: admin passwd: secretpassword no_host_keys: true其中ssh.hosts下的每个键就是一个资源 IDinit()salt/resources/ssh/init.py在资源类型加载时通过salt.utils.resources.pillar_resources_tree(opts)读取这些主机配置并缓存进__context__[ssh_resource]discover()则以这些键集合作为资源 ID 列表返回给 master 的资源注册表。每主机连接参数全表下表汇总了_connection_kwargs()state.py与_make_shell()中实际读取的字段及其默认值参数默认值说明host必填远端主机的主机名或 IP 地址userrootSSH 登录用户port22SSH 端口priv无SSH 私钥文件路径与passwd互斥但两者可同时指定一旦设置privSalt 优先使用基于密钥的选项串passwd无SSH 密码生产环境建议优先密钥认证priv_passwd无保护私钥的 passphrasesudoFalse是否通过 sudo 以 root 执行命令timeout30连接/60state 执行SSH 连接超时秒数_connection_kwargs中 state 路径默认60_make_shell中默认30ttyFalse是否强制分配 TTYidentities_onlyFalse传递-o IdentitiesOnlyyes阻止 SSH agent 提供无关密钥no_host_keysFalse完全禁用主机密钥校验同时设置StrictHostKeyCheckingno与UserKnownHostsFile/dev/nullignore_host_keysFalse仅传-o StrictHostKeyCheckingno不丢弃 known-hosts 数据库known_hosts_file无为该主机指定自定义known_hosts文件路径ssh_options无附加的-o KeyValue选项列表原样传给ssh二进制keepaliveTrue启用 TCP keepalivekeepalive_interval60ServerAliveInterval秒keepalive_count_max3ServerAliveCountMaxthin_dir自动生成远端 salt-thin 束的工作目录若配置则优先使用注意timeout在两处默认值不同——_make_shell用于ping/cmd_run等默认 30 秒而 state 执行路径的_connection_kwargs默认 60 秒。主机密钥策略与 SSH 版本的处理state 模块通过_target_opts()state.py构造一份适合SSHHighState与Single的 opts 副本关键处理包括把opts[id]设为资源 ID使 top file 能匹配到正确的目标主机从资源配置中注入no_host_keys、ignore_host_keys、known_hosts_file三项主机密钥策略注入_ssh_version优先取__context__[ssh_resource][_ssh_version]由init()预解析并缓存避免 job 线程中运行子进程否则调用salt.client.ssh.ssh_version()固定opts[relenv] True让状态执行走 relenvPython 运行时打包路径。三、核心函数highstate、sls 与 apply模块公开三个状态函数源码中均带 CLI 示例。state.highstate——对整个资源应用 highstatedef highstate(testNone, **kwargs):对目标 SSH 资源应用 highstate用资源 ID 作为 top-file 目标编译 highstate把 state 文件打包进传输 tarSCP 到远端并用 salt-thin 执行state.pkg。官方 CLI 示例salt -C Tssh:node1 state.highstate salt -C Tssh:node1 state.highstate testTrue流程细节state.py_target_opts()构造目标 opts_seed_thin_dir()把计算出的thin_dir写回 opts保证SSHHighState与prep_trans_tar使用一致的可写路径_get_initial_pillar()取管理 minion 已渲染的 pillar 作为initial_pillar传入SSHHighState——这能让State.__init__跳过_gather_pillar()否则会尝试为一个未知的 minion ID 编译 pillar产生虚假的 pillar 编译管理 minion 自身的 pillar 恰好已包含资源配置在with SSHHighState(...)上下文中调用st_.compile_low_chunks()编译 low chunksSSHHighState.__exit__会调用file_client.destroy()因此无需单独的 finally 清理遍历 chunks 时若发现非 dict 元素即错误列表直接返回若 chunks 为空top file 对资源 ID 无匹配直接返回一个与普通 minion No Top file 条目相同键格式的状态 dictresultFalse、comment 为No Top file or master_tops data matches found for resource id.从而在合并输出中干净地展示避免空返回导致展示异常——这一行为正是 单元测试TestHighstateEmptyChunks覆盖的场景用lowstate_file_refs()收集所有被引用文件叠加extra_filerefs_cleanup_slsmod_low_data()清理slsmod低数据prep_trans_tar()生成传输 tar最后调用_exec_state_pkg()执行远端状态。state.sls——对指定 SLS 文件应用状态def sls(mods, saltenvbase, testNone, **kwargs):对目标 SSH 资源应用一个或多个 SLS 文件。官方 CLI 示例salt -C Tssh:node1 state.sls node1 salt -C Tssh:node1 state.sls node1,common testTrue实现细节state.py若mods是字符串会先按逗号切分并去除空白mods [m.strip() for m in mods.split(,) if m.strip()]因此支持一次性指定多个 SLS与highstate不同这里不走 top file而是调用st_.render_highstate({saltenv: mods})手动构造 high data随后依次执行reconcile_extend处理extend声明、verify_high校验 high data 结构、requisite_in处理require_in/watch_in反向依赖、apply_exclude应用__exclude__最后compile_high_data得到 chunks——这条管线与 salt 常规state.sls的编译过程一一对应支持exclude参数字符串会被切分为列表并加入__exclude__任一环节返回errors非空则立即返回错误列表不发起远端执行。state.apply——统一入口def apply_(modsNone, **kwargs):官方 CLI 示例salt -C Tssh:node1 state.apply salt -C Tssh:node1 state.apply node1逻辑极简有mods则转发给sls()否则转发给highstate()——与常规 minion 上state.apply的行为语义一致。testTrue等 kwargs 原样透传。四、执行段_exec_state_pkg与 salt-thin 束编译、打包完成后真正的远程执行落在_exec_state_pkg()state.py。其执行步骤计算校验和salt.utils.hashutils.get_hash(trans_tar, opts[hash_type])计算传输 tar 的哈希默认sha256远端用pkg_sum校验包完整性构造Singlesalt.client.ssh.Single是 salt-ssh 单机执行的核心类。注意代码刻意传了占位 argvstate.pkg因为Single.__init__可能改写thin_dir如_salt→_salt_relenv真正的 argv 要在__init__完成后再构造cmd state.pkg {thin_dir}/salt_state.tgz test{test} pkg_sum{pkg_sum} hash_type{hash_type}SCP 推送single.shell.send(trans_tar, {}/salt_state.tgz.format(opts[thin_dir]))把包传到远端执行single.cmd_block()通过 salt-thin 束在远端运行state.pkg清理无论结果如何finally 中删除本地临时 tar 文件os.remove(trans_tar)OSError 吞掉。relenv 与 thin 束的本地化_relenv_path()state.py会在cachedir/relenv/linux/{x86_64,arm64}/salt-relenv.tar.xz中查找本地预构建的 relenv 压缩包找到就把它作为thin参数传给Single找不到则返回None让Single.__init__自行探测远端架构并下载对应压缩包。查找使用x86_64/arm64规范名因为salt.utils.relenv.gen_relenv会先把架构归一化再构建缓存路径。单元测试 的TestRelenvPath覆盖了四种情形仅 x86_64、仅 arm64、两者皆无、两者都有的优先级优先 x86_64。远端 thin_dir 的确定_thin_dir()state.py与 ssh 资源模块的同名函数 逻辑一致配置了thin_dir就用配置值否则用 UUID3命名空间 DNS 管理 minion FQDN的前 6 位 hex 生成路径且刻意放在/tmp/下/tmp/.user_hash_salt因为/tmp始终全局可写而/var/tmp/在某些系统上可能仅 root 可写。_seed_thin_dir()把它写进 opts保证编译与打包阶段路径一致。返回结构与异常兜底parse_ret在远端 retcode 非零时会抛出SSHCommandExecutionError——但某些 state 失败导致 retcode 2并不代表执行失败远端仍产出了合法的 state 结果 dict。因此代码捕获该异常后若异常携带的parsed[local][return]是 dict则解出 state 结果并把local[retcode]缺省EX_STATE_FAILURE写入__context__[retcode]正常返回——让运维人员看到完整 state 树而非原始 JSON否则重新抛出异常。正常路径下则解包envelope[return]thin 束会把结果包成{local: {jid: ..., return: ...}}信封并同步远端 retcode。模块最终直接返回 state 结果 dict 本身minion 分发器所期望的形式而非{local: {return: ...}}信封。单元测试 明确覆盖了这一异常兜底分支_exec_state_pkg()从异常中提取合法 state dict 返回、并在 parsed 无合法 state dict 时重新抛出。为什么在 job 内新建文件客户端_exec_state_pkg里特意新建了一个文件客户端_file_client()供Single.cmd_block()调用mod_data(fsclient)扫描扩展模块。_file_client()优先使用init()缓存在__context__[ssh_resource][master_opts]的 master 配置构造FSClient本地文件系统客户端不建立网络通道避开 minion job 线程内 tornado IO-loop 的复杂性无缓存时回退到RemoteClient。init()则优先从 minion 同目录的master配置文件读取完整 master opts比RemoteClient.master_opts()更全后者会缺fileserver_backend等键失败时回退。五、把模块放入资源模型一次完整的状态执行之旅结合 架构文档一次对 SSH 资源的状态执行在系统中是这样流动的目标展开运维执行salt -C Tssh:web-01 state.highstate。master 的资源注册表by_idmmap 索引查到 SRNssh:web-01的管理 minion ID把 job 投递给该 minion资源分发管理 minion 的 per-resource 加载器根据Tssh目标找到ssh类型的 state 覆盖层即本模块__resource__[id]指向web-01编译与打包highstate()用web-01作 top-file 目标编译 low chunksprep_trans_tar打包salt_state.tgz远程执行_exec_state_pkg通过Single把包 SCP 到远端thin_dir以 salt-thin 调用state.pkg远端 JSON 结果解包后作为 state dict 返回结果归并返回的 state 结果与普通 minion 的 state 结果一样进入 Job 返回运维看到完整 state 树。资源 ID 没有 top-file 匹配时则返回统一的 No Top file 状态条目。对运维的实用意义主机的发现与下线只需增删 Pillar 中ssh.hosts下的键并执行saltutil.refresh_resources无需重启进程discover()注释明确说明连接细节、主机密钥策略、超时与 keepalive 均可按主机覆盖testTrue预演、exclude排除、多 SLS 一次应用等常规 state 能力全部保留。六、测试与可靠性保障tests/pytests/unit/modules/test_sshresource_state.py 是围绕本模块的单元测试覆盖两类关键行为TestRelenvPath验证_relenv_path()在os.path.exists打桩下正确返回 x86_64/arm64 本地 relenv 压缩包路径、两者皆无时返回None、两者都有时优先 x86_64——保证不因路径探测逻辑在 job 线程中引入额外 SSH 往返TestHighstateEmptyChunkscompile_low_chunks返回空列表时highstate()必须返回resultFalse的 no top file 状态 dict而非None/空使合并展示干净_exec_state_pkg异常兜底用SSHCommandExecutionError(..., retcode2, parsed...)模拟远端 state 失败场景断言能从中提取合法 state dict 正常返回非法时重新抛出。测试中构造的_BASE_OPTS含id、resource_type、cachedir、hash_type: sha256、thin_dir、test、pillar与_BASE_RESOURCE{id: node1, type: ssh}也直观展示了模块运行所依赖的 dunder 环境__opts__、__resource__、__context__、__salt__。七、边界条件与注意事项基于源码可确认的边界与约束如下依赖ssh二进制资源类型在ssh不在 minion PATH 上时拒绝加载__virtual__返回Falsetop file 无匹配是可预期结果而非异常highstate()返回resultFalse的 No Top file 条目不会发起任何 SSH 往返initial_pillar为空 dict 时的坑State.__init__中if initial_pillar对空 dict 为假值会重新触发_gather_pillar因此_get_initial_pillar()对空 dict 显式返回None让调用方明确无缓存 pillar而非静默走错分支Single.__init__可能改写thin_dir因此 argv 必须在__init__之后构造注释明确说明远端 retcode 非零并不总是失败state 部分失败retcode 2时应展示完整 state 树模块通过异常兜底实现同时把 retcode 写入__context__供上层判断文件客户端策略优先本地FSClient避免 job 线程内的网络通道问题回退RemoteClient仅在无缓存的 master opts 时发生并记录 warning 日志。八、小结salt.resources.ssh.modules.state用一个约 500 行的模块把 salt-ssh 的编译—打包—SCP—thin 执行全流程下沉到管理 minion 进程内与资源子系统无缝衔接Pillar 声明主机、资源 ID 驱动 top-file 匹配与 SRN 路由、state.pkg承载远端执行、异常兜底保证 state 语义不被 SSH 错误码污染。对需要批量管理大量 SSH 主机的场景它提供了比逐个 proxy 更轻量、比手写 salt-ssh 脚本更统一的资源化抽象。相关实现可继续研读 ssh 资源模块、状态执行单元测试 与 资源配置文档。赞分享运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载相关推荐Salt 内核模块管理实战深入解析 kmod 执行模块与 kmod.present/absent 状态Salt 内核模块管理实战深入解析 kmod 执行模块与 kmod.present/absent 状态 本篇技术指南以 Salt 官方 API 文档 salt运维配置管理后端Salt SSH 资源执行模块 cmd无代理远程命令执行的源码级解析Salt SSH 资源执行模块 cmd无代理远程命令执行的源码级解析 导读 本文聚焦 salt.resources.ssh.modules.cmd 执行模块运维配置管理后端Salt 资源框架中的 dummy 类型执行模块覆盖深入解析 salt.resources.dummy.modules.testSalt 资源框架中的 dummy 类型执行模块覆盖深入解析 salt.resources.dummy.modules.test salt.resources运维配置管理后端上一篇AnuPpuccin 彩虹文件夹一步到位新手完整配置指南下一篇m4s转MP4免费合并工具B站缓存视频无损转换11.7GB只要38秒创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。