首页 > 其他分享 >20-资源优化:Kubernete 中有 GC(垃圾回收)吗?

20-资源优化:Kubernete 中有 GC(垃圾回收)吗?

时间:2024-01-11 13:44:38浏览次数:35  
标签:容器 20 删除 ReplicaSet -- GC Kubernetes Kubernete

Garbage Collector 即垃圾回收,通常简称 GC,和你之前在其他编程语言中了解到的 GC 基本上是一样的,用来清理一些不用的资源。Kubernetes 中有各种各样的资源,当然需要 GC啦,今天我们就一起来了解下 Kubernetes 中的 GC。

你可能最先想到的就是容器的清理,即 Kubelet 侧的 GC,清理许多处于退出(Exited)状态的容器,那么就先来了解一下吧。

Kubelet GC

GC 在 Kubelet 中非常重要,它不仅可以清理无用的容器,还可以清理未使用的镜像以达到节省空间的目的。当然 Kubelet 清理的这些容器都是 Kubernetes 自己创建的容器,你通过 Docker 手动创建的容器均不在 GC 的范围内,所以不必过于担心。

Kubelet 会对容器每分钟执行一次 GC 操作,对容器镜像每 5 分钟执行一次 GC 操作,这样可以保障 Kubelet 节点的稳定性,避免节点出现资源紧缺的情况。Kubelet 刚启动时并不会立即执行 GC 操作,而是在启动 1 分钟后开始执行第一次对容器的 GC 操作,启动 5 分钟后开始执行第一次对容器镜像的回收操作。这里建议你最好不用使用其他外部的 GC 工具,有可能会破坏 Kubelet 的 GC 逻辑。

目前 Kubelet 提供了 3 个参数,可以方便你调整容器镜像的 GC 参数:

  • --minimum-image-ttl-duration表示一个镜像在清理前的最小存活时间;

  • --image-gc-high-threshold表示磁盘使用率的上限阈值,默认值是 90%,即当磁盘使用率达到 90% 的时候会触发对镜像的 GC 操作;

  • --image-gc-low-threshold表示磁盘使用率的下限阈值,默认值是 80%,即当磁盘使用率降到 80% 的时候,GC 操作结束。

对镜像的 GC 操作,就是逐个删除最久最少使用(Least Recently Used)的镜像。

对于容器的 GC 操作,Kubelet 也提供了 3 个参数供你使用调整:

  • --minimum-container-ttl-duration表示已停止的容器在被清理之前最小的存活时间,默认值是 1 分钟,即容器停止超过 1 分钟才会被标记可被 GC 清理;

  • --maximum-dead-containers-per-container表示一个 Pod 内可以保留的已停止的容器数量,默认值是 2。Kubernetes 是以 Pod 为单位进行容器管理的。有时候 Pod 内运行失败的容器,比如容器自身的问题,或者健康检查失败,会被 kubelet 自动重启,这将产生一些停止的容器;

  • --maximum-dead-containers表示在本节点上可以保留的已停止容器的最大数量,默认值是240。毕竟这些容器也会消耗额外的磁盘空间,所以超过这个上限阈值后,就会触发 Kubelet 的 GC 操作,来帮你自动清理这些已停止的容器,释放磁盘空间。

当然,如果你想要关闭容器的 GC 操作,只需要将--minimun-container-ttl-duration设置为0,把--maximum-dead-containers-per-container--maximum-dead-containers都设置为负数即可。

在有些场景中,容器的日志需要保留在本地,如果直接清理掉这些容器会丢失日志。所以这里我强烈建议你将--maximum-dead-containers-per-container设置为一个足够大的值,以便每个容器至少有一个退出的实例。这里,你就可以根据自己的场景进行配置。

提到的这些 flag,目前仍能继续使用,在未来的版本中,Kubernetes 会用新的 flag 进行替换,详见官方文档。我们会在下一节课中,介绍这个新的 flag 的用法。

除了这些基本的 GC 以外,Kubernetes 内部也有很多操作对象,而且这些对象之间还存在着一定的“从属关系”,比如 Deployment 管理着 ReplicaSet。下面我们就来了解下 Kubernetes 内部对象的 GC。

Kubernetes 内部对象的 GC

通过之前的学习,我们已经知道创建好一个 Deployment 以后,kube-controller-manager 会帮助我们创建对应的 ReplicaSet。这些 ReplicaSet 会自动跟我们创建的 Deployment 进行关联,那 Kubernetes 是怎么样维护这种从属关系的呢?

在 Kubernetes 中,每个对象都可以设置多个 OwnerReference,即该对象从属于谁。

我们先来看看 OwnerReference 的定义:

// OwnerReference contains enough information to let you identify an owning
// object. An owning object must be in the same namespace as the dependent, or
// be cluster-scoped, so there is no namespace field.
type OwnerReference struct {
    // API version of the referent.
    APIVersion string `json:"apiVersion" protobuf:"bytes,5,opt,name=apiVersion"`
    // Kind of the referent.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
    // Name of the referent.
    // More info: http://kubernetes.io/docs/user-guide/identifiers#names
    Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
    // UID of the referent.
    // More info: http://kubernetes.io/docs/user-guide/identifiers#uids
    UID types.UID `json:"uid" protobuf:"bytes,4,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"`
    // If true, this reference points to the managing controller.
    // +optional
    Controller *bool `json:"controller,omitempty" protobuf:"varint,6,opt,name=controller"`
    // If true, AND if the owner has the "foregroundDeletion" finalizer, then
    // the owner cannot be deleted from the key-value store until this
    // reference is removed.
    // Defaults to false.
    // To set this field, a user needs "delete" permission of the owner,
    // otherwise 422 (Unprocessable Entity) will be returned.
    // +optional
    BlockOwnerDeletion *bool `json:"blockOwnerDeletion,omitempty" protobuf:"varint,7,opt,name=blockOwnerDeletion"`
}

在 OwnerReference 中,我们可以确定该对象所“从属于”的对象,从而建立两者之间的从属关系。我们通过一个例子,直观了解下这个“从属”关系:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  annotations:
    deployment.kubernetes.io/desired-replicas: "2"
    deployment.kubernetes.io/max-replicas: "3"
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2020-09-03T07:22:35Z"
  generation: 1
  labels:
    k8s-app: kube-dns
    pod-template-hash: 5644d7b6d9
  name: coredns-5644d7b6d9
  namespace: kube-system
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: Deployment
    name: coredns
    uid: 37ae660a-dba8-4ff9-a152-7d6f420e624d
  resourceVersion: "1542272"
  selfLink: /apis/apps/v1/namespaces/kube-system/replicasets/coredns-5644d7b6d9
  uid: fa3d9859-43d4-484b-9716-7536243acd0f
spec:
  replicas: 2
  ...
status:
  ...

这里我截取了一个 ReplicaSet 中的 metadata 的部分。注意看这个 ReplicaSet 的ownerReferences字段标识了一个名为 coredns 的 Deployment 对象。

同样,我们来看看该 ReplicaSet 管理的 Pod。这里 ReplicaSet 的副本数是 2,我们任意选择其中一个 Pod:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-09-03T07:22:35Z"
  generateName: coredns-5644d7b6d9-
  labels:
    k8s-app: kube-dns
    pod-template-hash: 5644d7b6d9
  name: coredns-5644d7b6d9-sz4qj
  namespace: kube-system
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: coredns-5644d7b6d9
    uid: fa3d9859-43d4-484b-9716-7536243acd0f
  resourceVersion: "1542270"
  selfLink: /api/v1/namespaces/kube-system/pods/coredns-5644d7b6d9-sz4qj
  uid: c52d630b-1840-4502-88d1-b67bed2dd625
spec:
  ...

可以看到该 Pod 的ownerReferences指向刚才的 ReplicaSet,名字和 UID 都与之相对应。

至此通过观察这几个对象中的ownerReferences的信息,我们可以建立起如下的“从属关系”,即:

  • Deployment(owner)—> ReplicaSet (dependent);

  • ReplicaSet (owner) —> Pod (dependent)。

了解了如上从属关系,我们后续就可以进行 GC 了。比如当你想彻底删除一个 Deployment 的时候,这时候 Kubernetes 会自动帮你把相关联的 ReplicaSet、Pod 等也一并删除掉,那么这种删除行为也称之为级联删除(Cascading Deletion),这也是 Kubernetes 默认的删除行为。

对于级联删除,Kubernetes 提供了两种模式,分别为后台(Background)模式和前台(Foreground)模式。

我们以后台级联删除 Deployment 为例。直观的体验就是,当你使用后台模式删除时,发送完请求,Kuberentes 会立即删除主对象,比如 Deployment,之后 Kubernetes 会在后台 GC 其附属的对象,比如 ReplicaSet。

而对于前台级联删除,会先删除其所属的对象,然后再删除主对象。依然以 Deployment 为例,这时候主对象 Deployment 首先进入“删除中”的状态,虽然你依然能够通过 REST API 看到该 Deployment,但是该对象的deletionTimestamp字段被设置非空即“删除中”。

同时该对象的 metadata.finalizers 字段为 foregroundDeletion,有了这个 fianlizer 的存在,该对象就不会被删除,并会一直处于“删除中”的状态。

然后开始删除 ReplicaSet。关联的 ReplicaSet 都被删除以后,主对象 Deployment 中metadata.finalizers 字段会移除 foregroundDeletion 这个 finalizer。这时候主对象就可以被删除掉了。你也许注意到了 ownerReference 字段中的 blockOwnerDeletion,只有这个字段设置为了 true,才会组织删除主对象。

当然如果你删除对象的时候,并不想自动删除其附属对象,那么这些附属对象就“孤立”存在了,即孤立对象(Orphaned)。比如删除 Deployment 的时候,并不想删除其关联的 ReplicaSet。

我们可以通过 deleteOptions.propagationPolicy 这个字段,来控制删除的策略,取值包括上面提到的三种方式,即 Orphan、Foreground 或者 Background。

如果我们使用 kubectl 进行后台删除的时候,可以通过如下命令进行操作:

$ kubectl proxy --port=8080
$ curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-replicaset \
  -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
  -H "Content-Type: application/json"

当然如果你使用的是 client-go 这类的库,也可以通过库中提供的函数,通过设置 DeleteOption 进行后台删除。
同样,我们也可以通过如下命令进行前台级联删除:

$ kubectl proxy --port=8080
$ curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-replicaset \
  -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
  -H "Content-Type: application/json"

这里如果你只想删除 ReplicaSet,但是并不像删除其关联的 Pod,你可以这么操作:

$ kubectl proxy --port=8080
$ curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
  -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
  -H "Content-Type: application/json"

kubectl 命令行在删除操作的时候,默认是进行级联删除的,如果你不想级联删除,可以这么操作:

$ kubectl delete replicaset my-repset --cascade=false

写在最后

Kubernetes 默认开启了 GC 的能力,不管是对于内部的各种 API 对象,还是对于 kubelet 节点上的冗余镜像以及退出的容器。这些默认的配置,已经基本上满足我们绝大多数的使用需要,不需要额外配置。当然你也可以通过调整一些参数和策略,实现自己的业务场景和逻辑。

到这里这节课就结束了,如果你对本节课有什么想法或者疑问,欢迎你在留言区留言,我们一起讨论。


标签:容器,20,删除,ReplicaSet,--,GC,Kubernetes,Kubernete
From: https://www.cnblogs.com/huangjiale/p/17958415

相关文章

  • 02-高屋建瓴:Kubernete 的架构为什么是这样的?
    通过上一课时的学习,我们已经对Kubernetes的前世今生有所了解。接下来,我们开始具体学习如何将Kubernetes应用到自己的项目中,首先就需要了解Kubernetes的架构。所以,在本节课程中,我们会一起学习Kubernetes的架构设计,以及背后的设计哲学。Google使用Linux容器有超过15年......
  • 03-集群搭建:手把手教你玩转 Kubernete 集群搭建
    通过上一节课的学习,我们已经对Kubernetes的架构有了清楚的认识。但是到现在还没有和Kubernetes集群真正打过交道,所以你可能有一种“不识庐山真面目”的云里雾里的感觉。那么本节课,我们就来学习如何搭建Kubernetes集群,开启探索Kubernetes的第一站。在线Kubernetes集群......
  • 04-核心定义:Kubernete 是如何搞定“不可变基础设施”的?
    在上一节课,我们已经了解了Kubernetes集群的搭建方式。从现在开始,我们就要跟Kubernetes集群打交道了。本节课我们会学习Kubernetes中最重要、也最核心的对象——Pod。在了解Pod之前,我们先来看一下CNCF官方是怎么定义云原生的。云原生技术有利于各组织在公有云、私有云......
  • 06-无状态应用:剖析 Kubernete 业务副本及水平扩展底层原理
    在上两节课中,我们已经了解了Kubernetes中最关键的对象Pod,也学习了一些Pod的常见用法。每一个Pod都是应用的一个实例,但是通常来说你不会直接在Kubernetes中创建和运行单个Pod。因为Pod的生命周期是短暂的,即“用后即焚”。理解这一点很重要,这也是“不可变基础设施”这......
  • 07-有状态应用:Kubernete 如何通过 StatefulSet 支持有状态应用?
    在上一节课中,我们学习了Kubernetes中的无状态工作负载,并上手实践了Deployment对象,相信现在你已经慢慢喜欢上Kubernetes了。那么本节课,我们来一起看看Kubernetes中的另外一种工作负载StatefulSet。从名字就可以看出,这个工作负载主要用于有状态的服务发布。关于有状态服务......
  • 前世今生:Kubernete 是如何火起来的?
    本课时,我们就开始正式进入Kubernetes的学习,或许你已经听过或简单了解过Kubernetes,它是一款由Google开源的容器编排管理工具,而我们想要深入地掌握Kubernetes框架,就不得不先了解Kubernetes的前世今生,而这一切都要从“云计算”的兴起开始讲起。云计算平台说来也巧,“云计算......
  • P4103 [HEOI2014] 大工程 题解
    题目链接:大工程先考虑只有一次查询,很显然我们可以暴力树上dp处理出答案。对于每个节点而言,有:容易看出类似点分治逐个遍历子树计算前面一堆子树对后面子树的贡献思想,我们可以很容易的知道:对于路径总和,显然多了一段新的贡献,这段贡献为当前关键点和前面点多的一段\(2\)号路......
  • 引领文旅创新_实时云渲染赋能2023湾区文采会元宇宙虚拟展厅
    2023年11月3日,2023粤港澳大湾区公共文化和旅游产品(东莞)采购会(下文简称:2023湾区文采会)开幕式在东莞市文化馆举行。本届大湾区文采会以“文采潮流融合共生”为主题,集聚了科技、时尚、潮流等关键元素,吸引了近900家文旅单位、文创机构、文化装备制造企业参展,展出超16000个产品。图......
  • CTSC 2016 香山的树
    题意给定\(n,k\)和Lyndon串\(s_1\),求长度小于等于\(n\)的Lyndon串中,按照字典序排在\(s_1\)后面\(k-1\)名的串\(s_k\),或报告无解。\(1\len\le50,1\lek\le10^{15}\)。Lyndon串:字典序严格小于所有自己真后缀的串题解只需要计数拥有某个给定前缀\(p\)的......
  • 美国本科留学期间受处分I20被开除,跨本申硕也能拿学位
    美国本科留学期间受处分I20被开除,跨本申硕也能拿学位留学期间因出勤、学分、GPA、学术诚信的情况被开除并取消I20,见太多。I20和签证失效学生就要离开美国境内,许多学生为了保留身份会立马选择一个同意挂靠学籍和发放I-20的院校,让自己能继续以学生的身份留在美国。可是那些院校真的是......