• (转)Kubernetes GC设计原则


     Ref

      Warning:设计文档的对应的 k8s 版本为1.7

    Q: What is GC of Kuernetes ? (k8s垃圾回收是什么?)

      GC 是 Garbage Collector 的简称。从功能层面上来说,它和编程语言当中的「GC」 基本上是一样的。它清理 Kubernetes 中「符合特定条件」的 Resource Object。(在 k8s 中,你可以认为万物皆资源,很多逻辑的操作对象都是 Resource Object。)

    Q: What are dependent mechanisms to clear needless resource objects?(清除不必要的资源对象的依赖机制是什么?)

      Kubernetes 在不同的 Resource Objects 中维护一定的「从属关系」。内置的 Resource Objects 一般会默认在一个 Resource Object 和它的创建者之间建立一个「从属关系」。

      当然,你也可以利用 ObjectMeta.OwnerReferences 自由的去给两个 Resource Object 建立关系,前提是被建立关系的两个对象必须在一个 Namespace 下。

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

       OwnerReference 一般存在于某一个 Resource Object 信息中的 metadata 部分。

       OwnerReference 中的字段可以唯一的确定 k8s 中的一个 Resource Object。两个 Object 可以通过这种方式建立一个 owner-dependent 的关系。

       K8s 实现了一种「Cascading deletion」(级联删除)的机制,它利用已经建立的「从属关系」进行资源对象的清理工作。例如,当一个 dependent 资源的 owner 已经被删除或者不存在的时候,从某种角度就可以判定,这个 dependent 的对象已经是异常(无人管辖)的了,需要进行清理。而 「cascading deletion」则是被 k8s 中的一个 controller 组件实现的: Garbage Collector 

      所以,k8s 是通过 Garbage Collector 和 ownerReference 一起配合实现了「垃圾回收」的功能。

    Q: What is the relationship like ?(owner-dependent)

      我们可以通过一个实际的例子来了解这个「从属关系」:

     1 apiVersion: extensions/v1beta1
     2 kind: ReplicaSet
     3 metadata:
     4   annotations:
     5     deployment.kubernetes.io/desired-replicas: "2"
     6     deployment.kubernetes.io/max-replicas: "3"
     7     deployment.kubernetes.io/revision: "1"
     8   creationTimestamp: 2018-09-07T07:11:52Z
     9   generation: 1
    10   labels:
    11     app: coffee
    12     pod-template-hash: "3866135192"
    13   name: coffee-7dbb5795f6
    14   namespace: default
    15   ownerReferences:
    16   - apiVersion: apps/v1
    17     blockOwnerDeletion: true
    18     controller: true
    19     kind: Deployment
    20     name: coffee
    21     uid: 4b807ee6-b26d-11e8-b891-fa163eebca40
    22   resourceVersion: "476159"
    23   selfLink: /apis/extensions/v1beta1/namespaces/default/replicasets/coffee-7dbb5795f6
    24   uid: 4b81e76c-b26d-11e8-b891-fa163eebca40
    25 spec:
    26   replicas: 2
    27 ....

      上面截取了一个 ReplicaSet Object 中的 metadata 的部分信息。

      我们可以注意到,它的 ownerReferences 字段标识了一个 Deployment Object。我们都清楚的是,ReplicaSet 会创建一系列的 Pod。通过 spec.replicas:2 可以知道,他会创建两个pod。

    1 root@xr-service-mesh-lab:~/istio-1.0.2# kubectl get pods  | grep coffee
    2 coffee-7dbb5795f6-6crxz          1/1       Running   0          9d
    3 coffee-7dbb5795f6-hv7tr          1/1       Running   0          5d
    4 root@xr-service-mesh-lab:~/istio-1.0.2#

      让我们来观察其中一个 Pod:

     1 apiVersion: v1
     2 kind: Pod
     3 metadata:
     4   annotations:
     5     cni.projectcalico.org/podIP: 192.168.0.14/32
     6   creationTimestamp: 2018-09-07T07:11:52Z
     7   generateName: coffee-7dbb5795f6-
     8   labels:
     9     app: coffee
    10     pod-template-hash: "3866135192"
    11   name: coffee-7dbb5795f6-6crxz
    12   namespace: default
    13   ownerReferences:
    14   - apiVersion: apps/v1
    15     blockOwnerDeletion: true
    16     controller: true
    17     kind: ReplicaSet
    18     name: coffee-7dbb5795f6
    19     uid: 4b81e76c-b26d-11e8-b891-fa163eebca40
    20   resourceVersion: "76727"
    21   selfLink: /api/v1/namespaces/default/pods/coffee-7dbb5795f6-6crxz
    22   uid: 4b863e4d-b26d-11e8-b891-fa163eebca40

      我们可以看出,pod 中的 ownerReferences 所标识的 Object 正式我们上面看到过的 ReplicaSet。最后让我们来检查一下 ReplicaSet 所对应的 Deployment 的情况:

     1 apiVersion: extensions/v1beta1
     2 kind: Deployment
     3 metadata:
     4   annotations:
     5     deployment.kubernetes.io/revision: "1"
     6   creationTimestamp: 2018-09-07T07:11:52Z
     7   generation: 1
     8   labels:
     9     app: coffee
    10   name: coffee
    11   namespace: default
    12   resourceVersion: "476161"
    13   selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/coffee
    14   uid: 4b807ee6-b26d-11e8-b891-fa163eebca40

      对比一下 ReplicaSet Object 中 ownerReference 标识的 Object 可知,这个 Deployment 是 ReplicaSet 的 owner。至此,我们通过观察三个 Object 中的 ownerReference 的信息,可以建立起如下的「从属关系」:

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

    Q: What is the working mechanism of Garbage Collector?(垃圾收集器的工作机制是什么?)

      一个 Garbage Collector 通常由三部分实现:

    • Scanner: 它负责收集目前系统中已存在的 Resource,并且周期性的将这些资源对象放入一个队列中,等待处理(检测是否要对某一个Resource Object 进行 GC 操作)
    • Garbage Processor: Garbage Processor 由两部分组成
      • Dirty Queue: Scanner 会将周期性扫描到的 Resource Object 放入这个队列中等待处理
      • Worker:worker 负责从这个队列中取出元素进行处理
        • 检查 Object 的 metaData 部分,查看ownerReference 字段是否为空
          • 如果为空,则本次处理结束
          • 如果不为空,检测ownerReference 字段内标识的 Owner Resource Object是否存在
            • 存在:则本次处理结束
            • 不存在:删除这个 Object

      其实,在有了 Scanner 和 Garbage Processor 之后,Garbage Collector 就已经能够实现「垃圾回收」的功能了。Scanner组件负责收集目前系统中已存在的 Resource,并且周期性的将这些资源对象放入Dirty Queue等待处理,worker 负责从这个队列中取出元素并进行处理。但是有一个明显的问题:Scanner 的扫描频率设置多少好呢?太长了,k8s 内部就会积累过多的「废弃资源」;太短了,尤其是在集群内部资源对象较多的时候,频繁的拉取信息对 API-Server 也是一个不小的压力。

      k8s 作为一个分布式的服务编排系统,其内部执行任何一项逻辑或者行为,都依赖一种机制:「事件驱动」。说的简单点,k8s 中一些看起来「自动」的行为,其实都是由一些神秘的「力量」在驱动着。而这个「力量」就是我们所说的「Event」。任意一个 Resource Object 发生变动的时候(新建,更新,删除),都会触发一个 k8s 的事件(Event),这个事件在 k8s 的内部是公开的,也就是说,我们可以在任意一个地方监听这些事件。

      总的来说,无论是「事件的监听机制」还是「周期性访问 API-Server 批量获取 Resource Object 信息」,其目的都是为了能够掌握 Resource Object 的最新信息。两者是各有优势的:

    1. 批量拉取:一次性拉取所有的 Resource Object,全面
    2. 监听 Resource 的 Event:实时性强, 且对 API—SERVER 不会造成太大的压力

      综上所述,在实现 Garbage Collector 的过程中,k8s 向其添加了一个「增强型」的组件:Propagator

    • Propagator: Propagator 由三个部分构成
      • EventQueue:负责存储 k8s 中资源对象的事件(Eg:ADD,UPDATE,DELETE)
      • DAG(有向无环图):负责存储 k8s 中所有资源对象的「owner-dependent」 关系
      • Worker:从 EventQueue 中,取出资源对象的事件,根据事件的类型会采取以下两种操作
        • ADD/UPDATE: 将该事件对应的资源对象加入 DAG,且如果该对象有 owner 且 owner 不在 DAG 中,将它同时加入 Garbage Processor 的 Dirty Queue 中
        • DELETE:将该事件对应的资源对象从 DAG 中删除,并且将其「管辖」的对象(只向下寻找一级,如删除 Deployment,那么只操作 ReplicaSet )加入 Garbage Processor 的 Dirty Queue 中

      在有了 Propagator 的加入之后,我们完全可以仅在 GC 开始运行的时候,让 Scanner 扫描一下系统中所有的 Object,然后将这些信息传递给 Propagator 和 Dirty Queue。只要 DAG 一建立起来之后,那么 Scanner 其实就没有再工作的必要了。「事件驱动」的机制提供了一种增量的方式让 GC 来监控 k8s 集群内部的资源对象变化情况

    Q: How can I delete the owner and reserve dependents ? (删除 owner,留下 dependents)

      没错,需求就是这么奇怪,k8s 还兼容一种情况:删除 owner,留下 dependents。剩余的 dependents 被称为是「orphan」

      你想怎么实现?

      如果暂时先不看设计文档中关于这部分的内容,根据之前对 k8s GC 的了解,让你来实现这个功能,你会怎么做呢?这里给出一下笔者的想法:

      首先,我们先来根据上面对于 GC 的了解,给出一幅大致架构图:

      在上图中,我用三种颜色分别标记了三条较为重要的处理过程:

    • 红色:worker 从 dirtyQueue 中取出资源对象,检查其是否带有 owner ,如果没带,则不处理。否则检测其 owner是否存在,存在,则处理下一个资源对象,不存在,删除这个 object。
    • 绿色: scanner 从 api-server 中扫描存在于 k8s 集群中的资源对象并加入至 dirtyQueue
    • 粉色:propagator.worker 从 eventQueue 中取出相应的事件并且获得对应的资源对象,根据事件的类型以及相应资源对象所属 owner 对象的情况来进行判定,是否要进行两个操作:
      • 从 DAG 中删除相应节点(多为响应 DELETE 事件的逻辑)
      • 将有级联关系但是 owner 不存在的对象送入 diryQueue 中

      其中红色是「数据处理」过程,而绿色和粉色是「数据收集」的过程。在「数据处理」的过程中(即我们上面分析过的 GC 的 Worker 的工作过程),worker 做的较为重要的工作有两步:

    • 检查资源对象信息的「ownerReference」字段,判断其是否处在一个级联关系中
    • 若资源对象有所属 owner 且不存在,则删除这个对象

      此时,回头看下我们的需求:「owner 删除,dependents 留下」。如果想在「数据处理」这条链路上做些修改达到我们目的的话,唯一可行的办法就是:在删除了 dependents 对应的 owner 对象之后,同时删除 dependents 信息中 「ownerReference」字段和对应的值。这样一来,在检测资源对象是否应该被删除的过程就会因为其没有「ownerReference」字段而放过它,最终实现了 dependents 对象的“孤立”。

      k8s 是怎么实现的?

      k8s 在系统内部实现了一种类似「删除拦截器链」的机制:即在删除某个资源对象的「删除链路」上,执行一个或多个「拦截逻辑」。并且这种「拦截逻辑」可以自主实现,然后像插件一样注入到这个删除链路上。这种机制在 k8s 当中统称为: Finalizers 。

       Finalizers 的声明非常简单,就是一个 []string 。这个 Slice 的内部填充的是要执行拦截器的名称。它存在于任何一个资源对象的 Meta 信息中: apimachinery/types.go at master · kubernetes/apimachinery · GitHub

       Finalizers 中的拦截器在其宿主资源对象触发删除操作之后顺序执行(资源对象的deletionTimestamp不为 nil),每执行完一个,就会从 Finalizers 中移除一个,直到 Finalizers 为空的 Slice,其宿主资源对象才可以被真正的删除。

      对于「删除 owner 但是不删除 dependents」 的需求,k8s 则是实现了一个:orphan finalizer。一般情况下,正常利用 GC 级连删除一个资源对象是不会涉及到 orphan finalizer 的。它执行的是我们之前提到的 GC 的工作逻辑。如果你想启用这个特性,就需要在删除资源对象的时候,根据 K8s 版本的不同,将名为 DeleteOption.OrphanDependents 的参数赋值为 True(1.7版本以前)

      或者将 DeleteOption.PropagationPolicy 参数赋值为 metav1.DeletePropagationOrphan :apimachinery/types.go at 9dc1de72c0f3996657ffc88895f89f3844d8cf01 · kubernetes/apimachinery · GitHub

      通过这个参数的注释也可以看出:如果设置好之后,将会在它的 Finalizers 中加入 orphan finalizer。而加入 orphan finalizer 这部分的逻辑是在 api-server 的 package 中:apiserver/store.go at master · kubernetes/apiserver · GitHub

      加入了 orphan finalizer 之后,在 GC 的 worker 从 dirtyQueue 中取出 owner 资源对象进行处理的时候,就会执行它的逻辑:删除 dependents 的 OwnerReference 部分:  kubernetes/garbagecollector.go at 0972ce1accf859b73abb5a68c0adf4174245d4bf · kubernetes/kubernetes · GitHub。最终,在「保留 dependents」 的逻辑完成之后,orphan finalizer 也会从相应资源对象的 Finalizers 中删除。

      一个隐含的 Race 问题

      对于 Controller 来说,它会周期性的通过 Selector 来寻找它所创建的资源。

      如果在筛选到了符合自己 label 的 资源,但是发现它的 Meta.OwnerReference 字段中没有自己相关的信息的时候,就会执行一个Adoption 的操作,也就是将和自己有关的 OwnerReference 信息注入到这个 Pod 的 Meta 部分。这种逻辑虽然看起来是比较「保险」,但是实际上它和 orphan finalizer 的逻辑是有冲突的。前者是对 dependents 增加 OwnerReference 信息, 后者则是删除它。两个逻辑在执行的时候,如果不保证「互斥」的话,很可能就会出现一个很严重的竞争问题:指定了 orphan finalizer 的 对象,其 dependents 最终也会被删除。

      借鉴操作系统对于「竞争」问题的处理方式,对 OwnerReference操作的的逻辑(即临界区),应该被「互斥」机制保护起来。而在 k8s 中,实现这种互斥保护机制的方式也很简单:Controller 在想执行 Adoption 操作之前,会检查一下当前资源对象的meta.DeletionTimestamp。如果这个字段的值为非 nil,那么就证明这个资源对象已经在被删除中了。所以就不会再继续执行 Adoption 操作。

      但是仔细想一下,这种「互斥」保护机制的实现方式,看起来是借助了一个「锁变量」(meta.DeletionTimestamp)的帮助。不过,我们并不需要担心这个字段的「竞争」问题,因为能修改它的操作,只有「删除」操作,而删除操作是肯定会发生在 orphan finalizer 执行之前的。也就是说,当 orphan finalizer 执行的时候,这个值早就被设置进去了。 kubernetes/replica_set.go at 7f23a743e8c23ac6489340bbb34fa6f1d392db9d · kubernetes/kubernetes · GitHub

    Q: How Kubernetes defines delete operation of resource object?

      K8s 在对资源对象「删除」操作的定义上,思考了一个较为重要的问题:「删除」操作真正完成的标志是什么?(达到什么样的条件才可以通知用户「删除」操作成功)。这个问题出现的源头是在用户侧,当用户在使用 k8s 提供的资源对象的「删除」操作时,有个问题会影响到他们:

    1. 「删除」操作成功多久后才可以在同一个 ns 下创建同名资源对象?

      如果你了解过构建一个 k8s 集群所需要的服务组件,就可以很清楚的知道:k8s 中的资源对象的信息都是存于一个key-value 的数据库当中的(etcd),且是以名字来做索引的。

          通过命令行 kubectl get xxx 查询的资源对象的信息都来自于那。而且,当 kubelet 组件删除掉其所在节点上的一些资源的时候,会调用 API-Server 提供的接口删除掉key-value 数据库中相应的记录。所以,在 k8s 中,给「删除」操作下了这样一个定义:

    在没有 orphanFinalizer 参与的前提下,直到被删除对象及其「管辖」对象的信息在 key-value 数据库中都被清除,才认为该对象真正的被 GC 回收。即达到了返回给用户「删除成功」的标准。

      本质上来说,上述所表示的删除操作是「同步」的。因为有「级联关系」(owner-dependent) 关系的存在,删除一个资源对象往往影响的不是他自己,还有他的 dependents。只有将因它出现的所有资源都删除,才可以认为这个对象被删除了。

      若想指定这种同步的删除模式,需要在两个不同的位置设置两个参数:

    1. dependents 对象 meta 信息中 OwnerReference.BlockOwnerDeletion
    2. 在发送删除对象请求时,设置 DeleteOptions.PropagationPolicy

       OwnerReference.BlockOwnerDeletion 参数大多数情况下在相应的 dependents 对象创建的时候就设置进去了。

      如果想在 dependents 对象创建之后更新这个参数的值,可能需要使用 admission controller  (1.7及以上版本)提供的一些权限相关的功能。

       DeleteOptions.PropagationPolicy 一共有3个候选值:

     1 // DeletionPropagation decides if a deletion will propagate to the dependents of
     2 // the object, and how the garbage collector will handle the propagation.
     3 type DeletionPropagation string
     4 
     5 const (
     6     // Orphans the dependents.
     7     DeletePropagationOrphan DeletionPropagation = "Orphan"
     8     // Deletes the object from the key-value store, the garbage collector will
     9     // delete the dependents in the background.
    10     DeletePropagationBackground DeletionPropagation = "Background"
    11     // The object exists in the key-value store until the garbage collector
    12     // deletes all the dependents whose ownerReference.blockOwnerDeletion=true
    13     // from the key-value store.  API sever will put the "foregroundDeletion"
    14     // finalizer on the object, and sets its deletionTimestamp.  This policy is
    15     // cascading, i.e., the dependents will be deleted with Foreground.
    16     DeletePropagationForeground DeletionPropagation = "Foreground"
    17 )

      再结合 OwnerReference.BlockOwnerDeletion 参数的注释

    1 // If true, AND if the owner has the "foregroundDeletion" finalizer, then
    2     // the owner cannot be deleted from the key-value store until this
    3     // reference is removed.
    4     // Defaults to false.
    5     // To set this field, a user needs "delete" permission of the owner,
    6     // otherwise 422 (Unprocessable Entity) will be returned.
    7     // +optional
    8     BlockOwnerDeletion *bool `json:"blockOwnerDeletion,omitempty" protobuf:"varint,7,opt,name=blockOwnerDeletion"`

      我们可以了解到。同步删除的开启方式如下:

    1. DeleteOptions.PropagationPolicy = DeletePropagationForeground
    2. OwnerReference. BlockOwnerDeletion = True

      开启之后,在删除身份为 owner 的资源对象的时候,就会先将 denpendents 对象中 OwnerReference.BlockOwnerDeletion 为 true 的资源对象先删除,然后再删除 owner 身份的对象。这里的「删除」就指的是我们前面说过的「真正的删除」:从 k8s 存储资源对象信息的 key-value 数据库中删除所有与其相关的信息。需要注意的是, OwnerReference.BlockOwnerDeletion 为 false 的dependent 对象不会阻碍 owner 对象的删除操作。

      Foreground 是 k8s 提供的两种级联删除方式其中之一,另外一种为 Background。通过上面相关的注释可以看到 Foreground 级联删除也是通过 Finalizer 来实现的,查看 Finalizer 相关的定义可知,标准的 Finalizer,一个是 orphan 的,另一个就是Foreground的:

    1 // These are internal finalizer values for Kubernetes-like APIs, must be qualified name unless defined here
    2 const (
    3     FinalizerOrphanDependents string = "orphan"
    4     FinalizerDeleteDependents string = "foregroundDeletion"
    5 )

      API-Server 的 Delete 函数,在接受到删除请求的时候,会检查 DeleteOptions.PropagationPolicy 参数,若其值为 DeletePropagationForeground , API-Server 随即会对该资源对象进行 Update 操作:

    1. 插入 FinalizerDeleteDependents  Finalizer
    2. 设置 ObjectMeta.DeletionTimestamp  为当前值

      然后,在 GC 处理 owner 对象的 Update 事件的逻辑中,还会给 owner 对象打上一个「正在删除 dependents」 对象的标签。之后,我们会将 owner 对象管辖的 dependent 对象和他自己都加入到 dirtyQueue。dirtyQueue 的 worker 在处理 owner 对象的时候,会检查 owner 对象 「正在删除 dependents」的标签是否存在,如果仍有 dependent 对象没有被删掉,owner 会被轮询处理。而 dependent 对象将会被正常删除。当 dependent 对象相应的删除事件被 Propagator 感知到后,会将其从 DAG 和其 owner 的 dependents 信息中删除。几个循环之后,dependents 机会被删光,而 owner 对象中的 finalizer 和自身也会随之被删掉。

      Background 模式的级联删除不会因 dependent 对象而影响 owner 对象的删除操作。当我们发送给 API-Server 删除一个 owner 身份的对象的请求之后,这个资源对象会立即被删除。它「管辖」的 dependent 对象会以「静默」的方式删除。

    Q: What problems GC handles in k8s?

      通过对 k8s GC 设计文档的阅读,可以大致的概括一下:GC 主要是按照用户的需求来清理系统中「异常」的资源,用户可以自定义「清理方式」和「清理策略」。不难发现,在 GC 中,到底是保留一个资源还是删除一个资源都参照了资源之间的「从属关系」。资源的「从属关系」可以大致分为几个形态:

    1. 无从属关系:这部分资源基本不会被 GC 做处理
    2. 有从属关系
      1. 不符合用户预期:删除异常资源
      2. 符合用户预期:解绑异常资源之间的级联关系

      在有从属关系的资源之间,即使被探测到关系异常,也并不代表一定要将他们都清除。如果有 Orphan Finalizer 的存在,可能某种「异常」正是用户想要的。所以,这就回到了我们一开始所说到的「清理策略」问题。GC 有一定的默认的清理策略,但是用户可以通过加入 Finalizer 的形式来修改「清理策略」,从而保持一个「符合用户期望」的资源之间的从属关系。

      同时,用户可以还可以通过参数来制定特定的「清理方式」,如 Foreground 或者 Background。总体上来说,GC 的行为会受到如下几个因素的影响:

    • 默认:
      • 依据:资源之间默认的从属关系
      • 行为:删除级联关系异常的资源
      • 方式:Foreground 或者 Background
    • 可定制
      • 依据:用户定义的从属关系(通过 Finalizer)
      • 行为:删除级联关系异常的资源
      • 方式:Foreground 或者 Background

      目前看来,GC 主要是解决了「资源清理」 的问题。那么再抽象一点来看的话,GC 解决的是「资源管理」这个大问题中的一个关于「清理」的小问题。既然说到「资源管理」,那么肯定就不止「清理」一个问题需要处理:

      其中,对于资源的创建部分,除了正常的新建操作之外,controller 还有定期执行一个「Adoption」 的操作,用来维护其创建的资源之间那些「本应该建立但是却断开的从属关系」。而对于更新操作来说,controller_manager 需要处理用户对于资源的扩缩容请求,如将 deployment.replicaset.replicacount 减少或者增大,相应资源对应的 controller 需要对可见资源的数量进行调整。至于「资源超卖」的问题,一定会涉及到 scheduler。因为物理资源是固定的,「超卖」本质上来说就是按照实时的需求,动态的调整服务所在的 Node,以便恰好满足服务对于资源的需求。

      如果不把资源管理问题讨论的范围局限在 k8s 中的话,那么「审计」和「复用」同样也是「资源管理」问题中不得不考虑的两个点。前者可以增加整个系统资源的「可控性」,后者则可以最大限度的提升资源的利用率,从而降低成本。其实「复用」和「超卖」的目的是一样的,都是想最大限度的利用物理资源。不过这两个功能笔者暂时还没有去查看它们是否在 k8s 已经实现。

      总结

      之所以去了解 k8s 的 GC,是因为在将 k8s 集群从1.7版本升级至1.9版本的过程中,因为我错误的设置了资源之间的从属关系,导致该资源被 GC 给回收掉了。问题在1.7版本没有出现的原因是那时 k8s 还没有支持对自定义资源(CRD)的级联删除。通过对 GC 设计理念的了解,我们可以初步的感受到 k8s 对于「资源管理」这个问题域中「资源清理」这个小问题的解决思路。以此为起点,我们可以顺藤摸瓜,去观察 k8s 对于「资源管理」问题域中的其他难题是如何处理的。后续,我也将会根据设计文档中的思路,在代码级别上去了解 GC 的实现细节,从而贡献出更加详细的 blog。

    英文单词翻译:

      Garbage Collector  垃圾回收    Cascading deletion 级联删除   Garbage Processor 垃圾处理器   Propagator 传播者   orphan  孤儿

    转自: https://zhuanlan.zhihu.com/p/50101300

  • 相关阅读:
    ZooKeeper概述(转)
    ZooKeeper典型应用场景(转)
    部署与管理ZooKeeper(转)
    Hbase分布式安装部署过程
    HBase安装
    使用info命令查看Redis信息和状态
    java定时调度器解决方案分类及特性介绍
    谈谈应用层切面设计
    七层协议和四层协议
    HTTP协议详解
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/15499228.html
Copyright © 2020-2023  润新知