iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >PouchContainer CRI的设计与实现方法是怎样的
  • 587
分享到

PouchContainer CRI的设计与实现方法是怎样的

2023-06-03 18:06:58 587人浏览 薄情痞子
摘要

PouchContainer CRI的设计与实现方法是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。  1. CRI简介  在每个kubernetes节点

PouchContainer CRI的设计与实现方法是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

  1. CRI简介

  在每个kubernetes节点的最底层都有一个程序负责具体的容器创建删除工作,Kubernetes会对其接口进行调用,从而完成容器的编排调度。我们将这一层软件称之为容器运行时(Container Runtime),大名鼎鼎的Docker就是其中的代表。

  当然,容器运行时并非只有Docker一种,包括CoreOS的rkt,hyper.sh的runV,Google的gvisor,以及本文的主角PouchContainer,都包含了完整的容器操作,能够用来创建特性各异的容器。不同的容器运行时有着各自独特的优点,能够满足不同用户的需求,因此Kubernetes支持多种容器运行时势在必行。

  最初,Kubernetes原生内置了对Docker的调用接口,之后社区又在Kubernetes 1.3中集成了rkt的接口,使其成为了Docker以外,另一个可选的容器运行时。不过,此时不论是对于Docker还是对于rkt的调用都是和Kubernetes的核心代码强耦合的,这无疑会带来如下两方面的问题:

  新兴的容器运行时,例如PouchContainer这样的后起之秀,加入Kubernetes生态难度颇大。容器运行时的开发者必须对于Kubernetes的代码(至少是Kubelet)有着非常深入的理解,才能顺利完成两者之间的对接。

  Kubernetes的代码将更加难以维护,这也体现在两方面:(1)将各种容器运行时的调用接口全部硬编码进Kubernetes,会让Kubernetes的核心代码变得臃肿不堪,(2)容器运行时接口细微的改动都会引发Kubernetes核心代码的修改,增加Kubernetes的不稳定性

  为了解决这些问题,社区在Kubernetes 1.5引入了CRI(Container Runtime Interface),通过定义一组容器运行时的公共接口将Kubernetes对于各种容器运行时的调用接口屏蔽至核心代码以外,Kubernetes核心代码只对该抽象接口层进行调用。而对于各种容器运行时,只要满足了CRI中定义的各个接口就能顺利接入Kubernetes,成为其中的一个容器运行时选项。方案虽然简单,但是对于Kubernetes社区维护者和容器运行时开发者来说,都是一种解放。

  2. CRI设计概述

PouchContainer CRI的设计与实现方法是怎样的

  如上图所示,左边的Kubelet是Kubernetes集群node Agent,它会对本节点上容器的状态进行监控,保证它们都按照预期状态运行。为了实现这一目标,Kubelet会不断调用相关的CRI接口来对容器进行同步。

  CRI shim则可以认为是一个接口转换层,它会将CRI接口,转换成对应底层容器运行时的接口,并调用执行,返回结果。对于有的容器运行时,CRI shim是作为一个独立的进程存在的,例如当选用Docker为Kubernetes的容器运行时,Kubelet初始化时,会附带启动一个Docker shim进程,它就是Docker的CRI shime。而对于PouchContainer,它的CRI shim则是内嵌在Pouchd中的,我们将其称之为CRI manager。关于这一点,我们会在下一节讨论PouchContainer相关架构时再详细叙述。

  CRI本质上是一套grpc接口,Kubelet内置了一个grpc Client,CRI shim中则内置了一个gRPC Server。Kubelet每一次对CRI接口的调用,都将转换为gRPC请求由gRPC Client发送给CRI shim中的gRPC Server。Server调用底层的容器运行时对请求进行处理并返回结果,由此完成一次CRI接口调用。

  CRI定义的gRPC接口可划分两类,ImageService和RuntimeService:其中ImageService负责管理容器的镜像,而RuntimeService则负责对容器生命周期进行管理以及与容器进行交互(exec/attach/port-forward)。

  3. CRI Manager架构设计

PouchContainer CRI的设计与实现方法是怎样的

  在PouchContainer的整个架构体系中,CRI Manager实现了CRI定义的全部接口,担任了PouchContainer中CRI shim的角色。当Kubelet调用一个CRI接口时,请求就会通过Kubelet的gRPC Client发送到上图的gRPC Server中。Server会对请求进行解析,并调用CRI Manager相应的方法进行处理。

  我们先通过一个例子来简单了解一下各个模块的功能。例如,当到达的请求为创建一个Pod,那么CRI Manager会先将获取到的CRI格式的配置转换成符合PouchContainer接口要求的格式,调用Image Manager拉取所需的镜像,再调用Container Manager创建所需的容器,并调用CNI Manager,利用CNI插件对Pod的网络进行配置。最后,Stream Server会对交互类型的CRI请求,例如exec/attach/portforward进行处理。

  值得注意的是,CNI Manager和Stream Server是CRI Manager的子模块,而CRI Manager,Container Manager以及Image Manager是三个平等的模块,它们都位于同一个二进制文件Pouchd中,因此它们之间的调用都是最为直接的函数调用,并不存在例如Docker shim与Docker交互时,所需要的远程调用开销。下面,我们将进入CRI Manager内部,对其中重要功能的实现做更为深入的理解。

  4. Pod模型的实现

  在Kubernetes的世界里,Pod是最小的调度部署单元。简单地说,一个Pod就是由一些关联较为紧密的容器构成的容器组。作为一个整体,这些“亲密”的容器之间会共享一些东西,从而让它们之间的交互更为高效。例如,对于网络,同一个Pod中的容器会共享同一个IP地址和端口空间,从而使它们能直接通过localhost互相访问。对于存储,Pod中定义的volume会挂载到其中的每个容器中,从而让每个容器都能对其进行访问。

  事实上,只要一组容器之间共享某些linux Namespace以及挂载相同的volume就能实现上述的所有特性。下面,我们就通过创建一个具体的Pod来分析PouchContainer中的CRI Manager是如何实现Pod模型的:

  1、当Kubelet需要新建一个Pod时,首先会对RunPodSandbox这一CRI接口进行调用,而CRI Manager对该接口的实现是创建一个我们称之为"infra container"的特殊容器。从容器实现的角度来看,它并不特殊,无非是调用Container Manager,创建一个镜像为pause-amd64:3.0的普通容器。但是从整个Pod容器组的角度来看,它是有着特殊作用的,正是它将自己的Linux Namespace贡献出来,作为上文所说的各容器共享的Linux Namespace,将容器组中的所有容器联结到一起。它更像是一个载体,承载了Pod中所有其他的容器,为它们的运行提供基础设施。而一般我们也用infra container代表一个Pod。

  2、在infra container创建完成之后,Kubelet会对Pod容器组中的其他容器进行创建。每创建一个容器就是连续调用CreateContainer和StartContainer这两个CRI接口。对于CreateContainer,CRI Manager仅仅只是将CRI格式的容器配置转换为PouchContainer格式的容器配置,再将其传递给Container Manager,由其完成具体的容器创建工作。这里我们唯一需要关心的问题是,该容器如何加入上文中提到的infra container的Linux Namespace。其实真正的实现非常简单,在Container Manager的容器配置参数中有PidMode, IpcMode以及NetworkMode三个参数,分别用于配置容器的Pid Namespace,Ipc Namespace和Network Namespace。笼统地说,对于容器的Namespace的配置一般都有两种模式:"None"模式,即创建该容器自己独有的Namespace,另一种即为"Container"模式,即加入另一个容器的Namespace。显然,我们只需要将上述三个参数配置为"Container"模式,加入infra container的Namespace即可。具体是如何加入的,CRI Manager并不需要关心。对于StartContainer,CRI Manager仅仅只是做了一层转发,从请求中获取容器ID并调用Container Manager的Start接口启动容器。

  3、最后,Kubelet会不断调用ListPodSandbox和ListContainers这两个CRI接口来获取本节点上容器的运行状态。其中ListPodSandbox罗列的其实就是各个infra container的状态,而ListContainer罗列的是除了infra container以外其他容器的状态。现在问题是,对于Container Manager来说,infra container和其他container并不存在任何区别。那么CRI Manager是如何对这些容器进行区分的呢?事实上,CRI Manager在创建容器时,会在已有容器配置的基础之上,额外增加一个label,标志该容器的类型。从而在实现ListPodSandbox和ListContainers接口的时候,以该label的值作为条件,就能对不同类型的容器进行过滤。

  综上,对于Pod的创建,我们可以概述为先创建infra container,再创建pod中的其他容器,并让它们加入infra container的Linux Namespace。

  5. Pod网络配置

  因为Pod中所有的容器都是共享Network Namespace的,因此我们只需要在创建infra container的时候,对它的Network Namespace进行配置即可。

  在Kubernetes生态体系中容器的网络功能都是由CNI实现的。和CRI类似,CNI也是一套标准接口,各种网络方案只要实现了该接口就能无缝接入Kubernetes。CRI Manager中的CNI Manager就是对CNI的简单封装。它在初始化的过程中会加载目录/etc/cni/net.d下的配置文件,如下所示:

PouchContainer CRI的设计与实现方法是怎样的

  其中指定了配置Pod网络会使用到的CNI插件,例如上文中的bridge,以及一些网络配置信息,例如本节点Pod所属的子网范围和路由配置。

  下面我们就通过具体的步骤来展示如何将一个Pod加入CNI网络:

  1、当调用container manager创建infra container时,将NetworkMode设置为"None"模式,表示创建一个该infra container独有的Network Namespace且不做任何配置。

  2、根据infra container对应的PID,获取其对应的Network Namespace路径/proc/{pid}/ns/net。

  3、调用CNI Manager的SetUpPodNetwork方法,核心参数为步骤二中获取的Network Namespace路径。该方法做的工作就是调用CNI Manager初始化时指定的CNI插件,例如上文中的bridge,对参数中指定的Network Namespace进行配置,包括创建各种网络设备,进行各种网络配置,将该Network Namespace加入插件对应的CNI网络中。

  对于大多数Pod,网络配置都是按照上述步骤操作的,大部分的工作将由CNI以及对应的CNI插件替我们完成。但是对于一些特殊的Pod,它们会将自己的网络模式设置为"Host",即和宿主机共享Network Namespace。这时,我们只需要在调用Container Manager创建infra container时,将NetworkMode设置为"Host",并且跳过CNI Manager的配置即可。

  对于Pod中其他的容器,不论Pod是处于"Host"网络模式,还是拥有独立的Network Namespace,都只需要在调用Container Manager创建容器时,将NetworkMode配置为"Container"模式,加入infra container所在的Network Namespace即可。

  6. IO流处理

  Kubernetes提供了例如kubectl exec/attach/port-forward这样的功能来实现用户和某个具体的Pod或者容器的直接交互。如下所示:

PouchContainer CRI的设计与实现方法是怎样的

  可以看到,exec一个Pod等效于ssh登录到该容器中。下面,我们根据kubectl exec的执行流来分析Kubernetes中对于io请求的处理,以及CRI Manager在其中扮演的角色。

PouchContainer CRI的设计与实现方法是怎样的

  如上图所示,执行一条kubectl exec命令的步骤如下:

  1、kubectl exec命令的本质其实是对Kubernetes集群中某个容器执行exec命令,并将由此产生的IO流转发到用户的手中。所以请求将首先层层转发到达该容器所在节点的Kubelet,Kubelet再根据配置调用CRI中的Exec接口。请求的配置参数如下:

PouchContainer CRI的设计与实现方法是怎样的

  2、令人感到意外的是,CRI Manager的Exec方法并没有直接调用Container Manager,对目标容器执行exec命令,而是转而调用了其内置的Stream Server的GetExec方法。

  3、Stream Server的GetExec方法所做的工作是将该exec请求的内容保存到了上图所示的Request Cache中,并返回一个token,利用该token,我们可以重新从Request Cache中找回对应的exec请求。最后,将这个token写入一个URL中,并作为执行结果层层返回到apiServer。

  4、ApiServer利用返回的URL直接对目标容器所在节点的Stream Server发起一个Http请求,请求的头部包含了"Upgrade"字段,要求将http协议升级为websocket或者SPDY这样的streaming protocol,用于支持多条IO流的处理,本文我们以SPDY为例。

  5、Stream Server对ApiServer发送的请求进行处理,首先根据URL中的token,从Request Cache中获取之前保存的exec请求配置。之后,回复该http请求,同意将协议升级为SPDY,并根据exec请求的配置等待ApiServer创建指定数量的stream,分别对应标准输入Stdin,标准输出Stdout,标准错误输出Stderr。

  6、待Stream Server获取指定数量的Stream之后,依次调用Container Manager的CreateExec和startExec方法,对目标容器执行exec操作并将IO流转发至对应的各个stream中。

  7、最后,ApiServer将各个stream的数据转发至用户,开启用户与目标容器的IO交互。

  事实上,在引入CRI之前,Kubernetes对于IO的处理方式和我们的预期是一致的,Kubelet会直接对目标容器执行exec命令,并将IO流转发回ApiServer。但是这样会让Kubelet承载过大的压力,所有的IO流都需要经过它的转发,这显然是不必要的。因此上述的处理虽然初看较为复杂,但是有效地缓解了Kubelet的压力,并且也让IO的处理更为高效。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网精选频道,感谢您对编程网的支持。

--结束END--

本文标题: PouchContainer CRI的设计与实现方法是怎样的

本文链接: https://www.lsjlt.com/news/235376.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PouchContainer CRI的设计与实现方法是怎样的
    PouchContainer CRI的设计与实现方法是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。  1. CRI简介  在每个Kubernetes节点...
    99+
    2023-06-03
  • Linux内核设计与实现的方法是什么
    今天小编给大家分享一下Linux内核设计与实现的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。 Unix...
    99+
    2023-06-16
  • Hybris Enterprise Commerce Platform 服务层的设计与实现是怎样的
    本篇文章给大家分享的是有关Hybris Enterprise Commerce Platform 服务层的设计与实现是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。我们来...
    99+
    2023-06-02
  • Go连接池设计与实现的方法是什么
    这篇“Go连接池设计与实现的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go连接池设计与实现的方法是什么”文章吧...
    99+
    2023-07-06
  • ArcEngine开发中右键菜单的设计与实现是怎样的
    ArcEngine开发中右键菜单的设计与实现是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。利用ArcGIS Engine开发自定义GIS应用程序中,一般有两种方式来...
    99+
    2023-06-17
  • Kubernetes中锁机制的设计与实现方法是什么
    这篇文章主要讲解了“Kubernetes中锁机制的设计与实现方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Kubernetes中锁机制的设计与实现...
    99+
    2022-10-19
  • 基于SSM试卷自动生成系统设计与实现是怎样的
    这篇文章将为大家详细讲解有关基于SSM试卷自动生成系统设计与实现是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。功能点: 1.后台管理员能够对用户管理,用户批量导入,用户组管理,角色管...
    99+
    2023-06-02
  • Flex应用程序设计界面布局的实现方式是怎样的
    Flex应用程序设计界面布局的实现方式是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。和大家重点讨论一下如何为Flex应用程序设计界面布局,许多容器组件都允许以绝对坐标的...
    99+
    2023-06-17
  • PHP分布式架构的设计思路与实现方法
    随着互联网业务的不断发展和用户量的不断增加,单机架构已经无法满足业务需求,分布式架构成为了目前互联网行业的主流趋势之一。PHP作为一种流行的后端开发语言,也需要在分布式架构中发挥作用。本文将介绍PHP分布式架构的设计思路和实现方法。 一、...
    99+
    2023-09-03
    分布式 npm numy
  • JavaScript实现的人脸检测方法是怎样的
    这篇文章给大家介绍JavaScript实现的人脸检测方法是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。我一直对视频和图片中的人脸标记、检测和人脸识别技术很感兴趣。尽管我知道获取...
    99+
    2022-10-19
  • VB6实现MUI程序方法是怎么样的
    这期内容当中小编将会给大家带来有关VB6实现MUI程序方法是怎么样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。为大家详细讲述的是VB6实现MUI程序方法,希望本文能给大家的日常开发工作带来一些启示。之...
    99+
    2023-06-17
  • Android实现计时与倒计时的方法汇总
    方法一Timer与TimerTask(Java实现)public class timerTask extends Activity{ private int recLen = 11; private TextView txtView; ...
    99+
    2023-05-31
    android 计时 倒计时
  • 责任链设计模式的实现方法是什么
    本篇内容介绍了“责任链设计模式的实现方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!责任链设计模式...
    99+
    2022-10-19
  • BufferQueue的设计思想和内部实现方法是什么
    这篇文章主要介绍“BufferQueue的设计思想和内部实现方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“BufferQueue的设计思想和内部实现方法是什么”文章能帮助大家解决问题。 背...
    99+
    2023-06-05
  • VB.NET实现接口的相关操作方法是怎样的
    VB.NET实现接口的相关操作方法是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。开发人员在应用VB.NET进行实际开发的时候,发现其中有不少跟其他语言不一样的地方,...
    99+
    2023-06-17
  • Java中List排序的三种实现方法是怎样的
    Java中List排序的三种实现方法是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。前言在某些特殊的场景下,我们需要在 Java 程序中对 List 集合...
    99+
    2023-06-22
  • linux中的cron计划任务配置方法是怎样的
    今天就跟大家聊聊有关linux中的cron计划任务配置方法是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. crontab命令选项代码如下:#crontab -u <...
    99+
    2023-06-13
  • 计算机策略无法打开的解决方法是怎样的
    计算机策略无法打开的解决方法是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。处理的办法:1. 右键单击“我的电脑”,然后单击“属性”。 2. 在...
    99+
    2023-06-14
  • Kubernetes存储的设计与基本架构方法是什么
    这篇文章主要讲解了“Kubernetes存储的设计与基本架构方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Kubernetes存储的设计与基本架构...
    99+
    2022-10-19
  • Android实现计时与倒计时的常用方法小结
    本文实例总结了Android实现计时与倒计时的常用方法。分享给大家供大家参考,具体如下: 方法一 Timer与TimerTask(Java实现) public class t...
    99+
    2022-06-06
    倒计时 小结 方法 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作