Telepresence 在七月八天内发布了两个重大版本:14 日的 2.30 版,22 日的 2.31 版。两者共同构成了该项目自 2.x 架构诞生以来最大的一次进步,它们共享一个只有事后才显而易见的主题。多年来 Telepresence 承诺的每一项能力都带有星号——当你在真实组织中尝试使用时才会发现的限制条件。你可以附加到任何工作负载(*如果允许我们修改它)。你的流量会隧道到你的笔记本电脑(*每个字节都通过 Kubernetes API 服务器)。你的整个团队都可以使用它(*任何能到达 traffic-manager 的人也可以)。你的开发环境是可复现的(*作为同事和 CI 管道都无法运行的 wiki 命令页面)。

这两次发布移除了这些限制条件。本文将逐一介绍——不仅仅是改变了什么,而是为什么最终变成了这样。很少有内容是源于白板设计:这些设计源于多年来遇到问题以及与社区的长期对话,而这些背景才是有趣决策的来源。

如果你不了解 Telepresence:它是一个 CNCF 工具,用于将你的工作站连接到 Kubernetes 集群的网络,这样你正在开发的服务就可以在本地运行——在你的 IDE 中,带调试器,带亚秒级重建——同时表现得就像部署在集群中一样,包括接收来自周围服务的实时流量。

无需修改 Pod 即可附加

自 2.x 架构诞生以来,有一件事始终成立:要接收工作负载的流量,Telepresence 必须修改该工作负载。流量代理 sidecar 被注入到 Pod 中,这意味着 Pod 模板被重写,Pod 在代理首次到达时重启一次。

这种设计的选择有充分的理由,而且这些理由仍然存在。sidecar 是非特权的。它存在于 Pod 自己的安全上下文中,可以像任何其他容器一样被准入和审计,并且允许管理员严格锁定开发人员的 RBAC,因为集群端机制执行特权工作。对于长期团队安装来说,这是一种合理的架构,仍然是默认设置。

但围绕它的生态系统发生了变化。在设计 sidecar 时,"Pod 规范改变" 不是事件。今天它经常是一个事件:GitOps 管道会标记与已提交清单的任何偏离,有些配置为立即还原;准入策略会拒绝在审查后发生变更的 Pod 规范;平台团队拥有产品开发人员明确不允许修改的工作负载;有些工作负载重启成本很高——有长时间预热的 JVM、有选举的状态服务、运行中的批处理工作程序。在所有这些环境中,sidecar 不仅仅是不方便。它是不可接受的。

node-agent(2.30 新增)就是答案。当你附加到工作负载时,traffic-manager 会在目标 Pod 运行的节点上创建一个节点绑定的 Job。该代理从外部进入 Pod 的网络命名空间,并从那里提供附加服务——与 sidecar 提供的相同流量重路由、环境和卷访问,但 Pod 本身从未被修改,也从未重启。其结果直接如下:

  • 附加和分离是即时的。 无需等待 rollout,也无需安排重启。分离在工作负载中不留痕迹——没有 drift 检测需要发现,因为从来没有 drift。
  • 适用于你不拥有的工作负载。 Pod 规范从未被触及,所以没有准入控制器需要拒绝,也没有策略需要禁止的修改。
  • 覆盖每个副本。 traffic-manager 为每个副本创建一个代理,并在 Pod 出现和消失时协调集合,因此在 intercept 下的缩放工作负载表现正确,而不是只 intercept 幸运的副本。
  • 并发开发人员共享代理。 附加到相同工作负载的两个人重用相同的 node-agent,而不是堆叠机器。

权衡值得像好处一样明确陈述:node-agent 作为特权 Job 运行,因为从外部进入另一个 Pod 的网络命名空间本质上是特权操作。没有聪明的技巧可以避免这一点;任何附加到未修改 Pod 的工具都会在某个地方付出代价。你可以选择的是特权存在于哪里——在 traffic-manager 按需创建的短期、节点绑定的 Job 中,而不是开发人员运行的任何东西中。agent-modes 指南介绍了如何在 sidecar 和 node-agent 之间选择,因为两者都是正确的,适用于不同的集群。

如果通过节点级代理附加到未修改的工作负载听起来像 mirrord,那应该如此——这种方法是 mirrord 构建的基础,而且是一个好方法。通过 2.30,Telepresence 提供了两种风格。这两个工具在架构上仍有很大差异——Telepresence 在网络级别连接你的整个工作站,mirrord 在系统调用级别链接单个进程——我们维护了一个详细、公正的 比较,说明何时哪种更适合。

traffic-manager 现在知道谁在调用

2.31 是一个安全版本,而且是迟到的版本。它解决的不舒服事实是:直到现在,traffic-manager 都信任它的调用者。任何能到达其 gRPC 端点的人都可以创建会话、对其他客户端的附加执行操作,并路由流量——而无需证明自己是谁。两个高严重性公告,GHSA-j8j4-rw65-56r6GHSA-6j3h-rp73-6rvf,具体描述了这可能导致什么:集群中的任何 Pod 都可以声称是 traffic-agent 并 intercept 服务的流量,活跃的客户端会话可以被知道其 ID 的任何人劫持。

一个工具是如何走到这一步的?历史上:Telepresence 成长为一个开发工具,集群本身被视为可信的。可达性就是边界。这种假设多年前就不再站得住脚——集群是多租户的,工作负载是半可信的,"集群中的任何东西都可以调用任何其他东西" 正是 zero-trust 架构旨在消除的属性。修复必须在从未有身份的协议上追溯性地添加身份,而不破坏任何现有安装。这个约束塑造了一切。

第一个设计决策:不要发明凭据系统。 集群已经有一个。客户端现在转发其 kubeconfig 凭据已解析到的 bearer token——静态 token、token 文件或 exec 凭据插件的输出——traffic-manager 使用 Kubernetes TokenReview 验证它。客户端呈现的身份正是集群会分配给它的身份;没有新的东西需要配置、轮换或泄露。traffic-agent 使用投影的、audience-bound 的 ServiceAccount token 进行身份验证,这不仅证明了它们是什么,还证明了它们是哪个 Pod——专门关闭了 impersonate-an-agent 的漏洞。

在身份验证之上有两个授权规则,都建立在集群已经理解的概念之上:

  • 会话绑定到创建它们的身份。 调用者不能再对另一个客户端或代理的会话执行操作——审查其他人的 intercept、分离其他人的附加,或代表它不在其中运行的 Pod 说话。
  • 创建 intercept 需要 RBAC——具体来说,调用者的 Kubernetes 身份必须在目标命名空间中持有 pods/portforward,使用 SubjectAccessReview 检查。这个权限是故意选择的:这是 kubectl port-forward 已经要求的,从能力角度来看,intercept 就是 port-forward。没有新的策略语言,没有 Telepresence 特定的角色需要设计;如果你的集群 RBAC 已经说明了谁可以转发流量到 Pod,那么它现在也说明了谁可以 intercept 它们。

第二个设计决策是关于 rollout 的,它反映了社会学观察和技术观察:破坏现有安装的安全升级不会被安装。 它们会被推迟、绕过,并被怨恨——未应用的安全修复不保护任何人。因此,强制执行是可选的,由一个 Helm 值控制,有三个设置。permissive 是默认值,验证每个 token 并记录每个授权决策,但不拒绝任何内容:升级不会改变用户的任何内容,而日志会告诉你强制执行做什么。enforcing 打开拒绝。(disabled 存在于真正想要旧行为的安装中。)预期的路径是设计上平淡无奇的:升级,让客户端和代理群集赶上,观察 permissive 日志直到它们安静下来,翻转开关。旧客户端在 permissive manager 上继续工作,2.31 客户端在旧 manager 上继续工作——群集只需要在最后一步保持最新。

完整细节,包括每种 kubeconfig 凭据类型提供的内容,都在新身份验证参考中。

QUIC:将 API 服务器移出数据路径

工作站和集群之间的所有隧道流量历史上都通过单个 port-forwarded gRPC 连接传输。这种设计有一个很大的优点:它在任何地方都能工作。如果你能到达 Kubernetes API 服务器,你就可以 port-forward,如果你能 port-forward,Telepresence 就能工作——没有 LoadBalancer,没有开放端口,没有防火墙对话。

但看看它的成本。port-forward 依赖 API 服务器连接,这意味着隧道开发流量的每个字节——你的服务接收的每个请求,它向上游发出的每个调用——都经过集群的控制平面。API 服务器是集群最关键、最有争议的组件,它从来不是为数据平面设计的。对于单个开发人员来说,负载是噪声;对于跨组织运行 Telepresence 的平台团队来说,这是可衡量的,而且花费在完全错误的组件上。

单个连接也伤害了开发人员。一个 gRPC 连接就是一个 TCP 流,将每个流多路复用到一个 TCP 流上,在规模上获得了 TCP 最糟糕的属性:队首阻塞。当一个数据包丢失时,TCP 会阻止它后面的所有内容,直到重传到达——包括仅共享管道的无关流的字节。在干净的网络上你不会注意到。在有损网络上——酒店 Wi-Fi、VPN 集中器遇到坏日子、拥塞的最后一英里——每个流都会定期为其他流的不幸付出代价,隧道感觉神秘地滞后,很难归因。

2.31 中的可选 QUIC 传输一次解决了这两个问题。客户端直接连接到 traffic-manager 暴露的 QUIC 端点,因此隧道流量完全绕过 API 服务器——控制平面回到做控制平面工作。由于 QUIC 为每个流提供独立的丢失恢复,丢失的数据包只会暂停它所属的流。我们的基准测试证实了这一点:在 1–3% 入口数据包丢失时,通过共享 gRPC 隧道的小请求流量的尾部延迟比通过 QUIC 高 1.7–1.8 倍——小请求的尾部延迟正是交互式开发的感觉——而收益并不局限于有损网络:在许多基准形状中,直接 QUIC 路径明显更快。

为什么是可选的?因为使 gRPC 隧道通用的属性是 QUIC 无法拥有的。QUIC 端点必须作为 UDP 服务可达——LoadBalancer 或 NodePort——这是管理员的决定,并非每个集群都能提供。因此,当设置 quicTunnel.enabled 时,traffic-manager 暴露 QUIC,客户端在可达时自动将新的隧道连接升级到它,gRPC 仍然是默认且始终可用的回退。telepresence status 会告诉你你实际获得了哪种传输——无需猜测。

你的开发环境现在是一个文件

Kubernetes 凭借一个想法获胜:描述你想要的状态,让控制器实现它。然而,集群原生开发的工作站端仍然顽固地命令式——连接到这个集群,用这九个标志 intercept 那个服务,启动本地服务器,明天重复,通过指向两个季度前准确的 wiki 页面来让新队友上手。

telepresence apply -f dev.yaml(2.31 新增)将声明式模型带到工作站。清单描述了可选连接和一组附加——intercept、replace、ingest 或 wiretap——每个都有其标志,可选地还有在附加运行时要运行的本地命令:你的开发服务器,在附加准备好时启动,在拆除时停止。Apply 是幂等的:已与清单匹配的保持不变,已漂移的被重新创建,--dry-run 显示计划而不触碰任何东西。telepresence delete -f 再次拆除整个状态。

实际转变比功能列表建议的更大。团队的标准开发设置不再是部落知识,而是成为仓库中的一个文件——版本化、审查,对新员工和老员工都相同。"我如何在这个服务上设置?" 变成了 telepresence apply -f dev.yaml,答案在每个人的机器上都相同。

下一步:将集群知识移入工具

上述功能使 Telepresence 更强大。下一个举措解决不同的问题:第一个小时。

安装真正适合集群的 traffic-manager 需要回答有关该集群的问题。它能否暴露 QUIC 端点,应该是 LoadBalancer 还是 NodePort?node-agent 会通过集群的准入策略吗?可以创建 mutating webhook,API 服务器能到达它吗?安装应该是集群范围的还是命名空间范围的,是哪些命名空间?是否已经安装了,是否健康?今天,答案存在于参考文档和试错中,这对于评估 Telepresence 是否值得采用的人来说是一个真正的成本——最熟悉这些问题的人是最不需要文档的人。

即将推出的 telepresence setup 命令(计划在下一个版本之一中推出)将这些知识移入工具。它只读探测集群——安装权限、QUIC 可行性、node-agent 准入(带有执行实际策略引擎的服务器端 dry-run 金丝雀)、webhook 可达性、命名空间规模、现有安装及其健康状况,甚至与工作站本地网络的路由冲突。然后它只问探测留下的问题,并验证、写入或应用完全配置的 Helm 安装。值得注意的设计决策:它从不修改工作站,因此可以安全地重复运行,也可以安全地只读运行;它写入的 values 文件是普通的 Helm values 文档,因此可以插入 GitOps 而不是绕过它;它也充当现有安装的医生;当你缺乏集群权限时,它会为你的管理员生成逐项移交,而不是死胡同。

感谢 OpenAI

没有资助的维护者时间,这一切都不会发生,这值得具体说明。像 node-agent 或从头开始的身份验证层这样的功能是几个月的工作:设计、实现、安全审查、文档和硬化的长尾。这种规模的工作不适合晚上和周末——不可持续,也不是安全层所要求的那种质量。

OpenAI 赞助 Telepresence 项目。 不是这些特定功能——没有附加功能方向——只是对项目本身的持续支持。这正是那种赞助,让维护者有空间承担这种规模的工作,而这两次发布就是直接结果。谢谢。

Telepresence OSS 是 CNCF 项目,采用 Apache 2.0 许可证。本文中描述的一切都是免费的——没有席位,没有付费层,没有功能门。如果你的组织从中获得价值,最好的回馈方式是 贡献赞助,直接资助维护和开发。

开始使用

快速入门 大约需要十分钟。完整的变更列表在 发行说明 中,问题和实战经验欢迎在 GitHub Discussions 或 CNCF Slack 的 #telepresence-oss 中讨论。

本文最初出现在 telepresence.io