当前位置: 首页 > news >正文

沈阳 建设工程 招标中心网站各大免费推广网站

沈阳 建设工程 招标中心网站,各大免费推广网站,北京专业网站建设网站,文化创意有限公司文章目录 前言kubelet 架构kubelet 职责Node管理(节点管理)Pod管理 kubelet管理Podkubelet如何管理当前节点上所有Podkubelet三个端口kubelet获取Pod清单kubelet通过CRI接口管理Pod以及里面的容器 PodWorker的工作细节PodWorker的工作细节PLEG组件PLEG报错 kubelet创建并启动Po… 文章目录 前言kubelet 架构kubelet 职责Node管理(节点管理)Pod管理 kubelet管理Podkubelet如何管理当前节点上所有Podkubelet三个端口kubelet获取Pod清单kubelet通过CRI接口管理Pod以及里面的容器 PodWorker的工作细节PodWorker的工作细节PLEG组件PLEG报错 kubelet创建并启动PodPod启动流程更加详细的Pod启动过程 kubelet CRI 容器运行时CRI 容器运行时CRI 容器运行时架构kubele调动高层运行时通过 CRI 规范接口高层运行时调用低层运行时通过 OCI 规范接口 CRI 高层运行时和低层运行时高层运行时和低层运行时如何查看当前k8s集群的高层运行时和低层运行时高层运行时: 从docker到containerd三种高层运行时比较Docker和Containerd的细节差异Containerd和CRI-O的性能比较 小结 尾声 前言 kubelet 架构 controller-manager包含了一组控制器它是整个集群的大脑每个控制器会关注自己所关注的对象这些控制器里面都会有一个固定的模式每个控制器都会通过list watcher去watch它所关注的对象当这些对象发生变化以后以事件通知的形式告知controllercontroller会注册这些事件的回调函数并且将这些事件放在一个队列里面同时会去启动一堆worker线程来从队列里面取出这些对象并且进行相关的处理。 也就是说当读了任何一个controller manager的代码可以将同样的思路套到其他的controller里面。在每个节点上面都会去运行一个组件叫做kubelet。 Kubelet架构 它是承担的很多很多职责的这样一个组件。 最上层它会提供一个api层这个api里面就会有蛮多的职责比如做自己的探活还有业务指标如何上报这些都是通过api你可以看到它工作在不同的端口上面都有监听器承担不同的职责。 中间就是在kubelet里面运行了一个一个的manager你可以理解为一个一个独立职责的小的管理器。 第一列(从左到右) probemanager就是为这个节点上面的pod做探活的这样一个管理器liveless readyless probe这些探活由kubelet发起kubelet的probemanager会去读取当前节点上面所有probe的定义然后它会去看这些probe有没有定义探活如果定义了探活的属性那么probemanager就会按照你定义的interval去做监听。oomwatcherkubelet是整个节点的守护神它是一个代理它负责所有应用的生命周期同时它有包含节点当前继续正常工作的职责所以它由oomwatcher来监听比如节点出现oom问题比如某些进程出现了oom的错误oomwathcer就会通过oom这个事件来获取这些异常并且上报给kubelet。GPU manager就是用来管理GPU等等这些扩展的device当节点上有GPU卡的时候GPUmanager就是用来管理这张GPU卡的。cadvisor是独立开源的软件kubelet里面会内嵌cadvisor它其实基于cgroup技术去获取节点上运行应用的资源状态整个集群的监控都是由cadvisor收集上来的并且通过kubelet上报的。 第二列(从左到右) 5. syncLoop: syncLoop使用控制器模式它要去watch一堆对象也就是当前节点的pod对象syncloop做完之后下面内嵌了一堆的workerpod worker就是当我的 sync group 接收到pod的变更通知的时候那么这个 pod worker 就会去干活也就是去维护pod的生命周期。kubelet 中的 syncLoop要去监听apiserver去获取当前节点的pod清单获取pod清单之后然后获取的pod清单每个pod都是一个一个的通知事件然后podworker就会处理这些事件。 6. PodWorker: PodWorker会去调用cri然后获取当前节点pod对应的容器是不是在启动的状态。如果没有启动那么他就会去启动这些容器进程把这个应用拉起来它就是通过cri的接口。cri接口传统都是通过dockershim去做的但是随着kubernetes架构不断升级它废弃了docker-shim这条线它决定不再支持比较臃肿的dokcer shim而是通过remote container interface比如通过containerd或者cri来支持整个运行时。 第三列(从左到右) 7. diskspacemanager这个节点的磁盘空间大小包括每个应用你上去了临时空间你是不是超了由diskspacemanager来管理。 8. statusmanager用来管理节点的状态的。 9. evictionmanagerkubelet是这个节点的守护神它会去监听当前节点上所有pod所消耗的资源比如说内存内存是不可压缩资源可压缩资源cpucpu是基于分时复用的当你多个进程去抢cpu的时候反正我们按照协商好的比例去分cpu时间片当出现竞争的时候顶多受损不会异常退出。但是内存不一样内存是不可压缩资源针对内存kubelet就会做比较激进的动作evictionevictionmanager就是承担这个职责的组件。它会去监听当前节点的资源使用情况如果它发现内存已经达到了一个水位比如10g内存使用了9g如果不制止这种情况那么可能整个节点都会受到影响。evictionmanager就会去监听这个水位当这个内存达到一定水位的时候它就会去做驱逐它会去按照既定策略将低优先级的业务而且占用内存又比较大的超出了自己预设值的这些进程驱逐掉也就是将pod从这个节点删除掉。通过这种极端的方式来保护整个节点。 10. volumemanagerpod启动要挂载磁盘要挂载存储卷的这个是由volumemanager去做的。 第四列(从左到右) 11. imagegc如果我这个节点不断的启动应用每个应用都需要拉取自己的image如果我不做一些清理工作就会导致这个节点的image会越来越多把磁盘占满所谓的imagegc就会去扫描一些不怎么活跃的镜像把这些镜像清除掉。 12. containegc就是你的进程可能会退出它会有一个exit的container这个container其实它的文件层是没有清理掉的所谓的container gc就是会清除这些退出的容器。 13. imagemanager就是做镜像管理的。 14. certificatesmanagerkubelet有签证书的能力当我们需要kubelet去管理证书的时候certificatesmanager就可以起作用。 kubelet 职责 每个节点上都运行一个kubelet服务进程默认监听10250端口kubelet的职责包括 管理Node(通过kubelet访问apiserver的方式): 每个kubelet进程会在APIServer上注册节点自身信息定期向 master 节点汇报节点的资源使用情况并通过 cAdvisor 监控节点和容器的资源。pod健康状态通过pleg去做上报节点的资源使用情况通过cadvisor上报管理Pod及Pod中的容器(通过kubelet watch apiserver的方式): 接收并执行master apiserver发来的指令(其实是用watch的机制去监听的如果这些pod发生了变化他就会去执行某些操作具体执行什么样的操作就是管理pod当中的容器) Node管理(节点管理) kubelet本身有节点管理的功能包括注册节点更新节点状态所以在启动kubelet的时候如果加了register-node那么就会自动的将当前节点注册到apiserver。 节点管理最主要的两个是节点自注册和节点状态更新∶ kubelet 可以通过设置启动参数–register-node 来确定是否向API Server注册自己如果 kubelet 没有选择自注册模式则需要用户自己配置Node 资源信息同时需要告知 kubelet集群上的APIServer的位置kubelet在启动时通过APIServer注册节点信息并定时向APIServer发送节点新消息APIServer在接收到新消息后将信息写入etcd。 Pod管理 比节点管理相关更加重要的是pod的管理因为节点的注册管理是一次性的然后由kublet不断的上报状态更重要的是应用的管理也即是pod。 kubelet如何管理pod它首先要知道节点上要启动哪些pod这就涉及到如何获取pod清单kubelet有几种方式去获取pod清单第一种就是文件的方式也就是static pod扫描到目录下有pod清单文件就将这些pod启动起来。 staticPodPath: /etc/kubernetes/manifests第二种方式是通过http endpoint来加载pod你可以给它一个启动参数叫做manifest-url这个url是http-endpoint你把所有pod清单放在那他也会去读取那个url来加载pod清单。 第三种方式是通过apiserver了当apiserver启动之后它自己会去启动apiserverkubelet连接到apiserver会去监听apiserver上面所有的pod当然是和这个节点相关的所有pod经过调度scheduler之后的所有pod。kubelet会去watch apiserverapiserver那边有pod创建出来了并且和这个节点相关这个节点上的kubelet就会去工作 获取Pod清单∶ (1) 文件∶启动参数–config指定的配置目录下的文件默认/etc/Kubernetes/manifests/。该文件每20秒重新检查一次可配置。 (2) HTTP endpointURL∶启动参数–manifest-url设置。每20秒检查一次这个端点可配置。 (3) APIServer∶通过APIServer监听etcd目录同步Pod清单。 (4) HTTP Server∶ kubelet 侦听 HTTP 请求并响应简单的 API 以提交新的 Pod 清单。 kubelet管理Pod 从上到下分为三层如下 最上一层kubelet三个端口 次一层kubelet获取Pod清单 第三层kubelet通过CRI接口管理Pod以及里面的容器 下面分层介绍。 kubelet如何管理当前节点上所有Pod kubelet三个端口 kubelet api 包含三个端口 (1) 10250 端口: 业务api, 上面阐述的节点管理和Pod管理通过 10520 端口的api来实现的 (2) 10250 端口: 只读api (3) 10248 端口: 健康检查api 查看 kubelet 三个端口 测试 健康检查接口 (apiserver和kubelet都有健康检查接口) kubelet获取Pod清单 中间还有一个syncloop和PodWorkder 所谓的syncloop又是控制器模式了它要去watch一堆对象也就是当前节点的pod对象sync loop做完之后下面内嵌了一堆的workerpod worker就是当我的sync loop接收到pod的变更通知的时候那么这个pod worker就会去干活也就是去维护pod的生命周期。 kubelet要去监听apiserver去获取当前节点的pod清单获取pod清单之后然后获取的pod清单每个pod都是一个一个的通知事件然后podworker就会处理这些事件。 kubelet通过CRI接口管理Pod以及里面的容器 kubelet (本质是kubelet中的podworker) 会去调用cri然后获取当前节点pod对应的容器是不是在启动的状态。如果没有启动那么他就会去启动这些容器进程把这个应用拉起来它就是通过cri的接口。 cri接口传统都是通过dockershim去做的但是随着kubernetes架构不断升级它废弃了docker-shim这条线它决定不再支持比较臃肿的dokcer shim而是通过remote container interface比如通过containerd或者cri来支持整个运行时。 PodWorker的工作细节 PodWorker的工作细节 上面将kubelet三层结构中包括 kubelet 三个接口、kubelet 获取Pod清单、kubelet 通过 CRI 接口管理Pod以及里面的容器。这里详细讲解一下 kubelet 通过 syncLoop 获取 Pod 清单列表这个 syncLoop 底层怎么工作的。 步骤1kubelet中的synloop监听pod的状态变化 kubelet它本身的synloop就是去监听pod的状态变化这个pod的状态变化就是一个一个的pod的update或者是add事件接收到这些事件之后它就会将事件存在updateoption里面那么不同的worker在kubelet里面有多个worker每个worker都会从队列里面获取这些pod变更事件的清单。 事件就是Event类似于mysqll中的 crud 语句记录着数据操作APIServer审计日志会记录所有的事件的 步骤2针对每一个pod执行sync pod的操作 针对每一个pod它就会去执行sync pod的操作sync pod里面最重要的行为就是 compute pod actions也就是针对这个pod采取什么样的行为它会去比对当前节点上面的已经在运行的容器进程然后去判断说如果pod是新的我就create如果pod是已经存在的比如说是delete事件那么我就应该去删除如果是一个更新事件那么我就要去判断运行的容器进程和你当前的pod是不是匹配的比如它的哈希值变的话那么我就要重建这就是 compute pod actions所做的事情。它算完了之后就需要通过cri的接口去create这些进程或者kill这些进程。 步骤3kubelet中的pleg将每一个pod生命周期上报给apiserver 右边还有个组件叫做pleg它主要是pod lifecycle event的一个汇聚器就是pod运行完之后上面左边部分是用来管理pod的生命周期管理完之后这些pod的状态如何上报那么就是通过pleg组件去上报的。kubelet在pleg组件里面维护了一个pod cache它本地的一个缓存这个pleg会去定期的往container runtime里面去发一个list的操作去获取当前节点上pod的清单正在运行的pod清单那么这里就会把当前所有在运行pod状态在pleg这里汇聚由pleg 通过pod lifecycle event发回上报给apiserverapiserver那端就知道这个node节点上面所有pod的状态了。 小结apiserver将Pod 事件Event发送给kubeletkubelet将 Pod 生命周期 lifecycle 发送给apiserver 这就是 apiserver 与 kubelet 相互的业务沟通之前学习证书的时候apiserver和kubelet需要相互调用各自保留对方的客户端证书 PLEG组件 PLEG 是 kubelet 用来检查容器 runtime 的健康检查机制。这件事情本来可以由 kubelet 使用 polling 的方式来做。但是 polling 有其成本上的缺陷所以PLEG 应用而生。PLEG 尝试以一种“中断”的形式来实现对容器 runtime 的健康检查虽然实际上它同时用了 polling 和”中断”两种机制。 PLEG报错 如果contained runtime不响应了那么relist就会失败relist失败那么这些状态就上报不了那么最终这个状态无法上报那么kubernets就会认为你整个节点有问题。所以runtime本身不响应那么这个节点会变的不正常。 还有就是bug退出容器的gc没有做好就节点上出现了几千上万的exit container在那里pleg再去跟runtime relist 这些container的时候他就会去遍历所有的已经退出的容器就会导致时间非常的长它没有办法及时返回所有容器的清单没有在它规定的时间内返回那么整个pleg的操作就超时了那么就会导致整个节点的状态发生变化。 当集群节点进入 NotReady 状态的时候我们需要做的第一件事情肯定是检查运行在节点上的 kubelet 是否正常。在这个问题出现的时候使用 systemctl 命令查看 kubelet 状态发现它作为 systemd 管理的一个 daemon是运行正常的。当我们用 journalctl 查看 kubelet 日志的时候发现下边的错误。 journalctl -u kubelet.servicejournalctl命令是用于查看和管理systemd日志的命令行工具。systemd是Linux系统的系统管理和初始化系统journalctl命令可以用来查看systemd的日志信息。 这个报错很清楚的告诉我们容器 runtime 是不工作的 [container runtime is down]且 PLEG 是不健康的 [PLEG is not healthy]。这里容器 runtime 指的就是 docker daemon。Kubelet 通过直接操作 docker daemon 来控制容器的生命周期。而这里的 PLEG指的是 pod lifecycle event generator。 基本上看到上边的报错我们可以确认容器 runtime 出了问题。在有问题的节点上通过 docker 命令尝试运行新的容器命令会没有响应。这说明上边的报错是准确的。​​​​​​​ kubelet创建并启动Pod Pod启动流程 高层运行时有两种一种docker一种containerd上图是以containerd来说明更加轻量。 步骤1用户去创建pod那么pod的请求会发给apiserverapiserver接收到请求之后会把对象存储到etcd里面 [吻合: apiserver与etcd的关系是apiserver单向调用etcd]存储完成之后调度器scheduler 就去watch到pod的创建时间并且完成调度绑定pod [scheduler完成了将这个新建的Pod放到哪个Node上]。 步骤2绑定之后也就是更新继续去etcd里面做持久化持久化完成之后kubelet就watch到已经绑定的pod。[此时开始kubelet管理所在Node上的新建的这个Pod] kubelet在启动pod的时候它启动的不是一个容器进程而是多个容器进程不仅仅启动了应用进程同时还启动了pause容器镜像的实例容器进程启动了之后可以把它和某个网络namespace产生关联关系把它放在某个网络namespace下面在这个独立的网络namesapce下面它可以有独立的网络配置如果直接将容器进程放到网络namesapce里面会出现什么样的问题呢 kubelet两个参数 –network-plugincni 表示Pod之间使用cni通信 –pod-infra-container-imagek8s.gcr.io/pause:3.4.1 表示Pod使用pause镜像启动一个pause容器,维持Pod生命周期,并且把这个pause容器放在一个network ns里面 你的容器进程可靠吗会不会有错误会不会异常退出oom空指针等等当出现这些问题的时候容器进程就退出了退出之后容器进程就和这个网络namespace之间的绑定关系就消失了如果不做一些措施的话那是不是每次容器进程退出都需要重新为这个容器进程配置网络那么这样的效率不会很高如果容器频繁重启那么就会导致节点上面多了很多不必要的系统操作。 有什么办法让容器进程退出的时候网络存储这些东西都不发生变化这就是为什么需要pause容器。在容器启动之前网络就需要就绪网络是要在容器之前就绪的这就需要额外的容器进程先启动起来。这个也是pause的功能。 pause容器里面entrypoint其实就是pause它永远sleep它是一个不会退出不消耗资源的一个稳定的进程那么所有的网络就可以挂载在这个pause上面当容器应用进程启动的时候我只需要将应用进程的网络namespace挂载在pause上面就行了。 即使容器出现各种问题重启没关系因为网络是挂载在其下面的。所以它就提供了非常稳定的基座。 解释: pause容器里面entrypoint其实就是pause, pause容器永远运行 在Kubernetes中Pause容器是一个特殊的容器它被用作Pod中其他容器的父容器。Pause容器不执行任何操作而只是保持运行状态以保持Pod的生命周期。当Pod中的所有其他容器退出运行时Pause容器仍然保持运行状态。 而entrypoint是容器在启动时运行的可执行程序或命令。对于Pause容器来说entrypoint就是容器启动时运行的空命令例如/pause而这个空命令并不会做任何实际的工作。它只是保持容器的运行状态以确保Pod在存在其他容器运行时保持处于活跃状态。 总之Pause容器的entrypoint就是一个空命令它的作用是保持容器的运行状态以保持Pod的生命周期并在其他容器退出运行时继续保持Pod的活跃状态。 更加详细的Pod启动过程 复述一下Pod启动pod启动的时候最先启动pause容器启动之后containerd就会去调用cni的插件去setup pod其实它会将ADD的命令告诉cni插件帮我setup网络cni这边setup网络之后会去将pod信息返回给runtime然后这个信息会返回给kubelet那么这个时候其实pod就有IP了这个时候才会去进行下面的用户应用容器的启动。 可以看到在启动容器的时候网络是已经就绪的所以有网络需求就可以满足了整个启动完之后就会将状态回写到Apiserver里面那么整个的启动过程就完成了。 上面是更加详细的Pod启动流程框图最左边是kubelet 中间是CRI 右边是CNI kubelet 最重要的功能是 syncPod 在这个 syncPod 操作之前包括五个步骤 步骤1. Check Admitkubelet在sync pod也就是做pod同步的时候首先也会去做准入比如它要去启动pod如果节点资源不够你非要将nodename设置为该节点因为和节点产生绑定关系那么就需要启动这个容器了启动的时候我要去check一下也需要去做准入的要去看你的cpu的需求满足不满足如果不满足就直接报错了out of cpu的error写回到这个pod状态里面。 步骤2. Check network plugin然后会去监听当前节点上网络插件的情况如果网络插件不就绪那么pod是启动不起来的所以这里也会直接报错。 步骤3. Update cgroupnamspace cgroup这些技术要去启动容器进程的时候要将容器对应的cgroup文件配置好。 步骤4. Makepoddirpod需要存储日志容器的日志需要在主机上有个目录它会去将数据目录创建起来。 步骤5. Wait For attach and mount你的pod是需要一些存储比如configmap轻量级存储只需要将文件下载下来然后mount到容器当中就行了如果是更高要求的存储比如网络存储那么需要去创建volume然后和这个节点产生attach关系然后再mount到容器里面其实就是等待存储就绪。 问题CRI CNI CSI它们之间关系是怎么样的呢在启动pod的时候谁先启动谁后启动 回答CRI (Container Runtime Interface)、CNI (Container Network Interface) 和 CSI (Container Storage Interface) 是 Kubernetes 中的三个关键组件分别负责容器运行时、容器网络和容器存储。它们之间的关系是 CRI负责与容器运行时如Docker、Containerd等进行通信以创建和管理容器。 CNI负责为容器提供网络连接包括为容器分配IP地址、配置网络路由等。 CSI负责为容器提供持久化存储功能包括挂载存储卷、快照、克隆等。 在启动Pod时先启动CRI来创建和管理容器然后CNI为容器分配网络连接最后CSI为容器提供持久化存储。因此启动顺序是先启动CRI然后启动CNI最后启动CSI。这样确保容器能够正常运行并连接到网络和存储资源。 上面可以很清晰看到 CSI 容器存储 就在kubelet这部分运行就是在pod后续加载还没有启动的时候我就得先去将存储挂载好并且mount进来。如果这一步不过的话它会一直卡在这里接下来才会去做syncpod。 syncpod里面就是来计算sandbox和容器变化如果sandbox发生变化了就是已经在运行的容器和我pod本身不匹配了那就是重建了这里面其实就是computer pod action的动作如果这个pod已经不存在了你的容器还在那么就需要将容器kill掉。 然后你要启动一个新的容器那么会去经历启动的动作。之前讲了第一步就是createpodsandbox它会去生成这些sandbox的config它有一些mainfest要将这些配置文件生成出来。然后pod的日志目录要创建好然后要去调用runtime的sandbox。 以containerd为例它的cri本身又是一个grpc的服务kubelet会去调用grpc服务这个时候整个请求就转到containerd进程里面kubelet就要暂时等待它的返回结果了。然后就是 create sandbox container然后一步一步的往下走最后由cri去调用cni的接口。 针对这种创建网络的请求其实就是setup网络的过程在cni里面是add network这种方法去实现的上面就是整个pod清单的获取一直到pod容器进程启动的这样一个过程。至于用户容器启动就不多说了。 kubelet CRI 容器运行时 CRI 容器运行时 kubelet在启动容器进程的时候要真正的启动这些容器进程随着版本的迭代它逐渐将启动过程当中这些标准的行为抽象为一个一个的接口。它的好处是kubelet就不需要和具体的runtime产生绑定关系了kubelet自己是一些代码框架它定义好这些接口它只需要调用这些接口由不同的容器运行时提供商来实现这些接口。让运行时可以适配我的标准这样可以使用你也可以不使用你这就是 SPI 机制 SPI 我定义我使用别人实现 API 我定义我实现别人使用 对于任何一个程序来说(也包括)最上层提供给别人使用的是自己的API接口最下层依赖/使用别人的SPI机制 这样我们就可以选择是使用docker还是containerd呢还是kata其他类型的容器这样就使得kubernetes就不和某一个运行时有具体的强绑定关系防止被某个厂商锁死。 容器运行时Container Runtime运行于KubernetesK8s集群的每个节点中负责容器的整个生命周期。其中Docker是目前应用最广的。随着容器云的发展越来越多的容器运行时涌现。为了解决这些容器运行时和Kubernetes的集成问题在Kubernetes1.5版本中社区推出了CRIContainer Runtime Interface容器运行时接口以支持更多的容器运行时。 如上图CRI就是将容器运行时的这些实现标准的接口都抽象出来了kubelet要去操作任何的容器进程都是通过CRI的接口然后不同的容器运行时会实现这些CRI接口最终去操作这些容器进程。 CRI 容器运行时架构 整体流程kubele调动高层运行时通过 CRI 规范接口高层运行时调用低层运行时通过 OCI 规范接口 kubelet是客户端可以看到在kubelet里面有grpc client它会去基于grpc框架去调用运行时服务类似docker containerd这类的服务。它是运行在kubelet之外的在安装kubernetes的时候会先去安装docker containerd安装完之后再去安装kubelet。 这样的话kubelet作为客户端来调用runtime的接口。这些runtime就要按照CRI的规范去实现那些接口。 容器运行时最终的目的是要去启动一个一个的容器进程所以你可以理解为容器运行时它本身是一个中间层它向上面对的是kubelet向下面对的是这些容器进程。所以它分为high-level-runtime和low-level-runtimehigh-level-runtime是对外提供的这些grpc服务。由客户端grpc client来调用这些服务它接受到这些请求需要通过low-level的api去启动和操作这些容器。它(指高层运行时)有点像一层代理它只是做命令的转发接受来自客户端的请求然后再去操作下面的容器进程。它所谓的low-level-runtime容器的话就是runc。 kubele调动高层运行时通过 CRI 规范接口 Dockershim containerd和CRI-O都是遵循CRI的容器运行时 我们称他们为高层级运行时(High-level Runtime)。kubele调动高层运行时通过 CRI 规范接口。 CRI是Kubernetes定义的一组gRPC服务。kubelet作为客户端基于gRPC框架通过Socket和容器运行时通信。CRI 包括两类服务∶镜像服务Image Service和运行时服务Runtime Service。 (1) 镜像服务提供下载、检查和删除镜像的远程程序调用。 (2) 运行时服务包含用于管理容器生命周期以及与容器交互的调用exec/attach/port-forward的远程程序调用。 imageservice提供了很多接口主要是对image相关的操作。 runtimeservice同样通过了很多接口可以看到对sandbox有很多操作以及和对用户容器相关的。 高层运行时调用低层运行时通过 OCI 规范接口 容器运行时最终遵循了oci的一个标准oci定义了容器相关的行业标准。这个行业标准主要分为了三大类定义了镜像如何打包、如何解压的这样一个规范、通过镜像如何去运行容器进程这样的一个规范。 OCIOpen Container Initiative开放容器计划定义了创建容器的格式和运行时的开源行业标准包括镜像规范Image Specification和运行时规范Runtime Specification。 镜像规范定义了OCI镜像的标准。高层级运行时将会下载一个OCI镜像并把它解压成 OCI运行时文件系统包filesystem bundle还有存储镜像文件到指定的目录下。 运行时规范则描述了如何从OCI运行时文件系统包运行容器程序并且定义它的配置、运行环境和生命周期。如何为新容器设置命名空间namepsaces和控制组cgroups以及挂载根文件系统等等操作都是在这里定义的。它的一个参考实现是runC。我们称其为低层级运行时Low-level R untime。除runC以外也有很多其他的运行时遵循OCI标准例如kata-runtime。 CRI 高层运行时和低层运行时 高层运行时和低层运行时 容器运行时是真正管理容器的组件分为高层运行时和低层运行时。高层运行时由 Docker、containerd或CRI-O 充当 低层运行时由 runc、kata 或 gVisor 充当。低层运行时 kata 和 gVisor 都处于小规模落地或者实验阶段其生态成熟度和使用案例都比较欠缺所以除非有特殊的需求否则 runc 几乎是必然的选择。因此对于容器运行时的选择上主要聚焦与高层运行时的选择。 容器运行时包括高层运行时和低层运行时流程是 kubelet 调用高层运行时高层运行时调用低层运行时低层运行时调用具体业务容器。在整个业务流程中kubelet和具体业务流程是不可选择的但是高层运行时和低层运行时是可选择的。 高层运行时有 Docker containerd 和 cri-o 三种可以选择具体选择那种下面会讨论这三种的优劣一般是 containerd 和 cri-o 比较好。 低层运行时目前只有 runc 一种可用那就那没得选就是 runc。 如何查看当前k8s集群的高层运行时和低层运行时 kubectl get nodes -o jsonpath‘{range .items[*]}{.metadata.name}{“\n”}{.status.nodeInfo.containerRuntimeVersion}{“\n”}{.status.nodeInfo.containerRuntimeVersion}{end}’ 该命令将返回一个包含每个节点名称和容器运行时版本的列表。通常如果你安装了Docker那么结果应该显示Docker的版本号。如果你使用其他容器运行时你将看到相应的版本号。 kubectl get nodes 获取节点的信息。这将返回所有集群中的节点列表。 -o jsonpath 使用 JSON 路径格式化输出结果。 [-o 表示 output, 后面的 jsonpath 表示输出格式] ‘…’ JSON 路径的模板包裹在引号中。其中使用 {} 定义占位符来引用节点属性。 {range .items[*]} 是一个迭代器用于遍历每个节点的列表。 .metadata.name 引用节点的名称。 {“\n”} 是一个换行符用于在每个节点信息之间添加换行。 .status.nodeInfo.containerRuntimeVersion 引用节点的容器运行时版本。 最后{end} 表示结束迭代。 {.metadata.name}{“\n”} 输出节点名称这里为 m {.status.nodeInfo.containerRuntimeVersion}{“\n”} 输出该节点的容器运行时版本 {.status.nodeInfo.containerRuntimeVersion}{end} 输出该节点的容器运行时版本 直接使用 kubectl get nodes -o json 也可以看到 使用 kubectl describe nodes m 也可以看到 另外你还可以通过逐个检查每个节点上运行的容器运行时进程来确定。连接到每个节点并使用以下命令检查运行的容器运行时进程 ps -ef | grep containerd这将在节点上查找名为containerd的进程。如果存在则使用Containerd作为高层运行时。同样你还可以使用其他容器运行时的进程名称进行检查如Docker“docker”或CRI-O“crio”等。 高层运行时: 从docker到containerd Docker 内部关于容器化运行时功能的核心组件是 containerd 后来 containerd 也可以直接和 kubelet 通过 CRI SPI 对接独立在 k8s 中使用。(即 containerd 可以独立作为一个进程运行不一定需要放在 docker 进程里面) 相对于 docker 而言containerd 减少了 docker 所需的处理模板 dockerd 和 docker-shim 并且对 docker 支持的存储驱动进行了优化因此在容器的创建爱你、启动、停止、删除已经对镜像的拉取上都具有性能上的优势。 架构的简化同时也带来了维护的遍历。当然 docker 也具有很多 containerd 不具有的功能 (因为 containerd 是docker的简化)尽管如此containerd 目前也基本能够满足容器的众多管理需求所以将它作为运行时的也越来越多。 containerd是能够取代docker的因为docker本身内嵌了containerd的docker是一个独立的产品我们可以通过docker的命令去管理自己的网络管理自己的存储所以docker大部分臃肿的逻辑都在docker daemon它自身的逻辑上面这些逻辑处理完之后也是将请求发给自带内嵌的containerd里面去 这样其实真正执行的逻辑是在containerd里面。 存储网络是kubernetes和docker之间的竞争在kubernetes里面用的都是kubernetes管理的这套体系那么docker的那部分其实是冗余的。不再使用docker自身的daemon了但是可以用你docker自身所带的containerd的。 三种高层运行时比较 上面说的高层运行时包括三种所以有选择的余地低层运行时只有一种就是runc,所以只能选它。 上面是三个常用的运行时最上面的路径其实是最长的。 (1) 如果是docker运行时那么是kubelet调用dockeshim调用docker再去调用containerdcontainerd再通过runc的接口去调用底层的容器进程。 (2) 如果是containerd那么就没有docker-shim和docker直接由kubelet发起命令到containerd然后containerd到runc。 (3) 如果是crio那么更加轻量级kubelet调用crio然后直接调用runc。 越来越简洁。 Docker和Containerd的细节差异 方式1(图片上半部分)如果是通过kubelet去调用docker的话这个请求是在kubelet的cri接口调用docker-shimdocker-shim再连接到docker-daemondocker-daemon里面红圈的这部分才是有用的也就是和image相关的操作以及正真去去调用containerd的这部分操作是有用的上面存储网络已经docker提供的cli这些都是不需要的那么这些都是冗余的。 方式2(图片下半部分)如果将docker换掉的话那么红线外的部分就没有了那么复杂性就大大降低的直接使用cri的接口调用containerd移除了这些不必要的调用转发环节这样整个系统架构更加简单。 上面就是理解去掉docker的意义这是一个必要的动作。 Containerd和CRI-O的性能比较 在选型的时候一个是架构的简单程度稳定性还有它的性能。 小结 问题kubelet是如何调用容器的 回答kubelet 通过基于 SPI 机制通过 CRI 接口调用 高层运行时然后高层运行时调用低层运行时然后低层运行时调用 Container 容器。高层运行时和低层运行时都是逻辑上的概念需要具体实现的中间件。当前的高层运行时只有 dockershim containerd cri-o 三种选择低层运行时只有 runC 可以选择。 注意kubelet是如何和docker打交道的 kubelet和docker的cgroupDriver必须相同 尾声 参考资料kubelet 架构 kubelet 职责 kubelet 管理 Pod kubelet 创建并启动 Pod kubelet CRI 容器运行时
http://wiki.neutronadmin.com/news/22785/

相关文章:

  • 做视频网站需要多少钱新闻发布会发言稿范文
  • 仿新浪微博网站代码中国建设信用卡网站
  • 微官网 手机网站苏州电商网站建设
  • 民政 门户网站 建设设计作品图片
  • 广州网站建设网站优化网站推广开发简单小程序公司
  • 网站怎么放在服务器上wordpress 晒单
  • 邗江区做网站企业文化展厅设计
  • 临沂建设公司网站网站建设 淘宝描述
  • 西宁做网站的有吗网站制作算是什么专业
  • 课程网站建设课程免费版网站建设合同
  • 怎样查找网站开发者怎么做下载类的网站吗
  • 用vs2012怎么做网站网上申请平台怎么申请
  • 长沙cms模板建站权威的深圳动画营销推广
  • 医院网站建设投标书给客户做非法网站
  • 上海网站营销公司建设银行办信用卡网站首页
  • 网站顶部地图代码怎么做的网站架构的优化
  • 杭州品牌网站设计自己做的网站能卖么
  • 企业网站建设与网络营销的关系母婴网站模板dede
  • 做磁力搜索网站好吗马云的网站是谁建设的
  • 创建网站成功案例动漫网页制作源代码
  • 机械技术支持东莞网站建设内容管理系统开源
  • 做网站开发工资怎样搜索引擎推广文案
  • 手机网站建设价格是多少wordpress主题ux themes
  • .php是什么网站windows系统做网站
  • 买极速赛车网站会动手做不石家庄微网站建设公司哪家好
  • 做网站价格报价费用多少钱汕头网站推广哪家好
  • 黄陂区建设局网站新加坡服务器网站需要备案么
  • 网站建设需求说明文档网页版微信无法登录
  • 免费发布广告信息的网站嵌入式培训心得
  • python网站开发视频教程外贸 需要到国外建网站吗