k8s 读书笔记 - CRI(容器运行时接口)详解

k8s Node 节点(kubelet)的主要功能就是启动和停止容器的组件,这组件我们称之为 容器运行时(Container Runtime),这其中最知名的就是 Docker 了。为了更具扩展性,k8s 从 v1.5 版本开始就加入了容器运行时插件 API,即 Container Runtime Interface,简称 CRI

39a89b3d1693349c00635fbac92f9fec.png

CRI 概述

每个容器运行时都有各自的特点,因此用户希望 k8s 能够支持更多的容器运行时。k8s 从 v1.5 版本开始,引入了 CRI 接口规范,通过插件接口模式,k8s 无需重新编译就可以使用更多的容器运行时

可替代的容器运行时支持是 k8s 中的新概念。在 k8s v1.3 发布时,rktnetes 项目同时发布,让 rkt 容器引擎成为除 Docker 外的又一选择。然而,不管是 Docker 还是 rkt ,都用到了 kubelet 的内部接口,同 kubelet 源码纠缠不清。这种程度的集成需要对 kubelet 的内部机制有非常深入的了解,还会给社区带来管理压力,这就给新生代容器运行时造成了难于跨越的集成壁垒。CRI 接口规范试图用定义清晰的抽象层清除这一壁垒,让开发者能够专注于容器运行时(Container Runtime)本身。在通向插件式容器支持及建设健康生态环境的路上,这是一小步,也是很重要的一步。

什么是 CRI?

  1. CRI(容器运行时接口)是一个插件接口,它使 kubelet 能够使用各种容器运行时,无需重新编译集群组件。你需要在集群中的每个节点上都有一个可以正常工作的 容器运行时, 这样 kubelet 能启动 Pod 及其容器。

  2. CRI 是 kubelet容器运行时(Container Runtime) 之间通信的主要协议。k8s 容器运行时接口(CRI) 定义了主要 gRPC 协议, 用于集群组件 kubelet 和 容器运行时。

CRI 包含 Protocol Buffers、gRPC API、运行库支持及开发中的标准规范和工具。Docker 的 CRI 实现在 k8s v1.6 中被更新为 Beta 版本,并在 kubelet 启动时默认启动。

什么是 Container Runtime?

Container Runtime 提供容器运行环境,是负责运行容器的软件

说明:k8s 自 v1.24 版起,Dockershim 已从 Kubernetes 项目中移除。

你需要在 集群内每个 Node 节点上安装一个 容器运行时 以使 Pod 可以运行在上面。

说明:v1.24 之前的  k8s 版本包括与 Docker Engine 的直接集成,使用名为 dockershim(垫片) 的组件。这种特殊的直接整合不再是 k8s 的一部分 (这次删除被作为 v1.20 发行版本的一部分宣布)。你可以阅读检查 Dockershim 弃用是否会影响你 以了解此删除可能会如何影响你。要了解如何使用 dockershim 进行迁移, 请参阅从 dockershim 迁移。如果你正在运行 v1.24 以外的 Kubernetes 版本,检查该版本的文档。

CRI 主要组件

kubelet 使用 gRPC 框架通过 UNIX Socket 与容器运行时(或CRl代理)进行通信。在这个过程中 kubelet 是客户端,CRI 代理(shim)是服务端,如下图所示。

f4940b39122d144818bee337a106aae8.png

cri 主要组件

Protocol Buffers API 包含两个 gRPC 服务:ImageService 和 RuntimeService

  • ImageService 提供了从仓库拉取镜像、查看和移除镜像的功能。

  • RuntimeService 负责 Pod 和容器的生命周期管理,以及与容器的交互 (exec/attach/port-forward )。

rkt 和 Docker 这样的容器运行时可以使用一个 Socket 同时提供两个服务,在 kubelet 中可以用 --containcr-runtime-endpoint 和 --image-service-endpoint 参数设置这个 Socket

Pod 和 Container 生命周期管理

Pod 由一组应用容器(Container)组成,其中包含共有的环境和资源约束。在 CRI 里,这个环境被称为 PodSandbox(Pod 沙箱)。k8s 有意为容器运行时留一些发挥空间,他们可以根据自己的内部实现来解释PodSandbox。对于 Hypervisor 类的运行时,PodSandbox 会具体化为一个虚拟机。其他例如 Docker,会是一个 Linux 命名空间(namespace)。在 v1alphal API,kubelet 会创建 Pod 级别的 cgroup 传递给容器运行时,并以此运行所有进程来满足 PodSandbox 对 Pod 的资源保障。

在启动 Pod 之前,kubelet 调用 RuntimeService.RunPodSandbox 来创建环境。这一过程包括为 Pod 设置网络资源(分配IP等操作)。PodSandbox 被激活后,就可以独立地创建启动、停止和删除不同的容器了。kubelet 会在停止和删除 PodSandbox 之前首先停止和删其中的容器。

kubelet 的职责在于通过 RPC 管理容器的生命周期,实现容器生命周期的钩子,存活和健康监测,以及执行 Pod 的重启策略等

RuntimeService 服务包括对 SandboxContainer 操作的方法,下面的伪代码展示了主要的 RPC 方法:

service RuntimeService {
// 沙箱操作
rpc RunPodSandbox(RunPodSandboxRequest) returns(RunPodSandboxResponse) { }
rpc StopPodSandbox(StopPodSandboxRequest) returns(StopPodSandboxResponse) { }
rpc RemovePodSandbox(RemovePodSandboxRequest) returns(RemovePodSandboxResponse) { }
rpc PodSandboxStatus(PodSandboxStatusRequest) returns(PodSandboxStatusResponse) { }
rpc ListPodSandbox(ListPodSandboxReauest) returns(ListPodSandboxResponse) { }
// 容器操作
rpc CreateContainer(CreateContainerRequest) returns(CreateContainerResponse) { }
rpc StartContainer(StartContainerReauest) returns(StartContainerResponse) { }
rpc StopContainer(StopContainerReauest) returns(StopContainerResponse) { }
rpc RemoveContainer(StopContainerReauest) returns(RemoveContainerResponse) { }
rpc ListContainers(ListContainersReauest) returns(ListContainersResponse) { }
rpc ContainerStatus(ContainerStatusReauest) returns(ContainerStatusResponse) { }
...
}

面向容器级别的设计思想

k8s 中最小的调度单元是 Pod,它曾经可能采用的一个 CRI 设计就是复用 Pod 对象,使得容器运行时可以自行实现控制逻辑和状态转换,极大地简化 API,让CRI 能够更广泛地适用于多种容器运行时。但是经过深入讨论之后,k8s 放弃了这一想法。

  • 首先,kubelet 有很多 Pod 级别的功能和机制(例如 crash-loop backoff机制)。如果交给容器运行时去实现,则会造成很重的负担;

  • 其次,更重要的是,Pod 标准还在快速演进中。很多新功能(如初始化容器,Init Conatiner)都是由 kubelet 完成管理的,无须交给容器运行时实现。

CRI 选择了在容器级别进行实现,使得容器运行时能够共享这些通用特性,以获得更快的开发速度。这并不意味着设计哲学的改变—— kubelet 要负责、保证容器应用的实际状态和声明状态的一致性。

Kubernetes 为用户提供了与 Pod 及其中的容器进行交互的功能(kubectlexec/attach/port-forward)。kubelet 目前提供了两种方式来支持这些功能。

  1. 调用容器的本地方法。

  2. 使用Node上的工具(例如 nsenter 及 socat )。

因为多数工具都假设 Pod 用 Linux 的 namespace 做了隔离,因此使用 Node 上的工具并不是一种容易移植的方案。在 CRI 中显式定义了这些调用方法,让容器运行时进行具体实现。下面的伪代码显示了 Exec、Attach、PortForward 这几个调用需要实现的 RuntimeService 方法:

service RuntimeService {
...
// Execsync 在容器中同步执行一个命令。
rpc ExecSync(ExecSyncRequest) returns(ExecSyncResponse) { }
// Exec 在容器中执行命令
rpc Exec(ExecRequest) returns(ExecResponse) { } 
// Attach 附着在容器上
rpc Attach(AttachRequest) returns(AttachResponse)  { } 
// PortForward 从 Pod 沙箱中进行端口转发
rpc PortForward(PortForwardRequest) returns(PortForwardResponse)  { }
...
}

目前还存在一个潜在的问题,kubectl 处理所有的请求连接,使其成为 Node 通信瓶颈的可能。在设计 CRI 时,要让容器运行时能够跳过中间的过程。容器运行时可以启动一个单独的流式服务来处理请求(还能对 Pod 的资源使用情况进行记录),并将服务地址返回给 kubelet 。这样 kubelet 就能反馈信息给 API Server(kube-apiserver),使之可以直接连接到容器运行时提供商的服务,并连接到客户端。

尝试使用新的 CRI 来创建容器

尝试新的 Kubelt-CRI-Docker 集成,只需为 kubelet 启动参数加上 --enable-cri=true 开关来启动 CRI。该选项从 k8s v1.6 开始已经作为 kubelet 的默认选项。如果不希望使用 CRI ,可以设置 --enable-cri=false 来关闭该功能。

查看 kubelet 的日志,可以看到启用 CRI 和创建 gRPC Server 的日志:

10603 15:08:28.953332 3442 container_manager_linux.go:250] Creating 
Container Manager object based on Node Config: {RuntimeCgroupsName:SystemCgroupsName: 
KubeletCgroupsName:ContainerRuntime :docker CgroupsPerQOS:true CgroupRoot:/
CgroupDriver:cgroupfs ProtectKernelDefaults:false EnableCRI :true
NodeAllocatableConfig: {KubeReservedCgroupName: SystemReservedCgroupName:
EnforceNodeAllocatable:map[pods:{}] KubeReserved:map[] SystemReserved:map[]
HardEvictionThresholds:[{Signal :memory.available Operator:LessThan
Value:{Quantity:100Mi Percentage:0} GracePeriod:0s MinReclaim:<niI>}]}
ExperimentalQ0SReserved:map[]}
...
10603 15:08:29.060283 3442 kuhelet.go:573] Starting the GRPC server for the docker CRI shim.

创建一个 Deployment:

kubectl run nginx --image=nginx:1.8 --replicas=1
...
deployment "nginx" created

查看 Pod 的详细信息,可以看到将会创建 Sandbox(沙箱) 的 Event:

kubectl describe pod nginx
...
Events:
...From            Type      Reason           Message
...-------            --------  -----------      --------------- 
...default-scheduler  Normal    Scheduled        Successfuller assigned nginx to k8s-node-1
...kubelet,k8s-node-1 Normal    SandboxReceived  Pod sandbox received, it will be created.

从 Event 日志信息可以看出 kubelet 使用了 CRI 接口来创建 Container 容器。

常用的 CRI

目前已经有多款开源的 CRI 项目可用于 k8s,常见的容器运行时有以下几种:

  • containerd(k8s v1.24 版本及以后默认的容器运行时)

  • CRI-O

  • Docker Engine(k8s v1.24 版本已经剔除,默认使用 containerd)

  • Mirantis Container Runtime(MCR)

  • frakit(基于 Hypervisor 的容器运行时)

关于容器运行时的更多信息,请查看:https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Win11的这个功能,厉害了!

上周微软正式发布了Windows11的22H2版本&#xff0c;虽说是一周年更新版&#xff0c;但仍然有不少的问题。微软给Win10换了一套皮肤&#xff0c;并做了一些优化升级&#xff0c;摇身一变成了Win11&#xff0c;但是外观方面却做的并不是很协调&#xff0c;有一些界面仍然保留着以…

MAUI + Masa Blazor 开发带自动更新功能的安卓App

自动更新主要下面4个步骤获取最新版本号提示用户发现更新&#xff0c;等待用户确认更新下载最新的apk包安装apk包下面从创建MAUI项目开始1、创建Maui Blazor Server应用2、安装Masa.Blazor&#xff0c;并添加引用dotnet add package Masa.Blazor在 wwwroot/index.html 中引入资…

[deviceone开发]-一个很炫的手势动画示例

2019独角兽企业重金招聘Python工程师标准>>> 一、简介 这是iOS下的效果&#xff0c;android下完全一致。通过do_GestureView组件和do_Animation组件&#xff0c;deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过手势控制图片上下动画滑动实现开合…

POJ-3067 Japan---树状数组逆序对变形

题目链接&#xff1a; https://vjudge.net/problem/POJ-3067 题目大意&#xff1a; 日本岛东海岸与西海岸分别有N和M个城市&#xff0c;现在修高速公路连接东西海岸的城市&#xff0c;求交点个数。 解题思路&#xff1a; 记每条告诉公路为(x,y), 即东岸的第x个城市与西岸的第y个…

C# 笔迹擦除8边形

本文经原作者授权以原创方式二次分享&#xff0c;欢迎转载、分享。原文作者&#xff1a;唐宋元明清原文地址&#xff1a; https://www.cnblogs.com/kybs0/p/16593146.htmlC# 笔迹擦除8边形擦除区域与橡皮大小不一致测试反馈&#xff0c;擦除区域与真实的橡皮大小不一致&#…

资深私域运营必知的100个专业名词!

来源 | 晏涛三寿 &#xff08;ID&#xff1a;yantao-219&#xff09; 作者 | 晏涛 如今私域相关人才进入了供不应求的状态&#xff0c;不少企业开始设置专门的岗位&#xff0c;私域运营也成为了招聘市场中的“香饽饽”。 但是想要成为一名优秀的私域运营并不容易&#xff0c;…

【错误解决】[Maven] cannot be opened because it does not exist错误[文件无法编译到target目录下的解决方法]...

转载请注明出处&#xff1a;http://blog.csdn.net/qq_26525215 本文源自【大学之旅_谙忆的博客】 使用IDEA搭建的Maven项目&#xff0c;在写SpringEL和资源调用时出现了如下错误: 相信我&#xff0c;代码没问题的、 Caused by: java.io.FileNotFoundException: class path res…

JQ插件 jquery mobiscroll

参数&#xff1a; theme是指主题 display&#xff1a;bottom 是指弹出框的位置&#xff0c;分别可以使用top,bottom,inline来定义&#xff0c;这里解释一下inline的用法:inline的话就可以实现页面一加载就能看到这个弹出框&#xff0c;如果使用top和bottom,则必须使得输入框获得…

commons-lang3:DateUtils

2019独角兽企业重金招聘Python工程师标准>>> /** * 以秒为标准时间的毫秒数 */ public static final long MILLIS_PER_SECOND 1000 /** *以分钟为标准时间的毫秒数 */ public static final long MILLIS_PER_MINUTE 60 * MILLIS_PER_S…

Blazor University (46)依赖注入 —— Transient 依赖

原文链接&#xff1a;https://blazor-university.com/dependency-injection/dependency-lifetimes-and-scopes/transient-dependencies/Transient 依赖Transient 依赖是最容易理解的。在构建注册为 Transient 的可注入依赖项时&#xff0c;依赖项容器只是充当工厂。一旦实例被创…

AM335x 添加 HUAWEI MU609 Mini PCIe Module,并用pppd 启动相关设备

kernel 的配置kernel 3.2.0make menuconfigDevice Drivers --->[*] USB support ---><*> USB Serial Converter support ---><*> USB driver for GSM and CDMA modems kernel 3.2.0make menuconfigDevice Drivers --->[*] Network device supp…

构建LAMP平台及应用系统

LANP架构指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词&#xff0c;具体包括linux操作系统、apache网站服务器、mysql数据库服务器、PHP&#xff08;或Perl、Python&#xff09;网页编程语言。在构建LAMP平台时…

pyqt2_官网教程

sklearn实战-乳腺癌细胞数据挖掘&#xff08;博主亲自录制视频&#xff09; https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare Articles You can find a collection of P…

Windows10安装WSL2和Ubuntu的过程

因为在Windows10环境中安装了2个相同的包导致冲突&#xff0c;所以想到了通过WSL2Docker的方式进行编程开发。因为Docker Desktop直接安装就行了&#xff0c;不做介绍。本文主要介绍WSL2和Ubuntu的安装过程。一.安装前的环境准备1.升级Windows系统因为低于某个版本号不支持WSL2…

Hyper-V数据文件丢失解决方案(有图有真相)

一、Hyper-V虚拟化故障概述 1、虚拟机环境故障虚拟化环境为ESXI虚拟化服务器&#xff0c;虚拟机环境&#xff0c;虚拟机的硬盘文件和配置文件放在北京某服务器托管公司的DELL MD3200存储中&#xff08;存储由5块容量为600G的硬盘组成raid磁盘阵列&#xff09;。该存储中4块硬盘…

SQL小技巧,动态输出本周各天日期

SET DATEFIRST 1; --设置周一为每周第一天 SELECT DATEFIRST;WITH w AS(SELECTCONVERT(varchar(10),T.[Date],120) AS [Date],DATENAME(weekday, T.[Date] ) AS [Week],DATEPART(WK, T.[Date]) AS WeekIndexFROM(SELECTDATEADD(DAY, number, DATEADD(wk, DATEDIFF(wk, 0, get…

开源的价值观与文化的传递

| 作者&#xff1a;Sharan Foga, Apache 软件基金会董事&#xff08;2021 届、2022 届&#xff09;&#xff0c;曾亲身来到 2019 中国开源年会&#xff08;COSCon19&#xff09;以本文内容发表主题演讲。| 翻译&#xff1a;刘天栋.Ted&#xff0c;徐红伟.stronghx| 审阅&#x…

用python来更改小伙伴的windows开机密码,不给10块不给开机

今天教大家用python脚本来控制小伙伴们windows电脑的开机密码。没错就是神不知鬼不觉&#xff0c;用random()随机生成的密码&#xff0c;只有你自己知道哦~ 代码呢分两部分&#xff0c;一部分是client端跟server端两个。你只需要想办法让小伙伴运行你的client端脚本就OK啦。不过…

el-upload 防止选择上传重复文件

<el-uploadref"uploadRef"multipledragaction"":auto-upload"false":file-list"msgPara.MsgFileList":on-change"handleFileChanged" ><el-button type"primary">选择文件</el-button> </el…