资讯动态

Telepresence 工作台状态清单(Workstation State Manifest)实战指南:用 YAML 声明式管理 connect、intercept 与本地进程

发布时间:2026/9/29 8:16:25 来源:尧图企业网站定制
云原生开发工具微服务网络【免费下载链接】telepresenceLocal development against a remote Kubernetes or OpenShift cluster项目地址https://gitcode.com/gh_mirrors/te/telepresence点击查看免费下载在日常开发中启动一个 Telepresence 开发会话往往意味着重复执行同一串命令先telepresence connect连接集群再对一个或多个工作负载执行 attach/intercept/ingest最后还要启动处理这些流量的本地进程。Telepresence 的**工作台状态清单Workstation State Manifest**把这一整套状态固化到单个 YAML 文件中用telepresence apply -f file一键将工作台带到清单描述的状态用telepresence delete -f file一键拆除且 apply 具备幂等性可随项目仓库一起提交并随时重复应用。读完本文你将掌握清单的完整字段、apply/delete 的精确语义、处理器进程handler的生命周期规则以及如何在仓库源码中验证这些行为。本文以 docs/howtos/state-manifest.md 与 docs/reference/state-manifest.md 为骨架结合pkg/client/cli/manifest/下的源码实现进行纵深解析。什么是工作台状态清单一个工作台状态清单声明了工作台workstation上 Telepresence 的状态一个可选的连接connection和一组附件attachments——intercept、replace、ingest 或 wiretap每个附件可选地配对一个处理其流量的本地进程handler。telepresence apply -f file把工作台带到清单声明的状态telepresence delete -f file把该状态拆除。apply 是幂等的清单可以检入项目仓库随时重新应用凡是已经匹配的部分都会原样保留、不做任何改动。这意味着开发环境搭建可以被版本化——团队成员共享同一份dev.yaml就能复现完全一致的本地联调环境。从实现上看清单由 pkg/client/cli/manifest/apply.go 中的Apply函数驱动它先确保连接建立再按声明顺序逐个调和reconcile附件每个附件复用与命令式命令telepresence intercept等完全相同的状态机见 pkg/client/cli/manifest/reconcile.go 的reconcileAttachment。注意Docker 模式不在清单的管辖范围内。Docker 模式下工作台状态就是容器状态handler 是容器带镜像、网络、环境变量和挂载而 Docker Compose 正是声明这种状态的既有格式。Telepresence 的 compose 扩展让带注解的 compose 配置成为连接与附件的声明源telepresence compose up/down扮演了 apply/delete 的角色。如果清单再覆盖 Docker 模式就会成为同一状态的两个声明所有者与 compose 文件互相竞争。第一个清单连接 单个拦截下面这份清单声明了一个连接以及对api工作负载http端口的一个拦截apiVersion: telepresence.io/v1alpha1 kind: WorkstationState connection: namespace: my-team attachments: - type: intercept name: api ports: [8080:http]将其保存为dev.yaml后执行$ telepresence apply -f dev.yaml connection: connected intercept api: created再次执行同样的命令输出表明什么都不会改变$ telepresence apply -f dev.yaml connection: reused intercept api: unchanged这正是幂等性的体现连接会话被复用reused已建立的拦截被判定为一致unchanged。端口标识符PortIdentifier写法上面的ports: [8080:http]使用本地端口:标识符形式其中标识符是服务端口名或端口号用于唯一定位服务端口。根据清单 JSON Schema 中 PortIdentifier 的定义一个端口项既可以是纯端口号整数或字符串也可以是端口:端口或名称的映射。例如8080:8080表示本地 8080 转发到工作负载的 80809090:grpc表示本地 9090 转发到名为grpc的服务端口。作为 apply 一部分运行本地进程处理被拦截流量的本地进程通常需要远程容器的环境变量和卷挂载因此它必须在附件建立之后启动。清单用command声明它——这等价于telepresence intercept及其同类命令尾部接受的-- cmd args...apiVersion: telepresence.io/v1alpha1 kind: WorkstationState connection: namespace: my-team attachments: - type: intercept name: api ports: [8080:http] env: file: api.env command: [node, server.js]$ telepresence apply -f dev.yaml connection: connected intercept api: created, handler: started这里env.file将远程环境以指定语法默认docker格式可选sh、csh、json等写入本地文件api.env而command声明的进程会以合并了远程环境的方式启动。进程以**分离detached**方式运行它位于自己的进程组中stdout/stderr 追加写入 Telepresence 日志目录下的handler-api.log。再次 apply 时如果进程已退出、或清单中的command发生了变化它会重启只改 command 永远不会扰动附件本身$ telepresence apply -f dev.yaml connection: reused intercept api: unchanged, handler: restarted合成环境变量从 pkg/client/cli/manifest/handler.go 的handlerEnv函数可以看到handler 进程的环境 本地环境 附件远程环境 三个由命令式命令同样合成的变量TELEPRESENCE_INTERCEPT_ID附件 id对 ingest 而言其值与 handler 注册所用的 id 不同TELEPRESENCE_API_HOSTTelepresence API 主机来自 user daemon 的容器名TELEPRESENCE_ROOT挂载根路径。e[TELEPRESENCE_INTERCEPT_ID] envID e[agentconfig.EnvAPIHost] daemon.MustGetUserClient(ctx).DaemonID().ContainerName() e[TELEPRESENCE_ROOT] mountPoint多个附件按声明顺序应用附件按声明顺序应用每种类型接受与其命令式命令的 flag 相同的属性。下面的清单依次声明了一个 intercept、一个 ingest 和一个 wiretapapiVersion: telepresence.io/v1alpha1 kind: WorkstationState connection: namespace: my-team attachments: - type: intercept name: api ports: [8080:http] command: [node, server.js] - type: ingest name: worker mount: path: /tmp/worker-volumes - type: wiretap name: billing ports: [9090:grpc]intercept拦截目标工作负载的流量示例中name: api同时充当工作负载名可通过workload覆盖ingest摄取一个容器的环境与挂载、不路由任何流量mount.path指定远程卷的本地挂载点默认是生成的临时目录wiretap接收目标端口流量的副本不干扰原始流量流。清单要求附件名称在清单内唯一见 Schema 中attachments的约束delete则按逆序拆除。用 --dry-run 预览--dry-run会加载并校验清单、与当前状态对比然后不做任何改动地报告 apply 将会做什么$ telepresence apply --dry-run -f dev.yaml connection: reused intercept api: would-re-create (drift: ports: manifest[8081:http] actual porthttp target-port8080 pod-ports[]) ingest worker: unchanged wiretap billing: would-create输出中的would-create、would-re-create、would-connect分别对应真实 apply 的created、re-created、connected。漂移详情drift会直接附在报告里例如上面显示端口从清单的[8081:http]漂移到了实际的porthttp target-port8080。清单附件与当前已建立状态存在差异时端口、容器、过滤条件或挂载点不同真实 apply 会执行重建先移除、再从清单创建。漂移比较只针对清单实际指定的字段且只比较有服务端表示的字段——例如 env 文件路径只在附件被创建或重建时生效不会被纳入漂移比较。这一点在 pkg/client/cli/manifest/reconcile.go 的diffInterceptSpec/diffIngestSpec中逐字段实现workload、namespace、service、container、ports、address、mechanism、metadata、HTTP 过滤器、plaintext、toPod、mount.path、nodeAgent 等。拆除telepresence deletetelepresence delete -f file按逆声明顺序移除清单中的附件并停止其 handler 进程$ telepresence delete -f dev.yaml connection: disconnected wiretap billing: removed ingest worker: removed intercept api: removed, handler: stopped关键规则只有声明了connection的清单delete 时才会断开连接daemon 无论哪种情况都会继续运行。只有附件的清单apply 作用于、delete 也作用于当前已建立的连接并保持该连接继续运行若当前没有任何连接apply 会失败。已声明但并未建立的附件会被报告为absent且不视为错误见removeAttachment的实现附件不存在时Action absent仍然继续处理。清单 Schema 详解清单是 YAML或 JSON文档必须有如下头部并且connection与attachments至少存在一个apiVersion: telepresence.io/v1alpha1 kind: WorkstationState每个清单在比较或改动任何东西之前都会先经过 JSON Schema 校验未在 Schema 中定义的属性一律被拒绝additionalProperties: false。Schema 发布在 docs/schemas/workstation-state.v1alpha1.json其源文件位于仓库pkg/client/cli/manifest/state.schema.yaml。把 IDE 的 YAML 语言服务器指向发布的 Schema即可在编辑时获得自动补全与校验。connection 对象connection对象对应telepresence connect的全部 flag字段说明name连接名默认派生自 kubeconfig 上下文与命名空间kubeconfig要使用的 kubeconfig 文件路径context要使用的 kubeconfig 上下文名namespace连接作用的 Kubernetes 命名空间kubeFlags额外的 kubectl flag以不带前导横线的 flag 名为键如server、token、as、insecure-skip-tls-verifyflag 参数为值managerNamespace查找 traffic manager 的命名空间mappedNamespacesDNS 解析器与 NAT 在出站连接中考虑的命名空间默认全部命名空间alsoProxy额外代理的子网CIDRneverProxy永不代理的子网CIDRallowConflictingSubnets允许与本地子网冲突的子网vnat通过虚拟 IP 翻译、不经由特定工作负载路由的子网等价于--vnatflagproxyVia通过虚拟 IP 翻译、且经由某个工作负载路由的子网rerouteLocal本地主机上重路由到远程主机的端口格式本地端口:主机:端口[/{tcp,udp}]rerouteRemote远程主机上被重路由的端口格式主机:端口:新端口[/{tcp,udp}]vnat的每个条目可以是 CIDR 记号的子网也可以是符号名service、pods、also或all它是workload: local的proxyVia条目的简写——与--vnatflag 完全一致。只有当子网必须经由特定工作负载路由时才需要直接使用proxyVia。attachments 对象每个附件有typeintercept、replace、ingest、wiretap、唯一的name以及对应命令式命令 flag 的属性。Schema 中 AttachmentCommon 定义了四种类型共有的字段namespace工作负载的命名空间默认取连接的命名空间container提供环境与挂载的容器名默认取匹配第一个端口的容器env把远程环境以file/syntax/json形式输出到本地文件mount远程卷的挂载配置enabled默认true、path默认生成的临时目录、readOnly、localMountPort用 SFTP 在本地端口暴露远程文件系统nodeAgent是否使用节点级node-scoped流量代理command处理附件流量的本地命令即命令式命令尾部-- cmd args...的清单等价物。intercept与wiretap共享端口/过滤属性InterceptCommonworkload要附着的负载名默认取附件名service要附着的服务名有时用于唯一定位端口ports要转发的本地端口用本地端口:标识符唯一定位服务端口address本地转发地址默认127.0.0.1mechanism附件使用的机制默认tcphttpHeaders仅处理匹配全部给定 HTTP 头的请求格式名称正则httpPathEqualities/httpPathPrefixes/httpPathRegexps仅处理路径精确等于/匹配前缀/匹配正则的请求plaintext与本地 interceptor 进程通信时使用明文格式。intercept独有metadata附加到拦截上的元数据可通过 Telepresence API server 检索与toPod额外转发到 pod、在 localhost 上可用的端口默认协议 TCP端口/UDP表示 UDP。replace类型用于替换工作负载中的容器name是容器被替换的工作负载名未使用container属性时可用工作负载/容器来命名容器ports是要转发到本地的容器端口本地端口:容器端口表示本地端口不同all表示全部容器端口默认[all]。ingest类型摄取容器的环境与挂载而不路由任何流量name是要摄取的工作负载名挂载对 ingest 而言始终是只读的。Apply 的精确语义apply 先建立连接再按声明顺序逐个调和附件声明了连接对正在运行的匹配 daemon 做只读检查对应 apply.go 中ensureDeclaredConnection调用的CheckConnectRPC。会话设置与清单不一致时是漂移错误什么都不动对齐的或无会话的 daemon 走普通 connect 流程——与重复执行telepresence connect完全一致。未声明连接使用当前选中的连接当前无连接时 apply 失败delete 则保持该连接不动。附件缺失创建报告为created。附件已建立且匹配原样保留报告为unchanged。只比较清单实际指定、且有服务端表示的字段。附件已建立但漂移类型、workload、namespace、container、service、ports、address、mechanism、HTTP 过滤器、plaintext、metadata、toPod、挂载点或 agent 种类不同先移除、再从清单重建报告为re-created并附上检测到的漂移。第一个失败的附件会中止 apply但同一次运行中已调和的附件会保留——它们本就属于期望状态而重复运行 apply 是幂等的。--dry-run执行相同的加载、校验和比较但什么都不改改用would-connect、would-create、would-re-create报告连接漂移仍然是错误。当声明的连接尚不存在时没有会话可供比较因此每个附件都会报告为would-create对应 apply.go 中wouldConnect分支对全部附件统一打would-create/would-start的处理。两个命令都支持--output结构化输出此时摘要是一个 JSON 或 YAML 对象而不是每个附件一行。Handler 进程生命周期由于 apply 不会像命令式命令那样停留在一旁监督进程它采取了三项配套措施见 handler.go 的startHandler分离启动handler 在自己的进程组中运行stdout/stderr 追加到 Telepresence 日志目录下的handler-附件名.log注册到 user daemon通过AddHandlerRPC 注册附件被移除时delete、漂移重建、或命令式 leavedaemon 会终止该进程记录状态把 pid 与 argv 记录在 Telepresence 缓存目录下按 daemon 与附件名组织附件名会做安全化处理因为 replace 附件可能叫工作负载/容器供后续 apply 把运行中的进程与清单对账。对其余状态不变的附件handler 的调和规则如下表记录到的 handler 状态apply 动作报告运行中argv 匹配无无输出已退出或从未启动启动handler: started运行中argv 不同停止后重启handler: restarted运行中command被移除停止handler: stopped之所以只改command不会重建附件是因为 command 没有服务端表示。--dry-run相应报告would-start、would-restart、would-stop而不触碰进程。以上决策树完整实现在 reconcile.go 的reconcileHandler中。源码验证与可测试示例如果希望深入验证上述行为仓库提供了直接证据Schema 源文件pkg/client/cli/manifest/state.schema.yaml 定义了全部字段、默认值与约束发布版见 docs/schemas/workstation-state.v1alpha1.json。Go 类型定义pkg/client/cli/manifest/types.go 中State/Connection/Attachment/Env/Mount结构体与 JSON 标签一一对应 Schema。调和与漂移逻辑pkg/client/cli/manifest/reconcile.go 的reconcileAttachment、diffInterceptSpec、diffIngestSpec、reconcileHandler、removeAttachment。连接建立逻辑pkg/client/cli/manifest/apply.go 的Apply、ensureDeclaredConnection、connectDeclared。测试数据pkg/client/cli/manifest/testdata 目录下有valid-full.yaml、valid-command.yaml、valid-attachments-only.yaml以及invalid-duplicate-name.yaml、invalid-empty.yaml、invalid-unknown-property.yaml、invalid-wrong-kind.yaml、invalid-vnat-entry.yaml等一组合法/非法样例可直接对照学习哪些写法会被 Schema 拒绝对应的 load_test.go、reconcile_test.go、handler_test.go 覆盖加载、调和与 handler 生命周期。快速上手建议从valid-full.yaml或上面的首个示例出发建立一份dev.yaml检入项目仓库用telepresence apply --dry-run -f dev.yaml在不触碰环境的前提下先观察 diff 报告确认无误后telepresence apply -f dev.yaml建立环境日常迭代只改command即可实现 handler 的原地重启附件本身保持unchanged收工时用telepresence delete -f dev.yaml逆序拆除附件与 handler如需一并断开连接则在清单中声明connection。将这套工作流落地后连接 多个附件 本地 handler的整套开发环境就变成了一个可提交、可复用、可审计的声明式资产。赞分享云原生开发工具微服务网络【免费下载链接】telepresenceLocal development against a remote Kubernetes or OpenShift cluster项目地址https://gitcode.com/gh_mirrors/te/telepresence点击查看免费下载相关推荐Salt Apache 状态模块实战指南用 YAML 声明式管理 httpd 配置Salt Apache 状态模块实战指南用 YAML 声明式管理 httpd 配置 导读 apache 状态模块 salt.states.apache ht运维配置管理后端Salt State 模块 chocolatey 完全指南用声明式状态管理 Windows 软件包Salt State 模块 chocolatey 完全指南用声明式状态管理 Windows 软件包 本指南以 Salt 官方文档中 salt.states.c运维配置管理后端Salt 的 ini_manage 状态模块用 State 声明式管理 INI 配置文件Salt 的 ini_manage 状态模块用 State 声明式管理 INI 配置文件 导读 在管理 api paste.ini 、 sysctl.conf运维配置管理后端上一篇Gutenberg 中的 useBlockDisplayInformation Hook深入解析块显示信息解析机制下一篇es-toolkit unzip 使用指南将 zip 压缩的二维数组按位置解包还原创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑