本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
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 協議是當前受支援的標準化流式協議,可保證與不同元件和程式語言的相容性和互操作性。與 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 或更高,有兩個控制平面特性門控和兩個 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 中新增)來嘗試這種新行為。kubectl
的 1.31 版本可以自動使用這種新行為,但你需要連線到一個明確啟用了伺服器端功能的叢集。