当前位置: 首页 > 科技观察

Kubernetes中的垃圾收集

时间:2023-03-14 21:19:46 科技观察

考虑一个场景;您在Kubernetes中创建一个部署对象;因此,它会根据提供的清单生成副本集和Pod。后来,您意识到您错过了一个容器的属性,为了快速修复,您编辑了部署。版本部署会产生新的副本集对象和更新的Pod。知道旧的会发生什么吗?同样,如果删除部署,副本集或Pod会发生什么情况。答案很明显。删除部署将删除副本集和Pod;否则,这将是一团糟。上面的说法引出了一个更大的问题:Kubernetes中的级联删除是如何实现的,是否有多种级联删除策略,K8s中是否可能存在孤儿对象?看起来这是一个典型的垃圾收集问题。这篇文章将讨论Kubernetes中垃圾收集的概念和实现。首先,让我们快速探索一下垃圾收集。什么是垃圾收集(GC)?简单地说,垃圾回收就是从系统中移除不用的对象,并释放分配给它们的计算资源。GC存在于所有高级编程语言中,而低级编程语言通过系统库有GC。最常见的GC算法之一是标记清除。我没有深入算法的细节,但我们可以从标题有两个阶段的角度来解释它,在第一阶段标记在清理阶段删除的对象。>来自维基百科这里是对GC的非常简短的解释,如果需要,请点击参考部分中发布的链接以获得更详细的解释。现在,我们将探索在K8s中实现GC的方法。所有者拥有;OwnerReferencemetadata像面向对象的语言一样,一些对象引用/组成其他对象,在Kubernetes中以类似的方式,一些对象拥有其他对象。例如,副本集是一组Pod的所有者,部署是副本集的所有者。与面向对象语言不同,在K8的对象清单定义中,我们从未明确定义或编码与所有者相关的关系,但系统如何确定这种关系?在K8s中,每个从属对象都有一个唯一的meta数据字段名metas.ownerReferences用于关系表示。从Kubernetes1.8开始,K8s为ReplicaSet、StatefulSet、DaemonSet、Deployment、Job、CronJob等特定控制器创建或采用的对象设置了ownerReferences的值。如果需要,也可以手动设置OwnerReferences。一个对象可以有多个ownerReferences,例如在一个命名空间中。下面显示了KindK8s独立集群上core-dns部署的metadata.ownerReferences值。如果仔细查看上述命令的输出,您会注意到与其他GC实现的细微差别。对象交叉引用金字塔是颠倒的,而不是常规的颠倒。下图将为您提供帮助。>K8sKubernetes中对象DownsideUp关联中的垃圾收集策略前面提到,在Kubernetes1.8之前,依赖对象删除逻辑的实现是在客户端,有些资源也是在控制器端。client不是原子操作,有时候中间出现故障会导致集群状态乱七八糟,需要手动清理。后来,为了解决这个问题,K8s社区引入并实现了垃圾收集器控制器,以更好更简单的方式处理GC。在K8s中,对于未使用对象的GC,有两大类:级联:在其中一种级联中,删除所有者会导致从集群中删除依赖对象。孤儿:顾名思义,对所有者对象的删除操作只是将其从集群中删除,并使所有依赖对象处于“孤儿”状态。让我们更深入地了解上述策略。在级联删除策略中,依赖对象与所有者对象一起删除。在级联中,有两种模式:前景和背景。前台级联删除:在前台策略中,所有者对象删除等到所有从属对象都被删除。当前台删除是所有者对象的状态更改为正在进行删除时,会发生第一个更改。处于“正在删除”状态的对象的属性如下:通过RESTAPI,对象仍然可见设置了对象的deleteTimestamp对象的metadata.finalizers包含值“foregroundDeletion”。一旦状态发生变化,垃圾收集器将删除所有“阻塞”依赖项(所有者引用.blockOwnerDeletion=true的对象),最后删除所有者对象。后台级联删除:这个就简单多了,这里直接删除owner对象。稍后,GC确定相关对象并将其从后台移除。它比前台快很多,因为删除依赖对象没有等待时间。在孤立策略中,所有者对象被删除,依赖对象中的ownerReferences元数据设置为默认值。之后,GC控制器确定孤立对象并将其删除。Kubernetes垃圾收集器控制器如何工作?如果GC控制器的OwnerReferences元数据中没有任何所有者对象,则GC控制器负责删除该对象。GC控制器由扫描器、垃圾处理器和撒布器组成。Scanner:使用discoveryAPI,检测K8s集群支持的所有资源,并通过控制循环定期检测,扫描系统中的所有资源,并将每个对象添加到“脏队列”中。垃圾处理器:由处理“脏队列”的工作人员组成。每个工作人员将从“脏队列”中取出一个项目并检查该项目的OwnerReferences是否为空。如果为空,则只从Dirty队列中取出下一个条目进行处理;否则,将检查OwnerReferences元数据中的每个条目。如果OwnerReferences中列出的所有者都不存在,则工作人员请求API服务器删除该对象。Propagator:传播器用于优化GC控制器,由三个部分组成。事件队列、个体工作者和所有者相关关系的DAG。下面是breederDAG的特点只存储name/uid/orphan三元组,而不是每个项目的整个主体。监视创建/更新/删除事件的所有资源并将事件排入事件队列。工作人员从事件队列中取出项目。K8s对象的创建或更新相应地更新DAG。如果资源有所有者,但DAG中不存在该所有者,那么除了将对象添加到DAG之外,它还会将该对象排入“脏队列”。删除K8s对象会将其从DAG中移除,并将其所有依赖对象排入“脏队列”。communicator不需要做任何RPC,所以只需要一个工作线程就足够了,而且更容易锁定。使用传播器,我们只需要在GC启动时运行扫描器来填充DAG和脏队列。总的来说,KubernetesGC的实现是非常通用和复杂的,而且非常高效。希望这篇文章能帮助大家理解GC在K8s中的感悟。感谢阅读并期待反馈或赞赏。