女主宣言

Kubernetes的系统资源分为可压缩资源(CPU)和不可压缩资源(memory、storage)。默认情况下,kubelet没有做资源预留限制,这样节点上的所有资源都能被Pod使用。若节点上的pod负载较大,会引发一系列问题。本文介绍了针对该问题Kubernetes提供的kubelet的Node Allocatable特性。

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

背景简介

Kubernetes的系统资源分为可压缩资源(CPU)和不可压缩资源(memory、storage)。可压缩资源(比如CPU)在系统满负荷时会划分时间片分时运行进程,通常情况下系统整体会变慢;不可压缩资源(如Memory)在系统满负荷时,严重时会导致某些进程被系统OOM killer机制杀掉。

默认情况下,kubelet没有做资源预留限制,这样节点上的所有资源都能被Pod使用。若节点上的pod负载较大,这些pod可能会与节点上的系统守护进程和k8s组件争夺资源,严重时甚至会引发系统OOM而杀掉一些进程。若被杀掉的进程是系统进程或K8S组件,可能导致更严重的问题,甚至会导致集群的雪崩。

针对这种问题,kubernetes提供了kubelet的Node Allocatable特性,为系统进程和k8s组件预留资源。

资源预留

1

Node Allocatable

kubelet的启动配置中有一个Node Allocatable特性,来为系统守护进程和k8s组件预留计算资源,使得即使节点满负载运行时,也不至于出现pod去和系统守护进程以及k8s组件争抢资源,导致节点挂掉的情况。目前支持对CPU, memory, ephemeral-storage三种资源进行预留。kubernetes官方建议根据各个节点的负载情况来具体配置相关参数。

节点计算资源的分配如下图所示:

其中各个部分的含义如下:

  • Node Capacity:Node的硬件资源总量;

  • kube-reserved:为k8s系统进程预留的资源(包括kubelet、container runtime等,不包括以pod形式的资源);

  • system-reserved:为linux系统守护进程预留的资源;

  • eviction-threshold:通过--eviction-hard参数为节点预留内存;

  • allocatable:可供节点上Pod使用的容量,kube-scheduler调度Pod时的参考此值。

# 节点可供Pod使用资源总量的计算公式:
allocatable = NodeCapacity - [kube-reserved] - [system-reserved] - [eviction-threshold]

从公式可以看出,默认情况下(不设置kube-reserved、system-reserved、eviction-threshold)节点上提供给Pod使用的资源总量等于节点的总容量。

2

参数含义及配置

Kubelet Node Allocatable的代码比较简单,主要在pkg/kubelet/cm/node_container_manager.go,感兴趣的同学可以看一下。以下是相关配置参数:

  • --enforce-node-allocatable,默认为pods(默认情况下,kubelet会为所有pod的总cgroup做资源限制,限制为公式计算出的allocatable的大小)。要为kube组件和System进程预留资源,则需要设置为pods,kube-reserved,system-reserve,同时还要分别加上--kube-reserved-cgroup和--system-reserved-cgroup以指定分别限制在哪个cgroup里;

  • --cgroups-per-qos,Enabling QoS and Pod level cgroups,默认开启。开启后,kubelet会将管理所有workload Pods的cgroups;

  • --cgroup-driver,默认为cgroupfs,另一可选项为systemd。取决于容器运行时使用的cgroup driver,kubelet与其保持一致;

  • --kube-reserved,用于配置为kube组件(kubelet,kube-proxy,dockerd等)预留的资源量,比如—kube-reserved=cpu=2000m,memory=8Gi,ephemeral-storage=16Gi;

  • --kube-reserved-cgroup,如果设置了--kube-reserved,需设置对应的cgroup,且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为kube-reserved-cgroup=/kubelet.service;

  • --system-reserved,用于配置为System进程预留的资源量,比如—system-reserved=cpu=2000m,memory=4Gi,ephemeral-storage=8Gi;

  • --system-reserved-cgroup,如果设置了--system-reserved,需设置对应的cgroup,且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为system-reserved-cgroup=/system.slice。

  • --eviction-hard,用来配置kubelet的hard eviction条件,只支持memory和ephemeral-storage两种不可压缩资源。当出现MemoryPressure时,Scheduler不会调度新的Best-Effort QoS Pods到此节点。当出现DiskPressure时,Scheduler不会调度任何新Pods到此节点。

 配置与验证

针对pod、system、kube均做cgroup级别限制,需要进行以下配置:

# 在kubelet的启动参数中添加:
--enforce-node-allocatable=pods,kube-reserved,system-reserved \
--cgroup-driver=cgroupfs \
--kube-reserved=cpu=1,memory=1Gi,ephemeral-storage=10Gi \
--kube-reserved-cgroup=/system.slice/kubelet.service \
--system-reserved cpu=1,memory=2Gi,ephemeral-storage=10Gi \
--system-reserved-cgroup=/system.slice \
# 设置cgroup结构可参考官方建议。

为system.slice、kubelet.service创建cpuset子系统:未创建前system.slice这个cgroup是没有cpuset子系统的,而kubelet(1.9)启动时会去查看这些cgroup子系统是否存在,如果不存在会报相应的cgroup错误。

// Exists checks if all subsystem cgroups already exist
func (m *cgroupManagerImpl) Exists(name CgroupName) bool {  // Get map of all cgroup paths on the system for the particular cgroup  cgroupPaths := m.buildCgroupPaths(name)    // the presence of alternative control groups not known to runc confuses    // the kubelet existence checks.    // ideally, we would have a mechanism in runc to support Exists() logic // scoped to the set control groups it understands.  this is being discussed    // in https://github.com/opencontainers/runc/issues/1440    // once resolved, we can remove this code.  whitelistControllers := sets.NewString("cpu", "cpuacct", "cpuset", "memory", "systemd")  // If even one cgroup path doesn't exist, then the cgroup doesn't exist.  for controller, path := range cgroupPaths {    // ignore mounts we don't care about   if !whitelistControllers.Has(controller) {  continue    }   if !libcontainercgroups.PathExists(path) {  return false    }   }   return true
}

# 所以需要手工创建相应cpuset子系统:
sudo mkdir -p /sys/fs/cgroup/cpuset/system.slice
sudo mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service

重启kubelet后,可以验证(以内存为例):

通过公式计算、节点实际capacity及allocatable的值(kubectl describe node xxx)、 kubepods控制组中对内存的限制值(/sys/fs/cgroup/memory/kubepods/memory.limit_in_bytes)均与预期相符。

并且system.slice(/sys/fs/cgroup/memory/system.slice/memory.limit_in_bytes)、kubelet.service(/sys/fs/cgroup/memory/system.slice/kubelet.service/memory.limit_in_bytes)控制组对内存的限制值也与预期相符。

最佳实践

1. 生产环境中,建议同时限制pod、k8s系统组件、linux system进程资源,以免任一类资源负载过高影响其他组件,甚至造成雪崩;

2. 针对daemonset创建出来的系统级别pod,建议为其配置Guaranteed的服务质量等级。

相关文章

  • https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/

  • https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/node-allocatable.md#recommended-cgroups-setup

  • https://mp.weixin.qq.com/s/CY8qmvdUoAGj_Hbtim0hrw

  • https://my.oschina.net/jxcdwangtao/blog/1629059

  • https://www.qikqiak.com/post/kubernetes-qos-usage/

360云计算

由360云平台团队打造的技术分享公众号,内容涉及数据库、大数据、微服务、容器、AIOps、IoT等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享

浅析Kubernetes资源管理相关推荐

  1. [kubernetes] 资源管理 ---- 资源请求和限制

    当Kubernetes调度Pod时,容器是否有足够的资源来实际运行是很重要的. 如果大型应用程序被调度到资源有限的节点上,则节点可能会耗尽内存或CPU资源,并且可能会停止工作! 请求和限制 请求和限制 ...

  2. kubernetes资源管理平台ratel

    ratel是一个kubernetes集群资源管理平台,使用它可以对多种资源进行创建 查看 修改和删除操作,支持配置多个集群的管理. 官网:https://github.com/dotbalo/rate ...

  3. 【3】Kubernetes资源管理

    资源对象 kubernetes系统的 api server基于http/https接收并响应客户端的操作请求,它提供了一种基于资源的RESTful风格的编程结构,将集群的各种组件都抽象成为标准的RES ...

  4. kubernetes资源管理详解

    资源管理介绍 在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes. kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署 ...

  5. 浅析Kubernetes StatefulSet

    StatefulSet和Deployment的区别 "Deployment用于部署无状态服务,StatefulSet用来部署有状态服务". 具体的,什么场景需要使用Stateful ...

  6. [kubernetes] 资源管理 --- 资源预留实践

    一 概述 1.1 问题 系统资源可分为两类:可压缩资源(CPU)和不可压缩资源(memory.storage).可压缩资源比如CPU超配后,在系统满负荷时会划分时间片分时运行进程,系统整体会变慢(一般 ...

  7. 浅析Kubernetes Pod重启策略和健康检查

    使用Kubernetes的主要好处之一是它具有管理和维护集群中容器的能力,几乎可以提供服务零停机时间的保障.在创建一个Pod资源后,Kubernetes会为它选择worker节点,然后将其调度到节点上 ...

  8. 云原生之容器编排实践-Kubernetes资源管理:标签选择器,注解以及命名空间

    背景 前面的几篇文章我们从一个简单的 SpringBoot 服务开始,依次将其打包为镜像,推送至私有镜像仓库,安装 Kubernetes 的极简实践环境 minikube , minikube 传递秘 ...

  9. 浅析 Kubernetes原生NetworkPolicy 网络策略,让更安全的容器运行环境唾手可得

    k8s中的网络策略主要分为原生 NetworkPolicy 和第三方网络插件提供的网络策略.本文将主要分析原生Networkpolicy的网络策略. 什么是网络策略 网络策略(NetworkPolic ...

最新文章

  1. mysql data文件夹恢复_【专注】Zabbix源码安装教程—步骤详解(2)安装并配置mysql...
  2. php实现享元模式,php设计模式 flyweight (享元模式)
  3. java基础知识点_零基础学习Java语言,各个阶段需要掌握的知识点
  4. UVA12412 A Typical Homework (a.k.a Shi Xiong Bang Bang Mang)
  5. geoserver动态颜色参数样式、动态sql配置实现
  6. 数据库中数据数据初始化的好处
  7. 对包含HttpContext.Current.Cache的代码进行单元测试
  8. python闭包有什么作用_闭包在实际开发中有什么用?
  9. 工厂供电技术实训设备QY-PGD19
  10. Foxit Quick PDF Library License Key
  11. JVM篇-JVM内存结构与存储机制
  12. 平面坐标转大地坐标(经纬度)
  13. win8 怎么桌面计算机图标不见了,win8系统桌面图标不见了怎么办?如何恢复
  14. CO-PA: 获利能力分析配置和业务实践
  15. matlab中ones函数的使用方法详细介绍(附matlab代码)
  16. 你好,Googler!
  17. Wi-Fi6移动热点功能配置
  18. 2021年南京大学软件工程专硕考研初试410分(数学满分)总成绩第二上岸经验贴
  19. 模态框中弹模态框的问题
  20. 区块链项目是如何盈利的

热门文章

  1. 英语学习过程中的几点体会(2)
  2. DataBinder.Eval数据绑定中的使用
  3. 实现option上下移动_JS实现Select的option上下移动的方法
  4. React hooks + antd前台实现input搜索框实时搜索table表格
  5. 第 69 章 数据库链接
  6. 论__AlertDialog自定义布局回调修改的正确方式
  7. 四种launchMode启动方式
  8. Linux 时间同步问题_qingshanli1988-ChinaUnix博客
  9. nginx ssl 双向认证
  10. CCNA网络小菜鸟笔记之(第十一章, 广域网协议)