CRI shim:Kubelet 怎么与容器运行时交互之二

开发 架构
今天给大家 propose 的这个东西叫做 Containerd ShimV2。前面我们说过 CRI,CRI 决定的是 Runtime 和 Kubernetes 之间的关系,那么我们现在能不能再有一层更细致的 API 来决定我的 CRI Shim 跟下面的 Runtime 之间真正的接口是什么样的?

[[441669]]

前言

通过《CRI shim:kubelet怎么与容器运行时交互(一)》这一篇文章,我们知道了:

  • 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去集成,而且他们的功能全部都是重复的。
  • 多容器运行时用于不同目的,比如使用虚拟化容器引擎式运行不可信应用和多租户应用,而使用 Docker 运行系统组件或者无法虚拟化的容器(比如需要 HostNetwork 的容器。

所以这就产生了Containerd ShimV2的这样的shim来解决这个问题。

Containerd ShimV2

2018 年,由 containerd 社区主导的 shimv2 API 的出现,在 CRI 的基础上,为用户集成自己的容器运行时带来了更加成熟和方便的实践方法。

今天给大家 propose 的这个东西叫做 Containerd ShimV2。前面我们说过 CRI,CRI 决定的是 Runtime 和 Kubernetes 之间的关系,那么我们现在能不能再有一层更细致的 API 来决定我的 CRI Shim 跟下面的 Runtime 之间真正的接口是什么样的?

这就是 ShimV2 出现的原因,它是一层 CRI shim 到 Containerd runtime 之间的标准接口,所以前面我直接从 CRI 到 Containerd 到 runC,现在不是。我们是从 CRI 到 Containerd 到 ShimV2,然后 ShimV2 再到 RunC 或者 KataContainer。这么做有什么好处?

我们来看一下,最大的区别在于:在这种方式下,你可以为每一个 Pod 指定一个 Shim。因为在最开始的时候,Containerd 是直接启动了一个 Containerd Shim 来去做响应,但我们新的 API 是这样写的,是 Containerd Shim start 或者 stop。所以这个 start 和 stop 操作怎么去实现是你要做的事情。

现在,我作为一位 Kata Containers项目的维护者我就可以这么实现。我在 created Sandbox 的时候 call 这个 start 的时候,我启动一个 Containerd Shim。

但是当我下一步是调用 API 的时候,就是在前面那个 CRI 里面,访问 Container API 时候,我就不用再启动一个连接,我是复用。我重用创建好的这个 Sandbox,这就为你的实现提供了很大的自由度。所以这时候你会发现整个实现的方式变了,这时候 Containerd 用过来之后,它不再去关心每个容器起 Containerd Shim,而是由你自己去实现。我的实现方式是我只在 Sandbox 时候,去创建 containerd-shim-v2,而接下来整个后面的 container 层的操作,会全部走到这个 containerd-shim-v2 里面,去重用这个 Sandbox,所以这个跟前面的时间就出现很大的不同。

所以你现在去总结一下这个图的话,你发现我们实现方式是变成这个样子:

首先,你还是用原来的 CRI Containerd,只不过现在装的是 runC,你现在再装一个 kata container 放在那机器上面。接下来我们 Kata 那边会给你写一个实现叫 kata-Containerd-Shimv2。

现在,我们只聚焦在怎么去把 Containerd 对接在 kata container 上面,就是所谓的实现 Shimv2 API,这是我们要做的工作。而具体到我们这要做的事情上,其实它就是这样一系列与run一个容器相关的 API。比如说我可以去 create、start,这些操作全部映射在我 Shimv2 上面去实现,而不是说我现在考虑怎么去映射,去实现 CRI,这个自由度由于之前太大,造成了我们现在的一个局面,就有一堆 CRI Shim 可以用。这其实是一个不好的事情。有很多政治原因,有很多非技术原因,这都不是我们作为技术人员应该关心的事情,你现在只需要想我怎么去跟 Shimv2 对接就好了。

给 Kubernetes 提供 kata-runtime

通过直接创建 Container 可以使用 kata-runtime 。但在集群中,我们该如何告诉 Kubernetes 哪些负载需要使用 kata-runtime 呢?根据不同的版本,Kata 提供了不同的方式。1.以 CentOS 操作系统为例,安装kata及命令工具:

  1. $ source /etc/os-release 
  2. $ yum -y install yum-utils 
  3. $ ARCH=$(arch) 
  4. $ BRANCH="${BRANCH:-master}" 
  5. $ yum-config-manager --add-repo "http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/CentOS_${VERSION_ID}/home:katacontainers:releases:${ARCH}:${BRANCH}.repo" 
  6. $ yum -y install kata-runtime kata-proxy kata-shim 

2.首先检查Kata 对硬件的要求是否满足以下任意条件:

  • Intel VT-x technology.
  • ARM Hyp mode (virtualization extension).
  • IBM Power Systems.
  • IBM Z mainframes.

安装完 kata-runtime 之后,执行检测命令:

  1. $ kata-runtime kata-check 
  2. $ System is capable of running Kata Containers 
  3. $ System can currently create Kata Containers 

3.安装 Kubernetes 集群 使用 Kubeadm 安装集群非常方便,可以参考之前的文档 使用 Kubeadm 安装 Kubernetes 集群 。4.生成 containerd 配置文件

  1. containerd config default > /etc/containerd/config.toml 
  • RuntimeClass 的方式

这种方式对相关组件版本有要求:

  1. Kata Containers v1.5.0 or above (including 1.5.0-rc) 
  2. Containerd v1.2.0 or above 
  3. Kubernetes v1.12.0 or above 

在 config.toml 配置文件中,增加如下内容:

  1. [plugins.cri.containerd] 
  2.   no_pivot = false 
  3. [plugins.cri.containerd.runtimes] 
  4.   [plugins.cri.containerd.runtimes.runc] 
  5.      runtime_type = "io.containerd.runc.v1" 
  6.      [plugins.cri.containerd.runtimes.runc.options] 
  7.        NoPivotRoot = false 
  8.        NoNewKeyring = false 
  9.        ShimCgroup = "" 
  10.        IoUid = 0 
  11.        IoGid = 0 
  12.        BinaryName = "runc" 
  13.        Root = "" 
  14.        CriuPath = "" 
  15.        SystemdCgroup = false 
  16.   [plugins.cri.containerd.runtimes.kata] 
  17.      runtime_type = "io.containerd.kata.v2" 
  18.   [plugins.cri.containerd.runtimes.katacli] 
  19.      runtime_type = "io.containerd.runc.v1" 
  20.      [plugins.cri.containerd.runtimes.katacli.options] 
  21.        NoPivotRoot = false 
  22.        NoNewKeyring = false 
  23.        ShimCgroup = "" 
  24.        IoUid = 0 
  25.        IoGid = 0 
  26.        BinaryName = "/usr/bin/kata-runtime" 
  27.        Root = "" 
  28.        CriuPath = "" 
  29.        SystemdCgroup = false 

这里 [plugins.cri.containerd.runtimes.kata] 中的 kata 将被作为 RuntimeClass handler 关键字。

  • 使用 untrusted_workload_runtime 的方式

对于不符合上述版本要求的环境,可以使用之前的方式。在配置文件中新增如下内容:

  1. [plugins.cri.containerd.untrusted_workload_runtime] 
  2.   runtime_type = "io.containerd.runtime.v1.linux" 
  3.   runtime_engine = "/usr/bin/kata-runtime" 

最后,都需要重启 containerd。

  1. $ containerd systemctl daemon-reload 
  2. $ systemctl restart containerd 

5.使用 kata-runtime 方式一:RuntimeClass 方式

  • 创建 RuntimeClass
  1. kind: RuntimeClass 
  2. apiVersion: node.k8s.io/v1beta1 
  3. metadata: 
  4.   name: kata-containers 
  5. handler: kata 

也可以为 runc 创建 RuntimeClass

  1. $ kubectl get runtimeclass 
  2.  
  3. NAME              CREATED AT 
  4. kata-containers   2020-08-30 

创建负载 kata-pod.yaml

  1. apiVersion: v1 
  2. kind: Pod 
  3. metadata: 
  4.   name: kata-nginx 
  5. spec: 
  6.   runtimeClassName: kata-containers 
  7.   containers: 
  8.   - name: nginx 
  9.     image: nginx 
  10.     ports: 
  11.     - containerPort: 80 

执行创建:

  1. $ kubectl apply -f kata-pod.yaml 

查看负载:

  1. $ kata-runtime list 

方式二:untrusted_workload_runtime 的方式 untrusted_workload_runtime 使用 annotations 告诉 Kubernetes 集群哪些负载需要使用 kata-runtime。

  1. annotations: 
  2.   io.kubernetes.cri.untrusted-workload: "true" 

下面是一个示例 kata-pod-untrusted.yaml

  1. apiVersion: v1 
  2. kind: Pod 
  3. metadata: 
  4.   name: kata-nginx-untrusted 
  5.   annotations: 
  6.     io.kubernetes.cri.untrusted-workload: "true" 
  7. spec: 
  8.   containers: 
  9.   - name: nginx 
  10.     image: nginx 
  11.     ports: 
  12.     - containerPort: 80 

执行创建:

  1. $ kubectl apply -f kata-pod-untrusted.yaml 

查看负载:

  1. $ kata-runtime list 

总结

Kubernetes 现在的核心设计思想,就是通过接口化和插件化,将原本复杂的、对主干代码有侵入性的特性,逐一从核心库中剥离和解耦。而在这个过程中,CRI 就是 Kubernetes 项目中最早完成了插件化的一个调用接口。这里主要为你介绍了在CRI基础上的另一种集成容器运行时的思路,即:CRI + containerd shimv2 的方式。

  • 通过这种方式,你就不需要再为自己的容器运行时专门编写一个 CRI 实现(CRI shim),而是可以直接重用 containerd对 CRI 的支持能力,然后通过 containerd shimv2的方式来对接具体的容器运行时(比如 runc)。
  • 这种集成方式已经成为了社区对接下层容器运行时的主流思路,像很多类似于 KataContainers,gVisor,Firecracker 等基于独立内核或者虚拟化的容器项目,也都开始通过 shimv2 ,进而借助 containerd项目无缝接入到 Kubernetes 当中。

reference

 

https://blog.csdn.net/yuchunyu97/article/details/109241723https://github.com/kata-containers/documentation/blob/master/install/centos-installation-guide.mdhttps://ustack.io/2019-11-21-container%E7%9B%B8%E5%85%B3%E6%A6%82%E5%BF%B5%E6%A2%B3%E7%90%86.htmlhttps://github.com/kata-containers/documentation/blob/master/how-to/how-to-use-k8s-with-cri-containerd-and-kata.mdhttps://github.com/kubernetes/kubernetes/issues/73189https://blog.zufardhiyaulhaq.com/kubernetes-with-cri-containerd-and-kata-containers/https://www.chenshaowen.com/blog/how-to-integrate-kata-in-kubernetes-cluster.html

 

责任编辑:武晓燕 来源: 运维开发故事
相关推荐

2021-11-05 08:07:57

kubeletKubernetesContainerd

2023-08-29 08:20:35

Kubernete跨云容器

2021-10-22 00:09:16

Kubernetes容器接口

2023-04-03 13:01:14

UbuntuCRI-O

2024-03-20 10:46:00

云原生容器

2021-09-11 15:38:23

容器运行镜像开放

2019-07-12 09:30:12

DashboardDockerDNS

2023-01-03 09:10:21

2020-08-11 08:59:20

容器虚拟化技术

2015-07-20 15:44:46

Swift框架MJExtension反射

2024-07-15 18:20:18

2024-03-21 09:15:58

JS运行的JavaScrip

2024-01-08 08:24:02

PythonSys 模块工具

2023-09-07 07:17:01

KubernetesCRI标准

2021-03-15 08:33:01

CC++动态库

2021-07-10 07:39:38

Node.js C++V8

2021-09-02 05:37:22

Containerd Kubernetes 容器

2021-08-18 08:32:09

代码运行时间示波器

2020-12-07 13:31:43

GoMutex开发者

2013-11-26 16:49:55

Android开发运行时KitKat
点赞
收藏

51CTO技术栈公众号