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

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

運(yùn)維 系統(tǒng)運(yùn)維
實(shí)現(xiàn)了 CRI 接口的容器運(yùn)行時通常稱為 CRI shim, 這是一個 gRPC Server,監(jiān)聽在本地的 unix socket 上;而 kubelet 作為 gRPC 的客戶端來調(diào)用 CRI 接口,來進(jìn)行 Pod 和容器、鏡像的生命周期管理。

[[433449]]

CRI shim是什么?

實(shí)現(xiàn)了 CRI 接口的容器運(yùn)行時通常稱為 CRI shim, 這是一個 gRPC Server,監(jiān)聽在本地的 unix socket 上;而 kubelet 作為 gRPC 的客戶端來調(diào)用 CRI 接口,來進(jìn)行 Pod 和容器、鏡像的生命周期管理。另外,容器運(yùn)行時需要自己負(fù)責(zé)管理容器的網(wǎng)絡(luò),推薦使用 CNI。

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

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

CRI shim server 接口圖示

**CRI 接口包括 RuntimeService 和 ImageService 兩個服務(wù),這兩個服務(wù)可以在一個 gRPC server 中實(shí)現(xiàn),也可以分開成兩個獨(dú)立服務(wù)。**目前社區(qū)的很多運(yùn)行時都是將其在一個 gRPC server 里面實(shí)現(xiàn)。

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

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

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

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

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

我們通過 kubectl 命令來運(yùn)行一個 Pod,那么 Kubelet 就會通過 CRI 執(zhí)行以下操作:

  • 首先調(diào)用 RunPodSandbox 接口來創(chuàng)建一個 Pod 容器,Pod 容器是用來持有容器的相關(guān)資源的,比如說網(wǎng)絡(luò)空間、PID空間、進(jìn)程空間等資源;
  • 然后調(diào)用 CreatContainer 接口在 Pod 容器的空間創(chuàng)建業(yè)務(wù)容器;
  • 再調(diào)用 StartContainer 接口啟動運(yùn)行容器
  • 最后調(diào)用停止,銷毀容器的接口為 StopContainer 與 RemoveContainer。

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

Streaming API

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

因?yàn)樗腥萜鞯牧魇秸埱蠖紩?jīng)過 kubelet,這可能會給節(jié)點(diǎn)的網(wǎng)絡(luò)流量帶來瓶頸,因而 CRI 要求容器運(yùn)行時啟動一個對應(yīng)請求的單獨(dú)的流服務(wù)器,將地址返回給 kubelet。kubelet 將這個信息再返回給 Kubernetes API Server,會直接打開與運(yùn)行時提供的服務(wù)器相連的流連接,并通過它與客戶端連通。

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

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

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

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

CRI-containerd架構(gòu)解析與主要接口解析

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

CRI-containerd 的一個好處是,containerd 還額外實(shí)現(xiàn)了更豐富的容器接口,所以它可以用 containerd 提供的 ctr 工具來調(diào)用這些豐富的容器運(yùn)行時接口,而不只是 CRI 接口

CRI實(shí)現(xiàn)了兩個GRPC協(xié)議的API,提供兩種服務(wù)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的實(shí)現(xiàn)CRIService中包含了很多重要的組件:其中最重要的是cni.CNI,用于配置容器網(wǎng)絡(luò)。還有containerd.Client,用于連接containerd來創(chuàng)建容器。

  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 的一個運(yùn)作的機(jī)制是面向終態(tài)的,在每一次調(diào)協(xié)的循環(huán)中,Kubelet 會向 apiserver 獲取調(diào)度到本 Node 的 Pod 的數(shù)據(jù),再做一個面向終態(tài)的處理,以達(dá)到我們預(yù)期的狀態(tài)。

循環(huán)的第一步,首先通過 List 接口拿到容器的狀態(tài)。確保有鏡像,如果沒有鏡像則 pull 鏡像再通過 Sandbox 和 Container 接口來創(chuàng)建容器。需要注意的是,我們的 CNI(容器網(wǎng)絡(luò)接口)也是在 CRI 進(jìn)行操作的,因?yàn)槲覀冊趧?chuàng)建 Pod 的時候需要同時創(chuàng)建網(wǎng)絡(luò)資源然后注入到 Pod 中(PS:CNI包含在創(chuàng)建Pod 這個動作里)。接下來就是我們的容器和鏡像。我們通過具體的容器創(chuàng)建引擎來創(chuàng)建一個具體的容器。

執(zhí)行流程為:

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

總結(jié)

發(fā)現(xiàn) CRI 只是服務(wù)于 Kubernetes 的,而且它呈現(xiàn)向上匯報的狀態(tài)。它是幫助 Kubernetes 的,它不幫助OCI的。所以說當(dāng)你去做這個集成時候,你會發(fā)現(xiàn)尤其對于 VM gVisor\KataContainer 來說,它與 CRI 的很多假設(shè)或者是 API 的寫法上是不對應(yīng)的。所以你的集成工作會比較費(fèi)勁,這是一個不 match 的狀態(tài)。

最后一個就是我們維護(hù)起來非常困難,因?yàn)橛捎谟辛? CRI 之后,比如 RedHat 擁有自己的 CRI 實(shí)現(xiàn)叫 cri-o,他們和 containerd 在本質(zhì)上沒有任何區(qū)別,跑到最后都是靠 runC 起容器,為什么還需要cri-o這種東西?

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

所以這就產(chǎn)生了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

本文轉(zhuǎn)載自微信公眾號「運(yùn)維開發(fā)故事」

責(zé)任編輯:姜華 來源: 運(yùn)維開發(fā)故事
相關(guān)推薦

2021-12-23 07:58:06

Kubelet容器運(yùn)行

2024-07-15 18:20:18

2023-09-07 07:17:01

KubernetesCRI標(biāo)準(zhǔn)

2015-08-06 15:13:49

runtimeIOS開發(fā)

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機(jī)制驅(qū)逐

2009-06-10 21:46:02

JavaScript與

2023-08-29 08:20:35

Kubernete跨云容器

2014-09-16 11:17:36

AndroidService交互方式

2015-08-17 09:46:15

UIjs

2009-07-01 14:42:30

JSP和XML

2011-06-13 09:04:39

QT Flash 交互

2025-03-03 08:05:14

2015-09-07 09:53:02

Objective-CRuntime

2022-05-16 11:17:01

應(yīng)用開發(fā)JSJAVA

2017-01-16 16:24:14

點(diǎn)贊
收藏

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

主站蜘蛛池模板: 亚洲欧美一区二区三区国产精品 | 黄色在线免费网站 | 久草福利| av一级久久 | 亚洲视频网 | 色眯眯视频在线观看 | 欧美一区二区三区 | 亚洲天堂男人的天堂 | 久久综合久色欧美综合狠狠 | a级毛片免费高清视频 | 欧美一区二区三区视频在线 | 81精品国产乱码久久久久久 | 九九免费在线视频 | 久久久视频在线 | 欧美国产日韩一区 | 日韩一区二区在线视频 | 日韩网站在线观看 | 日本久久久一区二区三区 | 午夜免费在线电影 | 日韩在线不卡视频 | 精品99爱视频在线观看 | 淫片一级国产 | 亚洲一区二区三区四区五区中文 | 久久久日韩精品一区二区三区 | 一级爱爱片 | 久久久噜噜噜久久中文字幕色伊伊 | 91精品国产一区二区在线观看 | 久久精品青青大伊人av | 日韩成人免费av | 毛片国产 | 欧美高清dvd | 国产一区二区在线免费观看 | 在线成人 | 国产91亚洲精品 | 欧美日韩国产在线观看 | 亚洲欧美一区二区三区国产精品 | 日本涩涩网 | 国产一区二区三区久久久久久久久 | 99热首页| 99久久久久久久 | 久久久区|