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

Kubernetes CRI - 容器運(yùn)行時接口解析

開發(fā) 架構(gòu)
kubelet 本身,也是按照“控制器”模式來工作的。它實(shí)際的工作原理,可以用如下所示的一幅示意圖來表示清楚。

[[430374]]

本文轉(zhuǎn)載自微信公眾號「運(yùn)維開發(fā)故事」,作者沒有文案的夏老師。轉(zhuǎn)載本文請聯(lián)系運(yùn)維開發(fā)故事公眾號。

kubelet 的組件

kubelet 本身,也是按照“控制器”模式來工作的。它實(shí)際的工作原理,可以用如下所示的一幅示意圖來表示清楚。

  • Kubelet Server 對外提供 API,供 kube-apiserver、metrics-server 等服務(wù)調(diào)用。比如 kubectl exec 時需要通過 Kubelet API /exec/{token} 與容器進(jìn)行交互;
  • Container Manager 管理容器的各種資源,比如 CGroups、QoS、cpuset、device 等;
  • Volume Manager 管理容器的存儲卷,比如格式化磁盤、掛載到 Node 本地、最后再將掛載路徑傳給容器;
  • Eviction 負(fù)責(zé)容器的驅(qū)逐,比如在資源不足時驅(qū)逐優(yōu)先級低的容器,保證高優(yōu)先級容器的運(yùn)行;
  • cAdvisor 負(fù)責(zé)為容器提供 Metrics;
  • Metrics 和 stats 提供容器和節(jié)點(diǎn)的度量數(shù)據(jù),比如 metrics-server 通過 /stats/summary 提取的度量數(shù)據(jù)是 HPA 自動擴(kuò)展的依據(jù);
  • Generic Runtime Manager 是容器運(yùn)行時的管理者,負(fù)責(zé)與CRI 交互,完成容器和鏡像的管理;

CRI中定義了容器和鏡像的服務(wù)的接口,因?yàn)槿萜鬟\(yùn)行時與鏡像的生命周期是彼此隔離的,因此需要定義兩個服務(wù)。該接口使用Protocol Buffer,基于gRPC,在Kubernetes v1.10+版本中是在pkg/kubelet/apis/cri/runtime/v1alpha2的api.proto中定義的。

CRI架構(gòu)

Kubernetes 中的容器運(yùn)行時組成

按照不同的功能可以分為四個部分:

(1)kubelet 中容器運(yùn)行時的管理,kubeGenericRuntimeManager,它管理與 CRI shim 通信的客戶端,完成容器和鏡像的管理(代碼位置:pkg/kubelet/kuberuntime/kuberuntime_manager.go);

(2)容器運(yùn)行時接口 CRI,包括了容器運(yùn)行時客戶端接口與容器運(yùn)行時服務(wù)端接口;

(3)CRI shim 客戶端,kubelet 持有,用于與 CRI shim 服務(wù)端進(jìn)行通信;

(4)CRI shim 服務(wù)端,即具體的容器運(yùn)行時實(shí)現(xiàn),包括 kubelet 內(nèi)置的 dockershim (代碼位置:pkg/kubelet/dockershim)以及外部的容器運(yùn)行時remote。如 cri-containerd(用于支持容器引擎containerd)、rktlet(用于支持容器引擎rkt)等。

更普遍的場景,就是你需要在每臺宿主機(jī)上單獨(dú)安裝一個負(fù)責(zé)響應(yīng) CRI 的組件。這個組件,一般被稱作 CRI shim。顧名思義,CRI shim 的工作,就是扮演 kubelet 與容器項(xiàng)目之間的“墊片”(shim)。所以它的作用非常單一,那就是實(shí)現(xiàn) CRI 規(guī)定的每個接口,然后把具體的 CRI 請求“翻譯”成對后端容器項(xiàng)目的請求或者操作。如下所示

CRI gRPC Server的具體實(shí)現(xiàn)

Container Runtime實(shí)現(xiàn)了CRI gRPC Server,包括RuntimeService和ImageService。該gRPC Server需要監(jiān)聽本地的Unix socket,而kubelet則作為gRPC Client運(yùn)行。CRI 接口包括 RuntimeService 和 ImageService 兩個服務(wù),這兩個服務(wù)可以在一個 gRPC server 中實(shí)現(xiàn),也可以分開成兩個獨(dú)立服務(wù)。目前社區(qū)的很多運(yùn)行時都是將其在一個 gRPC server 里面實(shí)現(xiàn)。這其中包含了兩個gRPC服務(wù):

看一下源碼,Kubernetes 1.20中的CRI接口在api.proto中的定義如下:

  1. // Runtime service defines the public APIs for remote container runtimes 
  2. service RuntimeService { 
  3.     // Version returns the runtime name, runtime version, and runtime API version. 
  4.     rpc Version(VersionRequest) returns (VersionResponse) {} 
  5.  
  6.     // RunPodSandbox creates and starts a pod-level sandbox. Runtimes must ensure 
  7.     // the sandbox is in the ready state on success. 
  8.     rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {} 
  9.     // StopPodSandbox stops any running process that is part of the sandbox and 
  10.     // reclaims network resources (e.g., IP addresses) allocated to the sandbox. 
  11.     // If there are any running containers in the sandbox, they must be forcibly 
  12.     // terminated. 
  13.     // This call is idempotent, and must not return an error if all relevant 
  14.     // resources have already been reclaimed. kubelet will call StopPodSandbox 
  15.     // at least once before calling RemovePodSandbox. It will also attempt to 
  16.     // reclaim resources eagerly, as soon as a sandbox is not needed. Hence, 
  17.     // multiple StopPodSandbox calls are expected. 
  18.     rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {} 
  19.     // RemovePodSandbox removes the sandbox. If there are any running containers 
  20.     // in the sandbox, they must be forcibly terminated and removed. 
  21.     // This call is idempotent, and must not return an error if the sandbox has 
  22.     // already been removed. 
  23.     rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {} 
  24.     // PodSandboxStatus returns the status of the PodSandbox. If the PodSandbox is not 
  25.     // present, returns an error. 
  26.     rpc PodSandboxStatus(PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {} 
  27.     // ListPodSandbox returns a list of PodSandboxes. 
  28.     rpc ListPodSandbox(ListPodSandboxRequest) returns (ListPodSandboxResponse) {} 
  29.  
  30.     // CreateContainer creates a new container in specified PodSandbox 
  31.     rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {} 
  32.     // StartContainer starts the container. 
  33.     rpc StartContainer(StartContainerRequest) returns (StartContainerResponse) {} 
  34.     // StopContainer stops a running container with a grace period (i.e., timeout). 
  35.     // This call is idempotent, and must not return an error if the container has 
  36.     // already been stopped. 
  37.     // The runtime must forcibly kill the container after the grace period is 
  38.     // reached. 
  39.     rpc StopContainer(StopContainerRequest) returns (StopContainerResponse) {} 
  40.     // RemoveContainer removes the container. If the container is running, the 
  41.     // container must be forcibly removed. 
  42.     // This call is idempotent, and must not return an error if the container has 
  43.     // already been removed. 
  44.     rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse) {} 
  45.     // ListContainers lists all containers by filters. 
  46.     rpc ListContainers(ListContainersRequest) returns (ListContainersResponse) {} 
  47.     // ContainerStatus returns status of the container. If the container is not 
  48.     // present, returns an error. 
  49.     rpc ContainerStatus(ContainerStatusRequest) returns (ContainerStatusResponse) {} 
  50.     // UpdateContainerResources updates ContainerConfig of the container. 
  51.     rpc UpdateContainerResources(UpdateContainerResourcesRequest) returns (UpdateContainerResourcesResponse) {} 
  52.     // ReopenContainerLog asks runtime to reopen the stdout/stderr log file 
  53.     // for the container. This is often called after the log file has been 
  54.     // rotated. If the container is not running, container runtime can choose 
  55.     // to either create a new log file and return nil, or return an error. 
  56.     // Once it returns error, new container log file MUST NOT be created. 
  57.     rpc ReopenContainerLog(ReopenContainerLogRequest) returns (ReopenContainerLogResponse) {} 
  58.  
  59.     // ExecSync runs a command in a container synchronously. 
  60.     rpc ExecSync(ExecSyncRequest) returns (ExecSyncResponse) {} 
  61.     // Exec prepares a streaming endpoint to execute a command in the container. 
  62.     rpc Exec(ExecRequest) returns (ExecResponse) {} 
  63.     // Attach prepares a streaming endpoint to attach to a running container. 
  64.     rpc Attach(AttachRequest) returns (AttachResponse) {} 
  65.     // PortForward prepares a streaming endpoint to forward ports from a PodSandbox. 
  66.     rpc PortForward(PortForwardRequest) returns (PortForwardResponse) {} 
  67.  
  68.     // ContainerStats returns stats of the container. If the container does not 
  69.     // exist, the call returns an error. 
  70.     rpc ContainerStats(ContainerStatsRequest) returns (ContainerStatsResponse) {} 
  71.     // ListContainerStats returns stats of all running containers. 
  72.     rpc ListContainerStats(ListContainerStatsRequest) returns (ListContainerStatsResponse) {} 
  73.  
  74.     // PodSandboxStats returns stats of the pod. If the pod sandbox does not 
  75.     // exist, the call returns an error. 
  76.     rpc PodSandboxStats(PodSandboxStatsRequest) returns (PodSandboxStatsResponse) {} 
  77.     // ListPodSandboxStats returns stats of the pods matching a filter. 
  78.     rpc ListPodSandboxStats(ListPodSandboxStatsRequest) returns (ListPodSandboxStatsResponse) {} 
  79.  
  80.     // UpdateRuntimeConfig updates the runtime configuration based on the given request. 
  81.     rpc UpdateRuntimeConfig(UpdateRuntimeConfigRequest) returns (UpdateRuntimeConfigResponse) {} 
  82.  
  83.     // Status returns the status of the runtime. 
  84.     rpc Status(StatusRequest) returns (StatusResponse) {} 
  85.  
  86. // ImageService defines the public APIs for managing images. 
  87. service ImageService { 
  88.     // ListImages lists existing images. 
  89.     rpc ListImages(ListImagesRequest) returns (ListImagesResponse) {} 
  90.     // ImageStatus returns the status of the image. If the image is not 
  91.     // present, returns a response with ImageStatusResponse.Image set to 
  92.     // nil. 
  93.     rpc ImageStatus(ImageStatusRequest) returns (ImageStatusResponse) {} 
  94.     // PullImage pulls an image with authentication config. 
  95.     rpc PullImage(PullImageRequest) returns (PullImageResponse) {} 
  96.     // RemoveImage removes the image. 
  97.     // This call is idempotent, and must not return an error if the image has 
  98.     // already been removed. 
  99.     rpc RemoveImage(RemoveImageRequest) returns (RemoveImageResponse) {} 
  100.     // ImageFSInfo returns information of the filesystem that is used to store images. 
  101.     rpc ImageFsInfo(ImageFsInfoRequest) returns (ImageFsInfoResponse) {} 

RuntimeService

RuntimeService 則提供了更多的接口,按照功能可以劃分為四組:

  • PodSandbox 的管理接口: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,而不是直接跟容器交互;

狀態(tài)接口:包括查詢 API 版本和查詢運(yùn)行時狀態(tài)。

ImageService

管理鏡像的 ImageService 提供了 5 個接口:

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

這些都很容易映射到 Docker API 或者CRI上面。

CRI相關(guān)初始化

跟容器最相關(guān)的一個 Manager 是 Generic Runtime Manager,就是一個通用的運(yùn)行時管理器。我們可以看到目前 dockershim 還是存在于 Kubelet 的代碼中的,它是當(dāng)前性能最穩(wěn)定的一個容器運(yùn)行時的實(shí)現(xiàn)。remote 指的就是 CRI 接口。CRI 接口主要包含兩個部分:

  • 一個是 CRI Server,即通用的比如說創(chuàng)建、刪除容器這樣的接口;
  • 另外一個是流式數(shù)據(jù)的接口 Streaming Server,比如 exec、port-forward 這些流式數(shù)據(jù)的接口。

CNI(容器網(wǎng)絡(luò)接口)也是在 CRI 進(jìn)行操作的,因?yàn)槲覀冊趧?chuàng)建 Pod 的時候需要同時創(chuàng)建網(wǎng)絡(luò)資源然后注入到 Pod 中。接下來就是我們的容器和鏡像。我們通過具體的容器創(chuàng)建引擎來創(chuàng)建一個具體的容器。kubelet中CRI相關(guān)初始化邏輯如下:

(1)當(dāng)kubelet選用dockershim作為容器運(yùn)行時,則初始化并啟動容器運(yùn)行時服務(wù)端dockershim(初始化dockershim過程中也會初始化網(wǎng)絡(luò)插件CNI)。

  • 如果是外部外部容器運(yùn)行時的時候,需要在每臺宿主機(jī)上單獨(dú)安裝一個負(fù)責(zé)響應(yīng) CRI 的組件。這個組件就是CRI shim,需要包含網(wǎng)絡(luò)插件CNI。比如支持containerd的CRI-Containerd的shim。到了 containerd 1.1 版本后就去掉了 CRI-Containerd 這個 shim,直接把適配邏輯作為插件的方式集成到了 containerd 主進(jìn)程中,所以我們現(xiàn)在可以直接使用--container-runtime-endpoint=unix:///run/containerd/containerd.sock這個套接字,就可以無縫切換的containerd。

(2)初始化容器運(yùn)行時CRI shim客戶端(用于調(diào)用CRI shim服務(wù)端:內(nèi)置的容器運(yùn)行時dockershim或remote容器運(yùn)行時);

(3)初始化Generic Runtime Manager,用于容器運(yùn)行時的管理。初始化完成后,后續(xù)kubelet對容器以及鏡像的相關(guān)操作都會通過該結(jié)構(gòu)體持有的CRI shim客戶端,與CRI shim服務(wù)端進(jìn)行通信來完成。

下面來簡單分析幾個比較重要的CRI相關(guān)啟動參數(shù):(1)--container-runtime:指定kubelet要使用的容器運(yùn)行時,可選值docker、remote、rkt (deprecated),默認(rèn)值為docker,即使用kubelet內(nèi)置的容器運(yùn)行時dockershim。當(dāng)需要使用外部容器運(yùn)行時,該參數(shù)配置為remote,并設(shè)置--container-runtime-endpoint參數(shù)值為監(jiān)聽的 unix socket位置。(2)--runtime-cgroups:容器運(yùn)行時使用的cgroups,可選值。(3)--docker-endpoint:docker暴露服務(wù)的socket地址,默認(rèn)值為unix:///var/run/docker.sock,該參數(shù)配置當(dāng)且僅當(dāng)--container-runtime參數(shù)值為docker時有效。(4)--pod-infra-container-image:pod sandbox的鏡像地址,默認(rèn)值為k8s.gcr.io/pause:3.5,該參數(shù)配置當(dāng)且僅當(dāng)--container-runtime參數(shù)值為docker時有效。(5)--image-pull-progress-deadline:容器鏡像拉取超時時間,默認(rèn)值為1分鐘,該參數(shù)配置當(dāng)且僅當(dāng)--container-runtime參數(shù)值為docker時有效。(6)--experimental-dockershim:設(shè)置為true時,啟用dockershim模式,只啟動dockershim,默認(rèn)值為false,該參數(shù)配置當(dāng)且僅當(dāng)--container-runtime參數(shù)值為docker時有效。(7)--experimental-dockershim-root-directory:dockershim根目錄,默認(rèn)值為/var/lib/dockershim,該參數(shù)配置當(dāng)且僅當(dāng)--container-runtime參數(shù)值為docker時有效。(8)--container-runtime-endpoint:容器運(yùn)行時的endpoint,linux中默認(rèn)值為unix:///var/run/dockershim.sock,注意與上面的--docker-endpoint區(qū)分開來。

  • unix:///var/run/dockershim.sock
  • unix:///run/containerd/containerd.sock,即使用本地的containerd作為容器運(yùn)行時。
  • 默認(rèn)是unix:///var/run/dockershim.sock,即默認(rèn)使用本地的docker作為容器運(yùn)行時。

(簡單介紹一下socket通信之Unix domain socket:Unix domain socket 又叫 IPC(inter-process communication 進(jìn)程間通信。用于實(shí)現(xiàn)同一主機(jī)上的進(jìn)程間通信。socket 原本是為網(wǎng)絡(luò)通訊設(shè)計的,但后來在 socket 的框架上發(fā)展出一種 IPC 機(jī)制,就是 UNIX domain socket。雖然網(wǎng)絡(luò) socket 也可用于同一臺主機(jī)的進(jìn)程間通訊(通過 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要經(jīng)過網(wǎng)絡(luò)協(xié)議棧,不需要打包拆包、計算校驗(yàn)和、維護(hù)序號和應(yīng)答等,只是將應(yīng)用層數(shù)據(jù)從一個進(jìn)程拷貝到另一個進(jìn)程。這是因?yàn)?,IPC 機(jī)制本質(zhì)上是可靠的通訊,而網(wǎng)絡(luò)協(xié)議是為不可靠的通訊設(shè)計的。)

(9)--image-service-endpoint:鏡像服務(wù)的endpoint,linux中默認(rèn)值為unix:///var/run/dockershim.sock。

當(dāng)前支持的CRI后端

我們最初在使用Kubernetes時通常會默認(rèn)使用Docker作為容器運(yùn)行時,其實(shí)從Kubernetes 1.5開始已經(jīng)開始支持CRI,目前是處于Alpha版本,通過CRI接口可以指定使用其它容器運(yùn)行時作為Pod的后端,docker、containerd、CRI-O、Frakti、pouch,它們銜接Kubelet與運(yùn)行時方式對比如下:

棄用 docker 后到底會產(chǎn)生什么影響

正常的 K8s 用戶不會有任何影響

生產(chǎn)環(huán)境中高版本的集群只需要把運(yùn)行時從 docker 切換到 containerd即可。containerd 是 docker 中的一個底層組件,主要負(fù)責(zé)維護(hù)容器的生命周期,跟隨 docker 經(jīng)歷了長期考驗(yàn)。同時 2019年初就從 CNCF 畢業(yè),可以單獨(dú)作為容器運(yùn)行時用在集群中。到了 containerd 1.1 版本后就去掉了 CRI-Containerd 這個 shim,直接把適配邏輯作為插件的方式集成到了 containerd 主進(jìn)程中,所以我們現(xiàn)在可以直接使用--container-runtime-endpoint=unix:///run/containerd/containerd.sock這個套接字,就可以無縫切換的containerd。因此把 runtime 從 docker 轉(zhuǎn)換到 containerd 是一個基本無痛的過程。

  • 開發(fā)環(huán)境中通過docker build構(gòu)建出來的鏡像依然可以在集群中使用鏡像一直是容器生態(tài)的一大優(yōu)勢,雖然人們總是把鏡像稱之為“docker鏡像”,但鏡像早就成為了一種規(guī)范了。具體規(guī)范可以參考image-spec。在任何地方只要構(gòu)建出符合 Image Spec 的鏡像,就可以拿到其他符合 Image Spec 的容器運(yùn)行時上運(yùn)行。如果你是一名開發(fā)/運(yùn)維人員,你依舊可以繼續(xù)使用 Docker 來構(gòu)建鏡像,以相同的方式將鏡像推送到 Registry,并且將這些鏡像部署到你的 Kubernetes 中;如果你是運(yùn)行和操作集群的用戶,你只需要將 Docker 切換成你需要的containerd 容器運(yùn)行時即可。
  • 在 Pod 中使用 DinD(Docker in Docker)的用戶會受到影響

有些使用者會把 docker 的 socket (/run/docker.sock)掛載到 Pod 中,并在 Pod 中調(diào)用 docker 的 api 構(gòu)建鏡像或創(chuàng)建編譯容器等,官方在這里的建議是使用 Kaniko、Img 或 Buildah。

2.我們可以通過把 docker daemon 作為 DaemonSet 或者給想要使用 docker 的 Pod 添加一個 docker daemon 的 sidecar 的方式在任意運(yùn)行時中使用 DinD 的方案。

3.同一集群中docker 節(jié)點(diǎn)與 containerd 節(jié)點(diǎn)共存,通過按節(jié)點(diǎn)標(biāo)簽調(diào)度,保 證這類業(yè)務(wù)調(diào)度到 docker 節(jié)點(diǎn)沒有通過上述方案。

預(yù)告

后期會圍繞runc,shim等探索容器的底層實(shí)現(xiàn)與管理API的暴露。敬請期待!!!!

reference

 

https://feisky.xyz/posts/kubernetes-container-runtime/https://jimmysong.io/kubernetes-handbook/concepts/cri.htmlhttps://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2221-remove-dockershimhttps://kubernetes.io/zh/docs/setup/production-environment/container-runtimes/https://www.qikqiak.com/post/containerd-usage/https://kubernetes.io/zh/blog/2020/12/02/dockershim-faq/https://github.com/containerdhttps://www.zhihu.com/question/324124344

 

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

2023-08-29 08:20:35

Kubernete跨云容器

2019-07-12 09:30:12

DashboardDockerDNS

2021-12-23 07:58:06

Kubelet容器運(yùn)行

2023-04-03 13:01:14

UbuntuCRI-O

2024-03-20 10:46:00

云原生容器

2021-09-11 15:38:23

容器運(yùn)行鏡像開放

2025-03-03 08:05:14

2023-01-03 09:10:21

2021-09-02 05:37:22

Containerd Kubernetes 容器

2020-08-11 08:59:20

容器虛擬化技術(shù)

2015-07-20 15:44:46

Swift框架MJExtension反射

2021-08-18 06:40:54

KubernetesDocker Containerd

2024-03-21 09:15:58

JS運(yùn)行的JavaScrip

2020-12-07 08:14:17

KubernetesDocker容器

2021-11-05 08:07:57

kubeletKubernetesContainerd

2009-09-24 17:19:06

運(yùn)行時多態(tài)性

2021-08-18 08:32:09

代碼運(yùn)行時間示波器

2013-11-26 16:49:55

Android開發(fā)運(yùn)行時KitKat

2020-12-07 13:31:43

GoMutex開發(fā)者

2023-07-28 10:42:43

點(diǎn)贊
收藏

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