Kubernetes Resource QoS Classes概念是什么

发布时间:2022-01-11 17:57:41 作者:iii
来源:亿速云 阅读:168

本文小编为大家详细介绍“Kubernetes Resource QoS Classes概念是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Kubernetes Resource QoS Classes概念是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

Kubernetes Resource QoS Classes介绍

基本概念

Kubernetes根据Pod中Containers Resource的request和limit的值来定义Pod的QoS Class。其中,指定容器request,代表系统确保能够提供的资源下限值。指定容器limit,代表系统允许提供的资源上限值。

Pods需要保证长期稳定运行需要设定“确保运行的最少资源”,然而pod能够使用的资源经常是不能确保的。

通常,Kubernetes通过设置request和limit的值来指定超卖比例,进而提升资源利用率。K8S的调度基于request,而不是limit。Borg通过使用“non-guranteed”的资源,提升了20%的资源利用率。

在一个资源被“超卖”的系统(总limits > machine capacity),容器在资源被耗尽的情况下会被kill。理想情况是那些“不重要”的容器先被kill。

对于每一种Resource都可以将容器分为3中QoS Classes: Guaranteed, Burstable, and Best-Effort,它们的QoS级别依次递减。K8S底层实际上是通过 limit和request值来实现不同等级QoS的划分。

注意,如果一个容器只指明了limit,而未指明request,则表明request的值等于limit的值。

Examples:
containers:
    name: foo
        resources:
            limits:
                cpu: 10m
                memory: 1Gi
    name: bar
        resources:
            limits:
                cpu: 100m
                memory: 100Mi
containers:
    name: foo
        resources:
            limits:
                cpu: 10m
                memory: 1Gi
            requests:
                cpu: 10m
                memory: 1Gi

    name: bar
        resources:
            limits:
                cpu: 100m
                memory: 100Mi
            requests:
                cpu: 100m
                memory: 100Mi
Examples:
containers:
    name: foo
        resources:
    name: bar
        resources:

Examples: 容器bar没有对Resource进行指定。

containers:
    name: foo
        resources:
            limits:
                cpu: 10m
                memory: 1Gi
            requests:
                cpu: 10m
                memory: 1Gi

    name: bar

容器foo和bar对不同的Resource进行了指定。

containers:
    name: foo
        resources:
            limits:
                memory: 1Gi

    name: bar
        resources:
            limits:
                cpu: 100m

容器foo未指定limit,容器bar未指定request和limit。

containers:
    name: foo
        resources:
            requests:
                cpu: 10m
                memory: 1Gi

    name: bar

可压缩/不可压缩资源的区别

kube-scheduler调度时,是基于Pod的request值进行Node Select完成调度的。Pod和它的所有Container都不允许Consume limit指定的有效值(if have)。

request和limit如何生效,依赖于资源是否是压缩的

可压缩资源的保证
不可压缩资源的保证
管理和调度策略

如何根据不同的QoS回收Resources

Node上的OOM Score 配置

Pod OOM 打分配置

mm/oom_kill.c 中的badness()给每个进程一个OOM score,更高OOM得分的进程更容易被kill。得分取决于:

这里提供一个计算系统上oom_score分数TPO10进程(最容易被oom killer杀掉的进程)脚本:

# vim oomscore.sh
#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
        printf "%2d %5d %s\n" \
                "$(cat $proc/oom_score)" \
                "$(basename $proc)" \
                "$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10

以下是几种K8S QoS 等级的OOM score:

Best-effort
Guaranteed
Burstable
Pod infra containers or Special Pod init process
Kubelet, Docker

已知的issue和潜在优化点

源码分析

QoS的源码位于:pkg/kubelet/qos,代码非常简单,主要就两个文件pkg/kubelet/qos/policy.go,pkg/kubelet/qos/qos.go。 上面讨论的各个QoS Class对应的OOM_SCORE_ADJ定义在:

pkg/kubelet/qos/policy.go:21

const (
        PodInfraOOMAdj        int = -998
        KubeletOOMScoreAdj    int = -999
        DockerOOMScoreAdj     int = -999
        KubeProxyOOMScoreAdj  int = -999
        guaranteedOOMScoreAdj int = -998
        besteffortOOMScoreAdj int = 1000
)

容器的OOM_SCORE_ADJ的计算方法定义在:

pkg/kubelet/qos/policy.go:40

func GetContainerOOMScoreAdjust(pod *v1.Pod, container *v1.Container, memoryCapacity int64) int {
        switch GetPodQOS(pod) {
        case Guaranteed:
                // Guaranteed containers should be the last to get killed.
                return guaranteedOOMScoreAdj
        case BestEffort:
                return besteffortOOMScoreAdj
        }

        // Burstable containers are a middle tier, between Guaranteed and Best-Effort. Ideally,
        // we want to protect Burstable containers that consume less memory than requested.
        // The formula below is a heuristic. A container requesting for 10% of a system's
        // memory will have an OOM score adjust of 900. If a process in container Y
        // uses over 10% of memory, its OOM score will be 1000. The idea is that containers
        // which use more than their request will have an OOM score of 1000 and will be prime
        // targets for OOM kills.
        // Note that this is a heuristic, it won't work if a container has many small processes.
        memoryRequest := container.Resources.Requests.Memory().Value()
        oomScoreAdjust := 1000 - (1000*memoryRequest)/memoryCapacity
        // A guaranteed pod using 100% of memory can have an OOM score of 10. Ensure
        // that burstable pods have a higher OOM score adjustment.
        if int(oomScoreAdjust) < (1000 + guaranteedOOMScoreAdj) {
                return (1000 + guaranteedOOMScoreAdj)
        }
        // Give burstable pods a higher chance of survival over besteffort pods.
        if int(oomScoreAdjust) == besteffortOOMScoreAdj {
                return int(oomScoreAdjust - 1)
        }
        return int(oomScoreAdjust)
}

获取Pod的QoS Class的方法为:

pkg/kubelet/qos/qos.go:50

// GetPodQOS returns the QoS class of a pod.
// A pod is besteffort if none of its containers have specified any requests or limits.
// A pod is guaranteed only when requests and limits are specified for all the containers and they are equal.
// A pod is burstable if limits and requests do not match across all containers.
func GetPodQOS(pod *v1.Pod) QOSClass {
        requests := v1.ResourceList{}
        limits := v1.ResourceList{}
        zeroQuantity := resource.MustParse("0")
        isGuaranteed := true
        for _, container := range pod.Spec.Containers {
                // process requests
                for name, quantity := range container.Resources.Requests {
                        if !supportedQoSComputeResources.Has(string(name)) {
                                continue
                        }
                        if quantity.Cmp(zeroQuantity) == 1 {
                                delta := quantity.Copy()
                                if _, exists := requests[name]; !exists {
                                        requests[name] = *delta
                                } else {
                                        delta.Add(requests[name])
                                        requests[name] = *delta
                                }
                        }
                }
                // process limits
                qosLimitsFound := sets.NewString()
                for name, quantity := range container.Resources.Limits {
                        if !supportedQoSComputeResources.Has(string(name)) {
                                continue
                        }
                        if quantity.Cmp(zeroQuantity) == 1 {
                                qosLimitsFound.Insert(string(name))
                                delta := quantity.Copy()
                                if _, exists := limits[name]; !exists {
                                        limits[name] = *delta
                                } else {
                                        delta.Add(limits[name])
                                        limits[name] = *delta
                                }
                        }
                }

                if len(qosLimitsFound) != len(supportedQoSComputeResources) {
                        isGuaranteed = false
                }
        }
        if len(requests) == 0 && len(limits) == 0 {
                return BestEffort
        }
        // Check is requests match limits for all resources.
        if isGuaranteed {
                for name, req := range requests {
                        if lim, exists := limits[name]; !exists || lim.Cmp(req) != 0 {
                                isGuaranteed = false
                                break
                        }
                }
        }
        if isGuaranteed &&
                len(requests) == len(limits) {
                return Guaranteed
        }
        return Burstable
}

PodQoS会在eviction_manager和scheduler的Predicates阶段被调用,也就说会在k8s处理超配和调度预选阶段中被使用。

读到这里,这篇“Kubernetes Resource QoS Classes概念是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. kubernetes系列教程(六)kubernetes资源管理和服务质量
  2. 如何进行Kubernetes 调度和资源管理

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

kubernetes

上一篇:API Basics怎么实现

下一篇:MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决方法是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》