zoukankan      html  css  js  c++  java
  • (转)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

  • 相关阅读:
    MVC模式-----struts2框架(2)
    MVC模式-----struts2框架
    html的<h>标签
    jsp脚本元素
    LeetCode "Paint House"
    LeetCode "Longest Substring with At Most Two Distinct Characters"
    LeetCode "Graph Valid Tree"
    LeetCode "Shortest Word Distance"
    LeetCode "Verify Preorder Sequence in Binary Search Tree"
    LeetCode "Binary Tree Upside Down"
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/15499228.html
Copyright © 2011-2022 走看看