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 cp
、kubectl attach
、kubectl exec
和 kubectl 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 版本可以自动使用新行为,但您需要连接到显式启用了服务器端特性的集群。