ZTunnel 更新过程
ZTunnel 在 OSI 模型的第 4 层(L4)运行:它代理 TCP 字节流,无法查看其上层的应用协议。因此,已建立的 TCP 连接无法从一个 ZTunnel 进程移交给替代进程。由于 ZTunnel 以每个节点一个的 DaemonSet 形式运行,替换它至少会一次影响一个节点上的所有网格流量。了解这种滚动更新行为,有助于你为依赖长连接的工作负载规划更新。
滚动更新阶段
默认情况下,ZTunnel DaemonSet 使用 RollingUpdate 策略,并一次处理一个节点。在每个节点上,替代过程会经历以下阶段:
- 启动 — 新的 ZTunnel pod 启动,旧 pod 继续提供流量服务。
- 就绪 — 新的 ZTunnel 在节点上的每个 pod 中建立监听器并报告就绪。两个实例会短暂并行运行;由于 ZTunnel 使用
SO_REUSEPORT,在此期间任一实例都可能接受新连接。 - 排空 — Kubernetes 向旧 ZTunnel 发送
SIGTERM,旧 ZTunnel 随即关闭监听器并开始排空。从此时起,只有新的 ZTunnel 接受连接;节点在任何时刻都不会处于没有 ZTunnel 监听的状态。 - 连接处理 — 旧 ZTunnel 继续为其已经持有的连接提供服务。
- 终止 —
terminationGracePeriodSeconds定义的排空时间结束后,旧 ZTunnel 会强制关闭仍处于打开状态的连接。
任何持续时间超过排空时间的连接都会被重置。下面两节介绍如何延长该时间,或完全避免强制重置。
配置优雅的连接终止
最简单的缓解措施是将 terminationGracePeriodSeconds 调高到足够让应用的连接在排空阶段自然完成。要选择合适的值,需要了解网格中工作负载的连接生命周期。请注意,DaemonSet 一次处理一个节点,因此过大的值会延长整个集群更新的持续时间——应尽量设置一个平衡的值。
在 ZTunnel custom resource(CR)中设置该值:
- 此示例中为五分钟——请根据需要保护的最长连接生命周期调整该值。
实现重试逻辑或使用较短 keepalive 超时的应用,比持有非常长的空闲 TCP 连接的应用更能从 ZTunnel 重启中平稳恢复。
通过排空节点安全地更新 ZTunnel
由于 TCP 连接无法在 ZTunnel 进程之间传输,将应用迁移到新 ZTunnel 的唯一可靠方式是优雅地重启应用本身。排空节点可以受控地完成这一过程:应用按照自身的终止宽限期关闭,空节点上的 ZTunnel 在没有任何流量风险的情况下完成替换,应用恢复后通过新的 ZTunnel 重新连接。
操作步骤
-
将 ZTunnel DaemonSet 切换为
OnDelete更新策略,以便仅在删除旧 pod 后创建新 pod:- 使用
OnDelete时,更新ZTunnel资源本身不会替换任何正在运行的 pod;只有删除某个节点上的 ZTunnel pod 时,该节点才会更新。
- 使用
-
将
ZTunnelCR 的spec.version字段设置为目标版本。 -
排空一个节点。所有应用会迁移到其他节点,并在各自的
terminationGracePeriodSeconds约束下优雅地关闭长连接。 -
删除已排空节点上的旧 ZTunnel pod,并等待新 pod 启动。由于节点上已没有工作负载,此替换不会给流量带来风险。
-
再次将节点标记为可调度。重新调度回该节点的工作负载会自动使用新的 ZTunnel。
-
对集群中的每个剩余节点重复步骤 3 至 5。
其他资源
- 排查 ZTunnel 问题(Istio 文档)
- 排查 waypoint proxy 问题(Istio 文档)