成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

CRI shim:kubelet怎么與runtime交互(一)

運維 系統運維
實現了 CRI 接口的容器運行時通常稱為 CRI shim, 這是一個 gRPC Server,監聽在本地的 unix socket 上;而 kubelet 作為 gRPC 的客戶端來調用 CRI 接口,來進行 Pod 和容器、鏡像的生命周期管理。

[[433449]]

CRI shim是什么?

實現了 CRI 接口的容器運行時通常稱為 CRI shim, 這是一個 gRPC Server,監聽在本地的 unix socket 上;而 kubelet 作為 gRPC 的客戶端來調用 CRI 接口,來進行 Pod 和容器、鏡像的生命周期管理。另外,容器運行時需要自己負責管理容器的網絡,推薦使用 CNI。

kubelet 調用下層容器運行時的執行過程,并不會直接調用Docker 的 API,而是通過一組叫作 CRI(Container Runtime Interface,容器運行時接口)的 gRPC 接口來間接執行的,意味著需要使用新的連接方式與 docker 通信,為了兼容以前的版本,k8s 提供了針對 docker 的 CRI 實現,也就是kubelet包下的dockershim包,dockershim是一個 grpc 服務,監聽一個端口供 kubelet 連接,dockershim收到 kubelet 的請求后,將其轉化為 REST API 請求,再發送給docker daemon。Kubernetes 項目之所以要在 kubelet 中引入這樣一層單獨的抽象,當然是為了對 Kubernetes 屏蔽下層容器運行時的差異。

解決思路再次體現了《代碼大全2》里提到的那句經典名言:any problem in computer science can be sloved by another layer of indirecition。計算機科學領域的任何問題都可以通過增加一個中間層來解決,我們的 CRI shim就是加了這樣一層。

CRI shim server 接口圖示

**CRI 接口包括 RuntimeService 和 ImageService 兩個服務,這兩個服務可以在一個 gRPC server 中實現,也可以分開成兩個獨立服務。**目前社區的很多運行時都是將其在一個 gRPC server 里面實現。

ImageServiceServer 提供了 5 個接口,用于管理容器鏡像。管理鏡像的 ImageService 提供了 5 個接口:

  • 查詢鏡像列表;
  • 拉取鏡像到本地;
  • 查詢鏡像狀態;
  • 刪除本地鏡像;
  • 查詢鏡像占用空間等。

關于容器鏡像的操作比較簡單,所以我們就暫且略過。接下來,我主要為你講解一下 RuntimeService 部分。RuntimeService 則提供了更多的接口,按照功能可以劃分為四組:

  • PodSandbox 的管理接口:CRI 設計的一個重要原則,就是確保這個接口本身,只關注容器,不關注 Pod。
  • PodSandbox 是對 Kubernete Pod 的抽象,用來給容器提供一個隔離的環境(比如掛載到相同的 CGroup 下面),并提供網絡等共享的命名空間。PodSandbox 通常對應到一個 Pause 容器或者一臺虛擬機;
  • Container 的管理接口:在指定的 PodSandbox 中創建、啟動、停止和刪除容器;

  • Streaming API 接口:包括 Exec、Attach 和 PortForward 等三個和容器進行數據交互的接口,這三個接口返回的是運行時 Streaming Server 的 URL,而不是直接跟容器交互。kubelet 需要跟容器項目維護一個長連接來傳輸數據。這種 API,我們就稱之為 Streaming API。
  • 狀態接口:包括查詢 API 版本和查詢運行時狀態。

我們通過 kubectl 命令來運行一個 Pod,那么 Kubelet 就會通過 CRI 執行以下操作:

  • 首先調用 RunPodSandbox 接口來創建一個 Pod 容器,Pod 容器是用來持有容器的相關資源的,比如說網絡空間、PID空間、進程空間等資源;
  • 然后調用 CreatContainer 接口在 Pod 容器的空間創建業務容器;
  • 再調用 StartContainer 接口啟動運行容器
  • 最后調用停止,銷毀容器的接口為 StopContainer 與 RemoveContainer。

就完成了整個Container的生命周期。

Streaming API

CRI shim 對 Streaming API 的實現,依賴于一套獨立的 Streaming Server 機制。Streaming API 用于客戶端與容器進行交互,包括 Exec、PortForward 和 Attach 等三個接口。kubelet 內置的 Docker 通過 nsenter、socat 等方法來支持這些特性,但它們不一定適用于其他的運行時,也不支持 Linux 之外的其他平臺。因而,CRI 也顯式定義了這些 API,并且要求容器運行時返回一個 Streaming Server 的 URL 以便 kubelet 重定向 API Server 發送過來的流式請求。

因為所有容器的流式請求都會經過 kubelet,這可能會給節點的網絡流量帶來瓶頸,因而 CRI 要求容器運行時啟動一個對應請求的單獨的流服務器,將地址返回給 kubelet。kubelet 將這個信息再返回給 Kubernetes API Server,會直接打開與運行時提供的服務器相連的流連接,并通過它與客戶端連通。

這樣一個完整的 Exec 流程就如上圖所示,分為多個階段:

  • 客戶端 kubectl exec -i -t ...;
  • kube-apiserver 向 kubelet 發送流式請求 /exec/;
  • kubelet 通過 CRI 接口向 CRI Shim 請求 Exec 的 URL;
  • CRI Shim 向 kubelet 返回 Exec URL;
  • kubelet 向 kube-apiserver 返回重定向的響應;
  • kube-apiserver 重定向流式請求到 Exec URL,然后將 CRI Shim 內部的 Streaming Server 跟 kube-apiserver 進行數據交互,完成 Exec 的請求和響應。

也就是說 apiserver 其實實際上是跟 streaming server 交互來獲取我們的流式數據的。這樣一來讓我們的整個 CRI Server 接口更輕量、更可靠。

注意:當然,這個 Streaming Server 本身,是需要通過使用 SIG-Node 為你維護的 Streaming API 庫來實現的。并且,Streaming Server 會在 CRI shim 啟動時就一起啟動。此外,Stream Server 這一部分具體怎么實現,完全可以由 CRI shim 的維護者自行決定。比如,對于 Docker 項目來說,dockershim 就是直接調用 Docker 的 Exec API 來作為實現的。

CRI-containerd架構解析與主要接口解析

整個架構看起來非常直觀。這里的 Meta services、Runtime service 與 Storage service 都是 containerd 提供的接口。它們是通用的容器相關的接口,包括鏡像管理、容器運行時管理等。CRI 在這之上包裝了一個 gRPC 的服務。右側就是具體的容器的實現。比如說,創建容器時就要創建具體的 runtime 和它的containerd-shim。Container 和 Pod Sandbox組成了一個Pod。

CRI-containerd 的一個好處是,containerd 還額外實現了更豐富的容器接口,所以它可以用 containerd 提供的 ctr 工具來調用這些豐富的容器運行時接口,而不只是 CRI 接口

CRI實現了兩個GRPC協議的API,提供兩種服務ImageService和RuntimeService。

  1. // grpcServices are all the grpc services provided by cri containerd. 
  2. type grpcServices interface { 
  3.   runtime.RuntimeServiceServer 
  4.   runtime.ImageServiceServer 
  5. // CRIService is the interface implement CRI remote service server. 
  6. type CRIService interface { 
  7.   Run() error 
  8.   // io.Closer is used by containerd to gracefully stop cri service. 
  9.   io.Closer 
  10.   plugin.Service 
  11.   grpcServices 

CRI的實現CRIService中包含了很多重要的組件:其中最重要的是cni.CNI,用于配置容器網絡。還有containerd.Client,用于連接containerd來創建容器。

  1. // criService implements CRIService. 
  2. type criService struct { 
  3.  // config contains all configurations. 
  4.  config criconfig.Config 
  5.  // imageFSPath is the path to image filesystem. 
  6.  imageFSPath string 
  7.  // os is an interface for all required os operations. 
  8.  os osinterface.OS 
  9.  // sandboxStore stores all resources associated with sandboxes. 
  10.  sandboxStore *sandboxstore.Store 
  11.  // sandboxNameIndex stores all sandbox names and make sure each name 
  12.  // is unique
  13.  sandboxNameIndex *registrar.Registrar 
  14.  // containerStore stores all resources associated with containers. 
  15.  containerStore *containerstore.Store 
  16.  // containerNameIndex stores all container names and make sure each 
  17.  // name is unique
  18.  containerNameIndex *registrar.Registrar 
  19.  // imageStore stores all resources associated with images. 
  20.  imageStore *imagestore.Store 
  21.  // snapshotStore stores information of all snapshots. 
  22.  snapshotStore *snapshotstore.Store 
  23.  // netPlugin is used to setup and teardown network when run/stop pod sandbox. 
  24.  netPlugin cni.CNI 
  25.  // client is an instance of the containerd client 
  26.  client *containerd.Client 
  27.  // streamServer is the streaming server serves container streaming request. 
  28.  streamServer streaming.Server 
  29.  // eventMonitor is the monitor monitors containerd events. 
  30.  eventMonitor *eventMonitor 
  31.  // initialized indicates whether the server is initialized. All GRPC services 
  32.  // should return error before the server is initialized. 
  33.  initialized atomic.Bool 
  34.  // cniNetConfMonitor is used to reload cni network conf if there is 
  35.  // any valid fs change events from cni network conf dir. 
  36.  cniNetConfMonitor *cniNetConfSyncer 
  37.  // baseOCISpecs contains cached OCI specs loaded via `Runtime.BaseRuntimeSpec` 
  38.  baseOCISpecs map[string]*oci.Spec 

我們知道 Kubernetes 的一個運作的機制是面向終態的,在每一次調協的循環中,Kubelet 會向 apiserver 獲取調度到本 Node 的 Pod 的數據,再做一個面向終態的處理,以達到我們預期的狀態。

循環的第一步,首先通過 List 接口拿到容器的狀態。確保有鏡像,如果沒有鏡像則 pull 鏡像再通過 Sandbox 和 Container 接口來創建容器。需要注意的是,我們的 CNI(容器網絡接口)也是在 CRI 進行操作的,因為我們在創建 Pod 的時候需要同時創建網絡資源然后注入到 Pod 中(PS:CNI包含在創建Pod 這個動作里)。接下來就是我們的容器和鏡像。我們通過具體的容器創建引擎來創建一個具體的容器。

執行流程為:

  • Kubelet 通過 CRI runtime service API 調用 CRI plugin 創建 pod
  • CRI 通過 CNI 創建 pod 的網絡配置和 namespace
  • CRI使用 containerd 創建并啟動 pause container (sandbox container) 并且把這個 container 置于 pod 的 cgroups/namespace
  • Kubelet 接著通過 CRI image service API 調用 CRI plugin, 獲取容器鏡像
  • CRI 通過 containerd 獲取容器鏡像
  • Kubelet 通過 CRI runtime service API 調用 CRI, 在 pod 的空間使用拉取的鏡像啟動容器
  • CRI 通過 containerd 創建/啟動 應用容器, 并且把 container 置于 pod 的 cgroups/namespace. Pod 完成啟動。

總結

發現 CRI 只是服務于 Kubernetes 的,而且它呈現向上匯報的狀態。它是幫助 Kubernetes 的,它不幫助OCI的。所以說當你去做這個集成時候,你會發現尤其對于 VM gVisor\KataContainer 來說,它與 CRI 的很多假設或者是 API 的寫法上是不對應的。所以你的集成工作會比較費勁,這是一個不 match 的狀態。

最后一個就是我們維護起來非常困難,因為由于有了 CRI 之后,比如 RedHat 擁有自己的 CRI 實現叫 cri-o,他們和 containerd 在本質上沒有任何區別,跑到最后都是靠 runC 起容器,為什么還需要cri-o這種東西?

我們不知道,如果我想使用Kata container與containerd多運行時的話,我需要給他們兩個分別寫兩部分的一體化把 Kata 集成進去。這就很麻煩,就意味著我有 100 種這樣的 CRI ,我就要寫 100 個shim去集成,而且他們的功能全部都是重復的。

所以這就產生了Containerd ShimV2的這樣的shim來解決這個問題。我們下回分解。

reference

https://time.geekbang.org/column/article/71499?utm_campaign=guanwang&utm_source=baidu-ad&utm_medium=ppzq-pc&utm_content=title&utm_term=baidu-ad-ppzq-title

https://blog.frognew.com/2021/04/relearning-container-02.html

https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md

https://developer.aliyun.com/article/679993

本文轉載自微信公眾號「運維開發故事」

責任編輯:姜華 來源: 運維開發故事
相關推薦

2021-12-23 07:58:06

Kubelet容器運行

2024-07-15 18:20:18

2023-09-07 07:17:01

KubernetesCRI標準

2015-08-06 15:13:49

runtimeIOS開發

2023-01-10 13:48:50

ContainerdCRI源碼

2014-07-29 11:16:07

2015-03-25 13:42:42

ZAKER

2010-08-10 17:01:48

FlexJavaScript

2017-10-18 12:22:43

NativeHybirdJavaScript

2021-08-30 09:44:47

Kubelet機制驅逐

2023-08-29 08:20:35

Kubernete跨云容器

2009-06-10 21:46:02

JavaScript與

2014-09-16 11:17:36

AndroidService交互方式

2015-08-17 09:46:15

UIjs

2011-06-13 09:04:39

QT Flash 交互

2009-07-01 14:42:30

JSP和XML

2025-03-03 08:05:14

2015-09-07 09:53:02

Objective-CRuntime

2022-05-16 11:17:01

應用開發JSJAVA

2017-01-16 16:24:14

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产日韩欧美在线 | 日韩欧美在线观看一区 | 国产在线视频一区 | 欧美福利视频 | 欧美一级久久 | 一区亚洲 | 国产乱码一区 | 亚洲精品亚洲人成人网 | 成人黄页在线观看 | 婷婷精品 | 精品久久国产 | 亚洲日韩中文字幕一区 | 精品久久久久久久 | 日韩欧美在线观看视频 | 人操人人干人 | 国产伦精品一区二区三区在线 | 日本超碰 | 天天射天天干 | 国产日韩欧美一区二区 | 精品欧美久久 | 日韩精品久久久 | 中文字幕高清视频 | 久久久xx| 91网站在线看| 四虎影院免费在线 | 国产精品中文字幕在线 | 一区二区三区久久久 | www成人免费视频 | 国产午夜久久久 | 99视频精品| 日韩欧美专区 | 最新高清无码专区 | 99这里只有精品视频 | 国产欧美日韩久久久 | 国产精品二区三区 | 91久久精品一区二区三区 | 91精品国产一区二区三区香蕉 | 91av免费版| 天堂综合 | 婷婷久久网 | 国产专区在线 |