Kubernetes 1.31:流式传输从 SPDY 过渡到 WebSockets

在 Kubernetes 1.31 中,kubectl 默认使用 WebSocket 协议进行流式传输,而非 SPDY。

本文将介绍这些变化对您意味着什么,以及为什么这些流式 API 很重要。

Kubernetes 中的流式 API

在 Kubernetes 中,通过 HTTP 或 RESTful 接口暴露的特定端点会被升级为流式连接,这需要流式协议。与作为请求-响应协议的 HTTP 不同,流式协议提供了一种持久连接,它是双向的、低延迟的,并允许您实时交互。流式协议支持在客户端和服务器之间通过同一连接双向读写数据。这种类型的连接非常有用,例如,当您从本地工作站进入运行中的容器创建 shell 并在容器中运行命令时。

为什么要更改流式协议?

在 v1.31 版本发布之前,Kubernetes 在升级流式连接时默认使用 SPDY/3.1 协议。SPDY/3.1 协议已弃用八年,且从未标准化。许多现代代理、网关和负载均衡器不再支持该协议。因此,当您尝试通过代理或网关访问集群时,可能会注意到诸如 kubectl cpkubectl attachkubectl execkubectl port-forward 等命令无法工作。

从 Kubernetes v1.31 开始,SIG API Machinery 已将 Kubernetes 客户端(如 kubectl)用于这些命令的流式协议修改为更现代的WebSocket 流式协议。WebSocket 协议是当前受支持的标准化流式协议,它保证了与不同组件和编程语言的兼容性和互操作性。相比 SPDY,WebSocket 协议得到了现代代理和网关更广泛的支持。

流式 API 的工作原理

Kubernetes 通过向原始 HTTP 请求添加特定的升级头来将 HTTP 连接升级为流式连接。例如,对集群内 nginx 容器运行 date 命令的 HTTP 升级请求类似于以下内容

$ kubectl exec -v=8 nginx -- date
GET https://127.0.0.1:43251/api/v1/namespaces/default/pods/nginx/exec?command=date…
Request Headers:
    Connection: Upgrade
    Upgrade: websocket
    Sec-Websocket-Protocol: v5.channel.k8s.io
    User-Agent: kubectl/v1.31.0 (linux/amd64) kubernetes/6911225

如果容器运行时支持 WebSocket 流式协议以及至少一种子协议版本(例如 v5.channel.k8s.io),服务器将响应成功的 101 Switching Protocols 状态,以及协商好的子协议版本

Response Status: 101 Switching Protocols in 3 milliseconds
Response Headers:
    Upgrade: websocket
    Connection: Upgrade
    Sec-Websocket-Accept: j0/jHW9RpaUoGsUAv97EcKw8jFM=
    Sec-Websocket-Protocol: v5.channel.k8s.io

此时,用于 HTTP 协议的 TCP 连接已变为流式连接。此后,此 shell 交互的 STDIN、STDOUT 和 STDERR 数据(以及终端大小调整数据和进程退出代码数据)将通过此升级后的连接进行流式传输。

如何使用新的 WebSocket 流式协议

如果您的集群和 kubectl 版本是 1.29 或更高,有两个控制平面特性门控 (feature gates) 和两个 kubectl 环境变量控制 WebSocket 的使用,而非 SPDY。在 Kubernetes 1.31 中,以下所有特性门控都处于 beta 阶段并默认启用

  • 特性门控
    • TranslateStreamCloseWebsocketRequests
      • .../exec
      • .../attach
    • PortForwardWebsockets
      • .../port-forward
  • kubectl 特性控制环境变量
    • KUBECTL_REMOTE_COMMAND_WEBSOCKETS
      • kubectl exec
      • kubectl cp
      • kubectl attach
    • KUBECTL_PORT_FORWARD_WEBSOCKETS
      • kubectl port-forward

如果您连接到较旧的集群但可以管理特性门控设置,请同时开启 TranslateStreamCloseWebsocketRequests(在 Kubernetes v1.29 中添加)和 PortForwardWebsockets(在 Kubernetes v1.30 中添加)来尝试此新行为。1.31 版本的 kubectl 可以自动使用此新行为,但您需要连接到一个服务器端特性已明确启用的集群。

了解更多关于流式 API 的信息