自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

源碼解析 Kubectl Port-Forward 工作原理

開發(fā) 前端
本文的源碼基于 Kubernetes v1.24.0,容器運(yùn)行時(shí)使用 Containerd 1.5,從源碼來(lái)分析 kubectl port-forward 的工作原理。

本文的源碼基于 Kubernetes v1.24.0,容器運(yùn)行時(shí)使用 Containerd 1.5,從源碼來(lái)分析 kubectl port-forward 的工作原理。

通過(guò) port-forward 流程的分析,梳理出 kubectl -> api-server -> kubelet -> 容器運(yùn)行時(shí) 的交互,了解 cri 的工作方式。

圖片kubectl-port-forward

kubectl

簡(jiǎn)單創(chuàng)建個(gè) pod:

kubectl run pipy --image flomesh/pipy:latest -n default

在執(zhí)行 kubectl forward 時(shí)添加參數(shù) -v 9 打印日志。

kubectl port-forward pipy 8080 -v 9
...
I0807 21:45:58.457986 14495 round_trippers.go:466] curl -v -XPOST -H "User-Agent: kubectl/v1.24.3 (darwin/arm64) kubernetes/aef86a9" -H "X-Stream-Protocol-Version: portforward.k8s.io" 'https://192.168.1.12:6443/api/v1/namespaces/default/pods/pipy/portforward'
I0807 21:45:58.484013 14495 round_trippers.go:553] POST https://192.168.1.12:6443/api/v1/namespaces/default/pods/pipy/portforward 101 Switching Protocols in 26 milliseconds
I0807 21:45:58.484029 14495 round_trippers.go:570] HTTP Statistics: DNSLookup 0 ms Dial 0 ms TLSHandshake 0 ms Duration 26 ms
I0807 21:45:58.484035 14495 round_trippers.go:577] Response Headers:
I0807 21:45:58.484040 14495 round_trippers.go:580] Upgrade: SPDY/3.1
I0807 21:45:58.484044 14495 round_trippers.go:580] X-Stream-Protocol-Version: portforward.k8s.io
I0807 21:45:58.484047 14495 round_trippers.go:580] Date: Sun, 07 Aug 2022 13:45:58 GMT
I0807 21:45:58.484051 14495 round_trippers.go:580] Connection: Upgrade
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

從日志可以看到請(qǐng)求的地址為 /api/v1/namespaces/default/pods/pipy/portforward,其中 portforward 為 pod 資源的子資源。

這里使用的協(xié)議是 spdy。

kubectl 此時(shí)會(huì)監(jiān)聽本地端口,同時(shí)使用 pod 子資源 portforward 的 url 創(chuàng)建到 api-server 的連接。

當(dāng)本地端口有連接接入時(shí),kubectl 會(huì)不斷地在兩個(gè)連接間拷貝數(shù)據(jù)。

參考源碼:

  • staging/src/k8s.io/kubectl/pkg/cmd/portforward/portforward.go:389[1]
  • staging/src/k8s.io/client-go/tools/portforward/portforward.go:242[2]
  • staging/src/k8s.io/client-go/tools/portforward/portforward.go:330[3]

api-server

pod 的三個(gè)子資源 exec、attach 和 portforward,對(duì)這三個(gè)資源的操作都會(huì)代理有對(duì)應(yīng) node 的 kubetlet server 進(jìn)行處理。

api-server 在接收到訪問(wèn) pod 子資源 portforward 的請(qǐng)求后,通過(guò) pod 及其所在 node 的信息,獲取訪問(wèn)該 node 上 kubelet server 的 url。

然后將訪問(wèn) pod 的 portforward 的請(qǐng)求,代理到 kubelet server。

參考源碼

  • pkg/registry/core/pod/rest/subresources.go:185[4]

kubelet

portforward 請(qǐng)求來(lái)到了 pod 所在節(jié)點(diǎn)的 kubelet server,在 kubelet server 中,有幾個(gè)用于調(diào)試的 endpoint,portforward 便是其中之一:

  • /run/{podNamespace}/{podID}/{containerName}
  • /exec/{podNamespace}/{podID}/{containerName}
  • /attach/{podNamespace}/{podID}/{containerName}
  • /portforward/{podNamespace}/{podID}
  • /containerLogs/{podNamespace}/{podID}/{containerName}
  • /runningpods/

kubelet server 收到請(qǐng)求后,首先會(huì)通過(guò) RuntimeServiceClient 發(fā)送 gRCP 請(qǐng)求到容器運(yùn)行時(shí)的接口(/runtime.v1alpha2.RuntimeService/PortForward)獲取容器運(yùn)行時(shí) streaming server 處理 pordforward 請(qǐng)求的 url。

拿到 portforward streaming 的 url 之后,kubelet server 將請(qǐng)求代理到該 url。

參考源碼

  • pkg/kubelet/server/server.go:463[5]
  • pkg/kubelet/server/server.go:873[6]
  • pkg/kubelet/cri/streaming/portforward/portforward.go:46[7]
  • pkg/kubelet/cri/streaming/server.go:111[8]

cri

這里以 Containerd 為例。

Containerd 在啟動(dòng)時(shí)會(huì)啟動(dòng) runtime service 和 image service。前者是負(fù)責(zé)容器相關(guān)的操作,后者負(fù)責(zé)鏡像相關(guān)的操作。

kubelet 獲取用于端口轉(zhuǎn)發(fā)的 streaming url,就是調(diào)用了 runtime service 的 gRPC 接口完成的。

除了兩個(gè) gRPC service 以外,還加載了一系列插件。這些插件中,其中有一個(gè)是 cri service。

cri service 會(huì)啟動(dòng) streaming server。這個(gè) server 會(huì)響應(yīng) /exec、/attach 和 /portforward 的 stream 請(qǐng)求。

portforward 支持兩種操作系統(tǒng) linux 和 windows:sandbox_portforward_linux.go 和 sandbox_portforward_windows.go。

在 linux 上,在 pod 所在的 network namespace 中使用地址 localhost 創(chuàng)建到目標(biāo)端口的連接。然后在 streaming server 的連接和該連接之間拷貝數(shù)據(jù),完成數(shù)據(jù)的傳遞。

在 windows 上,是通過(guò) wincat.exe 使用地址 127.0.0.1 創(chuàng)建到目標(biāo)端口的連接。

參考源碼

  • pkg/cri/streaming/server.go:149[9]
  • pkg/cri/server/streaming.go:69[10]
  • pkg/cri/server/service.go:138[11]
  • pkg/cri/server/sandbox_portforward_linux.go:34[12]

總結(jié)

結(jié)合源碼分析對(duì) port-foward 工作原理的梳理,相信對(duì) cri 的工作方式也有了一定的了解。本文是以容器運(yùn)行時(shí) Containerd 為例,不同的容器運(yùn)行時(shí)雖然實(shí)現(xiàn)了 cri,但是實(shí)現(xiàn)的細(xì)節(jié)上也會(huì)有所差異。

比如在 port-forward 的實(shí)現(xiàn)上,Kubernetes v1.23.0 版本中的 docker shim(1.24 中被移除)[13] 中,是使用nsenter 進(jìn)入 pod 所在的 network namespace 中通過(guò) socat 完成的端口轉(zhuǎn)發(fā)。

參考資料

[1] staging/src/k8s.io/kubectl/pkg/cmd/portforward/portforward.go:389: https://github.com/kubernetes/kubernetes/tree/release-1.24/staging/src/k8s.io/kubectl/pkg/cmd/portforward/portforward.go#L389

[2] staging/src/k8s.io/client-go/tools/portforward/portforward.go:242: https://github.com/kubernetes/kubernetes/tree/release-1.24/staging/src/k8s.io/client-go/tools/portforward/portforward.go#L242

[3] staging/src/k8s.io/client-go/tools/portforward/portforward.go:330: https://github.com/kubernetes/kubernetes/tree/release-1.24/staging/src/k8s.io/client-go/tools/portforward/portforward.go#L330

[4] pkg/registry/core/pod/rest/subresources.go:185: https://github.com/kubernetes/kubernetes/tree/release-1.24/pkg/registry/core/pod/rest/subresources.go#L185

[5] pkg/kubelet/server/server.go:463: https://github.com/kubernetes/kubernetes/tree/release-1.24/pkg/kubelet/server/server.go#L463

[6] pkg/kubelet/server/server.go:873: https://github.com/kubernetes/kubernetes/tree/release-1.24/pkg/kubelet/server/server.go#L873

[7] pkg/kubelet/cri/streaming/portforward/portforward.go:46: https://github.com/kubernetes/kubernetes/tree/release-1.24/pkg/kubelet/cri/streaming/portforward/portforward.go#L46

[8] pkg/kubelet/cri/streaming/server.go:111: https://github.com/kubernetes/kubernetes/tree/release-1.24/pkg/kubelet/cri/streaming/server.go#L111

[9] pkg/cri/streaming/server.go:149: https://github.com/containerd/containerd/tree/release/1.5/pkg/cri/streaming/server.go#L149

[10] pkg/cri/server/streaming.go:69: https://github.com/containerd/containerd/tree/release/1.5/pkg/cri/server/streaming.go#L69

[11] pkg/cri/server/service.go:138: https://github.com/containerd/containerd/tree/release/1.5/pkg/cri/server/service.go#L138

[12] pkg/cri/server/sandbox_portforward_linux.go:34: https://github.com/containerd/containerd/tree/release/1.5/pkg/cri/server/sandbox_portforward_linux.go#L34

[13] Kubernetes v1.23.0 版本中的 docker shim(1.24 中被移除): https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/kubelet/dockershim/docker_streaming_others.go#L43

責(zé)任編輯:武曉燕 來(lái)源: 云原生指北
相關(guān)推薦

2024-01-18 08:31:22

go實(shí)現(xiàn)gorm框架

2020-07-10 09:04:55

HTTPS瀏覽器網(wǎng)絡(luò)協(xié)議

2021-10-27 16:52:37

LayoutInfl源碼解析

2025-02-06 08:24:25

AQS開發(fā)Java

2011-04-07 15:32:25

2010-09-26 10:09:25

dhcp relay工

2024-05-28 00:00:02

Java線程程序

2018-09-18 10:13:37

2013-05-22 10:39:12

OpenFlowSDN軟件定義網(wǎng)絡(luò)

2021-09-07 06:40:25

AndroidLiveData原理

2011-06-16 15:28:31

正則表達(dá)式

2021-09-09 06:55:43

AndroidViewDragHel原理

2024-09-04 11:42:17

Vue3.5源碼API

2020-10-10 08:20:27

Spring Boot運(yùn)行原理代碼

2013-06-08 10:11:31

Java線程池架構(gòu)

2015-10-10 09:39:42

Java線程池源碼解析

2012-06-29 13:54:11

Java內(nèi)存原型

2010-03-22 14:22:23

智能交換機(jī)

2021-09-08 06:51:52

AndroidRetrofit原理

2024-12-31 08:12:30

容器Pod進(jìn)程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)