咖啡香

Kuberentes中基于策略的资源分配

前言:清明放假,抽空把在社区提的Proposal翻译一下。另外,我们产品的新版本(1.1) 节前也 release 了,有兴趣可以下载试用一下;有问题欢迎随时讨论 (我是传送门,戳我,戳我) 。

===================

原文 传送门,译文如下:

用户场景和要求

作为集群管理员,希望建立一个环境来运行不同的工作负载,例如 “长服务”,大数据。 由于这些应用程序由不同的部门管理,我必须为每个应用程序提供资源保证,如下所示:

长服务(app area)和 大数据(bigdata area)可以共享资源:

在大数据区域运行多个群集:

以大数据为例,下面是一些要求细节:

术语:

背景: 随着Kubernetes的成长,目前可以通过以下几个功能实现资源的共享。

Admission 和 ResourceQuota

在kubernetes中,namespace-level quota定义了命名空间可以使用的最大资源。通过ResourQuotaAdmission 实现,如果超过配额,则拒绝Pod创建。如果总配额大于集群的能力,则不会定义如何在namespace之间共享资源:如果一个namespace使用的资源少于其配额而但其它namespacey的资源请求超出了配额,则不能将这些资源借给其他资源(并在必要时抢占回来)。 Admission Controller是一个一般概念:Kubernetes可以根据任意策略拒绝Pod创建。例如,即使应用程序具有足够的配额来运行pod,如果应用程序在群集中使用的资源超过了比例,它也可以拒绝Pod创建。之前有过关于 “Job”(per-controller)进行Admission Control的讨论;这样就可以像批量任务系统那样进行处理。作为一般概念,可以建立定制的Admission Controller以拒绝Pod创建;但为了达到以下要求,引入了arbitrator:

抢占和重新安排

一个Pod可以被杀死然后重启,因为一些其他Pod需要它使用的资源(抢占)。有一个基于优先级的抢占方案(见Borge)的讨论(每个pod都有一个优先级,而具有更高和可能相同优先级的pod可以抢占它;但谁做出决定哪个pod要抢占还不确定:可以是默认的调度程序,rescheduler 和/或 具有调度功能的 customized controller)。抢占总是 graceful 的终止。优先权方案通常意味着一个优先级别基础上的配额分配,以便应用程序可以在最高优先级级别给予一定数量的配额,并且可以给予较低的优先级更大量的配额(甚至是无限的,即集群的整体容量)。并且通过resetuler驱逐pod来重新优化集群级别的策略(目前有一个执行策略的原始调度器: “关键的pod,如Heapster,DNS等不会由于集群中的空闲资源不足也无法运行;但有其他很多政策可以添加并执行)。它通过驱逐一个或多个pod来允许一些待处理的pod(s)进行调度。

抢占需要在namespace之间调度资源;arbitrator 可是定义“优先”的决策者之一。没有满足deserved的namespace的优先级高于overused的namespace。arbitrator将利用eviction功能进行抢占。rescheduler 将会继续为关键Pod抢占资源,也会重新调度Pods来达到更高的资源使用效率。有了arbitrator,kube-system具有无限的deserved资源:deserved的资源总是等于它的请求,其他namespace则共享其余的资源。

Customized Controller和ThirdPartyResource:

ThirdPartyResource是使用新的API对象类型来扩展Kubernetes API的一种方法。新的API类型将被赋予一个API endpoint并支持相应的增、删、改、查操作。您可以使用此API endpoint 创建自定义对象。通过 mesos-style.md 和ThirdPartyResource,开发人员可以使用自定义对象构建workload customized controller。k82cn/kube-arbitrator 有一个例子,它通过ThirdPartyResource功能提供资源共享和抢占功能。

水平/垂直缩放和节点级QoS: 节点级资源使用率的改进,对集群级资源共享并无贡献。

PS: 最近有一个关于”垂直缩放”的讨论/提案,个人感觉可以通过 vpa/hpa 与 arbitrator/scheduler 联动来管理集群资源,从而动态调整集群的资源分配情况来提高资源的使用效率。

解决方案/提案

概述:

为了达到上述要求,引入了一个新的组件(k8s-arbitrator)和两个 ThirdPartyResource(Consumer / Allocation)。

以下yaml文件演示了Consumer的定义:

apiVersion: kuabe-arbitrator.incubator.k8s.io/v1
kind: Consumer
metadata:
  name: defaults
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
  reserved:
    limits.memory: 1Gi

对于每个Consumer对象,它有两个字段: hardreserved

Consumer是由仲裁员为每个命名空间创建的,并且必要时由集群管理员进行更新;仲裁员创建具有无限hard和零reserved的保留的Consumer,因此namespace默认共享集群资源。

arbitrator将创建或更新Allocation中的额外字段: deserved

apiVersion: kuabe-arbitrator.incubator.k8s.io/v1
kind: Allocation
metadata:
  name: defaults
spec:
  deserved:
    cpu: "1.5"
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
  reserved:
    limits.memory: 1Gi

下图显示了Consumer/Allocation中的hardreserveddeserved的关系。

注意:只有”Compute Resource Quota”和”Storage Resource Quota”可用于reserveddeserved

    -------------  <-- hard
    |           |
    |           |
    - - - - - - -  <-- deserved
    |           |
    |           |
    |           |
    -------------  <-- reserved
    |           |
    -------------

k8s-arbitrator 是一个新的组件,它会创建/更新 Consumer 和 Allocation:

同时,k8s默认调度器仍然根据其策略来分派任务到主机,例如 PodAffinity:k8s-arbitrator 负责 resource allocation, k8s-scheduler 负责 resource assignment

Arbitrator 将DRF作为默认策略。它将从 k8s-apiserver 中取得pod/node,并根据DRF算法计算每个namespace的deserved资源;然后更新相应的配置。默认调度间隔为1s,可配置。arbitrator不会将主机名分配给deserved资源中;它依赖默认的调度器(kube-scheduler)在适当的主机上分派任务。

仲裁员还符合以下要求:

抢占

当资源请求/配额发生变化时,每个命名空间的deserved资源也可能会发生变化。 “较高”的优先级Pods将可能触发eviction,下图显示了由于deserved资源变化而引发eviction的情况。

T1:                T2:                              T3:
 --------------    -------------- --------------    -------------- --------------
 | Consumer-1 |    | Consumer-1 | | Consumer-2 |    | Consumer-1 | | Consumer-2 |
 |   cpu:2    | => |   cpu:1    | |   cpu:0    | => |   cpu:1    | |   cpu:1    |
 |   mem:2    |    |   mem:1    | |   mem:0    |    |   mem:1    | |   mem:1    |
 --------------    -------------- --------------    -------------- --------------

Arbitrator使用pod的 “/evict” REST API 来回收资源。但是当arbitrator选择需要被杀死的Pods时,至少有两个要求:

namespace在驱逐后可能会变成underused; arbitrator将尝试从最overused的namespace尝试杀死Pods。 对于资源碎片的问题,暂时不在本文的讨论范围内; 将在抢占实施文档中讨论设计细节。

功能交互

Workload customized controller:

Aribtrator也对workload customized controller 起作用,它会杀死overused的namespace中的Pods。Customized controller不能比Allocation.deserved使用更多的资源,如果Allocation.deserved变小,customized controller 需要选择Pods杀死;否则arbitrator将在grace period后杀死 Pods(例如FCFS)。

Multi-scheduler:

如果使用multi-scheduler,只能启动一个arbitrator以避免竞争条件

Admission Controller:

AribtratorAdmission检查Consumer相对于Quota中”Compute Resource”和”Storage Resource”的定义:Consumer.hard不能超过Quota.hard。 ResourceQuotaAdmission的其他指标将遵循当前行为。对其他Admission插件没有影响。

节点级QoS

在原型中,仅考虑requestlimit会在后面的版本考虑

ReplicaController/ReplicaSet

由于Consumer/Allocation是namespace级别而不是Job/RC级别,k8s-controller-manager不能根据RC的比例创建pod;它需要最终用户在RC之间平衡Pods或在Consumer中请求预留资源。

kubelet:

现在还不涉及kubelet,虽然命名空间的Allocation.deserved也是kubelet中evict的一个因素,例如:

目前进展:

路线图和未来:

引用:


comments powered by Disqus