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 协议是当前受支持的标准流式协议,可保证与不同组件和编程语言的兼容性和互操作性。WebSocket 协议比 SPDY 更广泛地被现代代理和网关支持。

流式 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 或更高版本,则有两个控制平面特性门和两个 kubectl 环境变量控制使用 WebSockets 而不是 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 中添加)以尝试此新行为。kubectl 的 1.31 版本可以自动使用新行为,但您需要连接到显式启用了服务器端特性的集群。

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