您好,欢迎来到网暖!

当前位置:网暖 » 站长资讯 » 建站基础 » 网络技术 » 文章详细 订阅RssFeed

# IT明星不是梦 # 图解kubernetes资源QOS机制实现原理

来源:网络整理 浏览:228次 时间:2020-08-11

QOS是k8s中一种资源保护机制,其主要是针对不可压缩资源比如的内存的一种控制技术,比如在内存中其通过为不同的Pod和容器构造OOM评分,并且通过内核的策略的辅助,从而实现当节点内存资源不足的时候,内核可以按照策略的优先级,优先kill掉哪些优先级比较低(分值越高优先级越低)的Pod,今天来分析下背后的实现

1.关键基础特性

image.png

1.1 一切皆文件

在Linux中一切皆文件,控制CGroup本身也是通过配置文件进行的,这是我创建的一个内存Lmits为200M的Pod的容器的配置

# pwd/sys/fs/cgroup# cat ./memory/kubepods/pod8e172a5c-57f5-493d-a93d-b0b64bca26df/f2fe67dc90cbfd57d873cd8a81a972213822f3f146ec4458adbe54d868cf410c/memory.limit_in_bytes209715200
1.2 内核内存配置

这里我们重点关注内存相关的两个配置:VMOvercommitMemory其值为1,表示运行分配所有的物理内存资源,注意不包括SWAP资源VMPanicOnOOM其值为0:表示当内存不足的时候触发oom_killer进行选择部分进程进行kill,QOS也是通过影响其kill流程来实现的

func setupKernelTunables(option KernelTunableBehavior) error {    desiredState := map[string]int{        utilsysctl.VMOvercommitMemory: utilsysctl.VMOvercommitMemoryAlways,        utilsysctl.VMPanicOnOOM:       utilsysctl.VMPanicOnOOMInvokeOOMKiller,        utilsysctl.KernelPanic:        utilsysctl.KernelPanicRebootTimeout,        utilsysctl.KernelPanicOnOops:  utilsysctl.KernelPanicOnOopsAlways,        utilsysctl.RootMaxKeys:        utilsysctl.RootMaxKeysSetting,        utilsysctl.RootMaxBytes:       utilsysctl.RootMaxBytesSetting,    }
2.QOS打分机制与判定实现

QOS打分机制主要是根据Requests和limits里面的资源限制来进行类型判定与打分的,我们就来快速看下这部分的实现

2.1 根据容器判定QOS类型2.1.1 构建容器列表

遍历所有的容器列表,注意这里会包含所有的初始化容器和业务容器

    requests := v1.ResourceList{}    limits := v1.ResourceList{}    zeroQuantity := resource.MustParse("0")    isGuaranteed := true    allContainers := []v1.Container{}    allContainers = append(allContainers, pod.Spec.Containers...)// 追加所有的初始化容器     allContainers = append(allContainers, pod.Spec.InitContainers...)
2.1.2 处理Requests和limits

这里遍历所有的Requests和Limits限制的资源,分别加入到不同的资源集合汇总,其中判定是不是Guaranteed主要是根据limits里面的资源是否包含CPU和内存两种资源,都包含才可能是Guaranteed

    for _, container := range allContainers {        // process requests        for name, quantity := range container.Resources.Requests {            if !isSupportedQoSComputeResource(name) {                continue            }            if quantity.Cmp(zeroQuantity) == 1 {                delta := quantity.DeepCopy()                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 !isSupportedQoSComputeResource(name) {                continue            }            if quantity.Cmp(zeroQuantity) == 1 {                qosLimitsFound.Insert(string(name))                delta := quantity.DeepCopy()                if _, exists := limits[name]; !exists {                    limits[name] = delta                } else {                    delta.Add(limits[name])                    limits[name] = delta                }            }        }        if !qosLimitsFound.HasAll(string(v1.ResourceMemory), string(v1.ResourceCPU)) {            // 必须是全部包含cpu和内存限制            isGuaranteed = false        }    }
2.1.3 BestEffort

如果Pod里面的容器没有任何requests和limits的限制则就是BestEffort

    if len(requests) == 0 && len(limits) == 0 {        return v1.PodQOSBestEffort    }
2.1.4 Guaranteed

要是Guaranteed必须是资源相等,并且限定的数量相同

    // 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 v1.PodQOSGuaranteed    }
2.1.5 Burstable

如果不是上面两种就是最后一种burstable了

    return v1.PodQOSBurstable
2.2 QOS OOM打分机制2.2.1 OOM打分机制

其中guaranteedOOMScoreAdj是-998其实这跟OOM实现有关系,一台node节点上主要是三部分组成:kubelet主进程、docker进程、业务容器进程,而OOM的打分里面-1000表示该进程不会被oom所kill, 那一个业务进程最少也就只能是-999因为你不能保证自己的业务永远不会出现问题,所以在QOS里面-999其实就是kubelet和docker进程所保留的,剩下的才能作为业务容器分配(分值越高越容易被kill)

    // KubeletOOMScoreAdj is the OOM score adjustment for Kubelet    KubeletOOMScoreAdj int = -999    // DockerOOMScoreAdj is the OOM score adjustment for Docker    DockerOOMScoreAdj int = -999    // KubeProxyOOMScoreAdj is the OOM score adjustment for kube-proxy    KubeProxyOOMScoreAdj  int = -999    guaranteedOOMScoreAdj int = -998    besteffortOOMScoreAdj int = 1000
2.2.2 关键Pod

关键Pod是一种特殊的存在,它可以是Burstable或者BestEffort类型的Pod,但是OOM打分却可以跟Guaranteed一样,这种类型的Pod主要包含三种:静态Pod、镜像Pod和高优先级Pod

    if types.IsCriticalPod(pod) {        return guaranteedOOMScoreAdj    }

判定实现

func IsCriticalPod(pod *v1.Pod) bool {    if IsStaticPod(pod) {        return true    }    if IsMirrorPod(pod) {        return true    }    if pod.Spec.Priority != nil && IsCriticalPodBasedOnPriority(*pod.Spec.Priority) {        return true    }    return false}
2.2.3 Guaranteed与BestEffort

这两种类型都有各自默认的值分别为Guaranteed(-998)和BestEffort(1000)

    switch v1qos.GetPodQOS(pod) {    case v1.PodQOSGuaranteed:        // Guaranteed containers should be the last to get killed.        return guaranteedOOMScoreAdj    case v1.PodQOSBestEffort:        return besteffortOOMScoreAdj    }
2.2.4 Burstable

其中关键的一行就是:oomScoreAdjust := 1000 - (1000memoryRequest)/memoryCapacity,从这个计算里面可以看出,如果我们申请的资源越多,那么 (1000memoryRequest)/memoryCapacity这个里面计算出来的时机值就会越小,即最终结果就越大,其实也就表明如果我们占用的内存越少,则打分就越高,这类容器就相对比较容易被kill

    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)

好了今天就到这里,看之前还很懵逼,看完有种豁然开朗的感觉,还是那句话说的对,源码面前了无秘密,加油

k8s源码阅读电子书地址: https://www.yuque.com/baxiaoshi/tyado3

推荐站点

  • 腾讯腾讯

    腾讯网(www.QQ.com)是中国浏览量最大的中文门户网站,是腾讯公司推出的集新闻信息、互动社区、娱乐产品和基础服务为一体的大型综合门户网站。腾讯网服务于全球华人用户,致力成为最具传播力和互动性,权威、主流、时尚的互联网媒体平台。通过强大的实时新闻和全面深入的信息资讯服务,为中国数以亿计的互联网用户提供富有创意的网上新生活。

    www.qq.com
  • 搜狐搜狐

    搜狐网是全球最大的中文门户网站,为用户提供24小时不间断的最新资讯,及搜索、邮件等网络服务。内容包括全球热点事件、突发新闻、时事评论、热播影视剧、体育赛事、行业动态、生活服务信息,以及论坛、博客、微博、我的搜狐等互动空间。

    www.sohu.com
  • 网易网易

    网易是中国领先的互联网技术公司,为用户提供免费邮箱、游戏、搜索引擎服务,开设新闻、娱乐、体育等30多个内容频道,及博客、视频、论坛等互动交流,网聚人的力量。

    www.163.com
  • 新浪新浪

    新浪网为全球用户24小时提供全面及时的中文资讯,内容覆盖国内外突发新闻事件、体坛赛事、娱乐时尚、产业资讯、实用信息等,设有新闻、体育、娱乐、财经、科技、房产、汽车等30多个内容频道,同时开设博客、视频、论坛等自由互动交流空间。

    www.sina.com.cn
  • 百度一下百度一下

    百度一下,你就知道

    www.baidu.com