k8s集群性能优化之kubelet配置资源预留

疑问分析

在k8s集群中,默认情况下 Pod 能够使用节点全部可用容量,同样就会伴随一个新的问题,pod消耗的内存会挤占掉系统服务本身的资源,这就好比我们在宿主机上运行java服务一样,会出现java程序将宿主机上的资源(内存、cpu)耗尽,从而导致系统登陆不上或者卡顿现象。同理在k8s集群中也会出现类似的问题,从而也会导致一系列不可控的故障产生。因此为系统守护进程预留出部分资源,也是很有必要的。

解决思路

要解决这个问题就需要为 k8s 集群配置资源预留,kubelet 暴露了一个名为 Node Allocatable 的特性,有助于为系统守护进程预留计算资源,k8s 也是推荐集群管理员按照每个节点上的工作负载来配置 Node Allocatable。

环境说明

本文的操作环境为 Kubernetes v1.18.0 版本,使用docker的容器运行时,docker 和 Kubelet 采用的 cgroup 驱动为 systemd。
在这里插入图片描述

Kubelet Node Allocatable 介绍

Kubelet Node Allocatable用来为Kube组件和System进程预留资源,从而保证当节点出现满负荷时也能保证Kube和System进程有足够的资源。目前支持cpu, memory, ephemeral-storage三种资源预留。

计算方式

Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold

其中:

  • Node Capacity:Node的所有硬件资源,kube-reserved是给kube组件预留的资源
  • Kube-reserved:kube 组件预留的资源
  • system-reserved:给system进程预留的资源
  • eviction-threshold(阈值):kubelet eviction(收回)的阈值设定

只有allocatable才是真正scheduler调度Pod时的参考值(保证Node上所有Pods的request resource不超过Allocatable) ,关系图如下:
在这里插入图片描述

配置方式(基于yum安装)

我们先通过 kubectl describe node 命令查看节点可分配资源的数据:
kubectl describe nodes k8s-m1

...
Capacity:
  cpu:                8
  ephemeral-storage:  206292644Ki
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             15731900Ki
  pods:               110
Allocatable:
  cpu:                8
  ephemeral-storage:  190119300396
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             15629500Ki
  pods:               110
...

可以看到其中有 Capacity 与 Allocatable 两项内容,其中的 Allocatable 就是节点可被分配的资源,我们这里没有配置资源预留,所以默认情况下 Capacity 与 Allocatable 的值基本上是一致的。

配置资源预留

比如我们现在需要为系统预留一定的资源,我们可以使用如下的几个 kubelet 参数来进行配置:

--enforce-node-allocatable=pods
--kube-reserved=memory=...
--system-reserved=memory=...
--eviction-hard=...

这里我们暂时不设置对应的 cgroup,比如我们这里先只对 master1 节点添加资源预留,我们可以直接修改 /var/lib/kubelet/config.yaml 文件来动态配置 kubelet,添加如下所示的资源预留配置:

apiVersion: kubelet.config.k8s.io/v1beta1
......
enforceNodeAllocatable:
 1. pods
kubeReserved:  # 配置 kube 资源预留
  cpu: 500m
  memory: 1Gi
  ephemeral-storage: 1Gi
systemReserved:  # 配置系统资源预留
  memory: 1Gi
evictionHard:  # 配置硬驱逐阈值
  memory.available: "300Mi"
  nodefs.available: "10%"

在这里插入图片描述
修改完成后,重启 kubelet,启动完成后重新对比 Capacity 及 Allocatable 的值:
kubectl describe nodes k8s-m1

...
Capacity:
  cpu:                8
  ephemeral-storage:  206292644Ki
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             15731900Ki
  pods:               110
Allocatable:
  cpu:                7500m
  ephemeral-storage:  189045558572
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             13327548Ki
  pods:               110
...

仔细对比可以发现其中的 Allocatable的值恰好是 Capacity 减去上面我们配置的预留资源的值:

allocatale = capacity - kube_reserved - system_reserved - eviction_hard
内存: 13327548Ki = 15731900Ki - 1*1024*1024Ki - 1*1024*1024Ki - 300*1024Ki
CPU: 7500m = 8000m - 500m (单位为m是以CPU的时间分片计量的,1C为1000m)

再通过查看 kubepods.slice(systemd 驱动是以 .slice 结尾)cgroup 中对节点上所有 Pod 内存的限制,该值决定了 Node 上所有的 Pod 能使用的资源上限:

cat /sys/fs/cgroup/memory/kubepods.slice/memory.limit_in_bytes
13961981952      #单位是byte

得到的 Pod 资源使用上限为:

13961981952 Bytes = 13634748 Ki = Allocatable(13327548 Ki) + eviction_hard(300*1024Ki)   # 13961981952 / 1024 = 13634748

也可以通过计算验证我们的配置是正确的:

kubepods.slice/memory.limit_in_bytes = capacity - kube_reserved - system_reserved

Eviction 与 OOM

  1. eviction 是指 kubelet 对该节点上的 Pod 进行驱逐,OOM 是指 cgroup 对进程进行 kill。
  2. kubelet 对 Pod 进行驱逐时,是根据 --eviction-hard 参数,比如该参数如果设置了 memory.available<20%,那么当主机的内存使用率达到80%时,kubelet 便会对Pod进行驱逐。但是,–eviction-hard=memory.available<20% 不会对/sys/fs/cgroup/memory/kubepods.slice/memory.limit_in_bytes 的值产生影响,因为kubepods.slice/memory.limit_in_bytes = capacity - kube-reserved - system-reserved,换句话说,Pod 的内存使用量总和是可以超过80%的,且不会被 OOM-kill,只会被 eviction。
  3. kubernetes 对 Pod 的驱逐机制如下(其实就是 QoS 章节的定义):
    首先驱逐没有设置资源限制的 Pod
    然后驱逐资源上限和资源下限不一样的 Pod
    最后驱逐资源上限等资源下限的Pod

可分配约束

前面我们在配置资源预留的时候,其中有一个 enforceNodeAllocatable 配置项(–enforce-node-allocatable),该配置项的帮助信息为:

--enforce-node-allocatable strings    
                
A comma separated list of levels of node allocatable enforcement to be enforced by kubelet. Acceptable options are
 'none', 'pods', 'system-reserved', and 'kube-reserved'. If the latter two options are specified, '--system-reserved-
 cgroup' and '--kube-reserved-cgroup' must also be set, respectively. If 'none' is specified, no additional options 
 should be set. See https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/ for more details. 
 (default [pods]) (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config 
 flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)

kubelet 默认对 Pod 执行 Allocatable 可分配约束,如果所有 Pod 的总用量超过了 Allocatable,那么驱逐 Pod 的措施将被执行,我们可通过设置 kubelet --enforce-node-allocatable 标志值为 pods 控制这个措施。

此外我们还可以通过该标志来同时指定 kube-reserved 和 system-reserved 值,可以让 kubelet 强制实施 kube-reserved 和 system-reserved 约束,不过需要注意,如果配置了 kube-reserved 或者 system-reserved 约束,那么需要对应设置 --kube-reserved-cgroup 或者 --system-reserved-cgroup 参数。

如果设置了对应的 --system-reserved-cgroup 和 --kube-reserved-cgroup 参数,Pod 能实际使用的资源上限是不会改变,但系统进程与 kube 进程也会受到资源上限的限制,如果系统进程超过了预留资源,那么系统进程会被 cgroup 杀掉。但是如果不设这两个参数,那么系统进程就可以使用超过预留的资源上限。

所以如果要为系统预留和 kube 预留配置 cgroup,则需要非常小心,如果执行了 kube-reserved 约束,那么 kubelet 就不能出现突发负载用光所有可用资源,不然就会被杀掉。system-reserved 可以用于为诸如 sshd、udev 等系统守护进程争取资源预留,但是如果执行 system-reserved 约束,那么可能因为某些原因导致节点上的关键系统服务 CPU 资源短缺或因为内存不足而被终止,所以如果不是自己非常清楚如何配置,最好别配置 cgroup 约束,如果需要自行配置,可以参考第一期的资源预留文档进行相关操作。

因此,我们强烈建议用户使用 enforce-node-allocatable 默认配置的 pods 即可,并为系统和 kube 进程预留出适当的资源,以保持整体节点的可靠性,不需要进行 cgroup 约束,除非操作人员对系统非常了解。

<think>嗯,用户想了解Kubernetes集群节点的资源配置最佳实践和要求。首先,我需要回忆一下K8s的官方文档和相关实践经验。记得K8s对节点的资源有一定的建议,但具体数值可能因版本而异。比如,控制平面节点和工作节点的需求不同,控制平面需要更高的CPU和内存来处理调度和API请求。 接下来,用户提到的CPU、内存、存储,每个部分都需要详细说明。CPU方面,控制节点至少需要2核,生产环境可能需要4核以上,而工作节点根据负载调整。内存的话,控制节点至少2GB,生产可能4GB以上,工作节点同样需要根据应用需求来定。存储方面,系统盘、容器运行时、持久化卷这些分区要考虑,还有IOPS的要求。 然后,最佳实践部分,比如资源预留、监控、水平扩展、存储选择、标签管理、污点容忍这些点都要覆盖。用户可能想知道如何优化节点配置,避免资源不足或浪费。另外,引用中的资料提到通过Java查询资源使用情况,说明用户可能对监控工具也有兴趣,可以提到Prometheus或者kubectl top这样的工具。 还要注意用户的真实需求,他们可能在部署集群时遇到资源配置的问题,或者想优化现有集群。需要强调一致性、监控的重要性,以及根据应用负载动态调整的策略。可能还需要解释节点资源不足会导致Pod被驱逐,影响服务稳定性,所以预留资源很关键。 最后,相关问题部分要引导用户深入思考,比如如何监控资源、处理资源不足、优化存储性能,以及自动扩缩容的机制。确保回答结构清晰,分点明确,引用相关的参考资料来增强可信度。需要检查是否有遗漏的重要点,比如节点操作系统、内核版本的影响,或者网络带宽的要求,但根据引用内容,用户主要关注CPU、内存、存储,所以可以集中在这些方面。</think>### Kubernetes集群节点资源配置要求最佳实践 #### 一、基础资源配置要求 1. **控制平面节点(Master节点)** - **CPU**:至少2核(推荐4核以上),用于处理API请求、调度、控制器等核心组件[^2] - **内存**:最低2GB(生产环境建议4GB以上),需支撑`kube-apiserver`、`etcd`等高消耗组件 - **存储**:系统盘建议50GB以上(需考虑`etcd`数据增长),IOPS不低于500[^3] 2. **工作节点(Worker节点)** - **CPU**:根据负载动态调整,建议预留至少1核供系统/K8s组件使用 - **内存**:总量需满足`Pod需求 + 系统预留(至少1GB)`,避免因OOM(内存溢出)导致Pod驱逐 - **存储**: - 容器运行时存储(如Docker):推荐100GB以上,支持镜像分层 - 持久化卷(PV):独立分区,根据业务需求配置(如SSD优化IO密集型应用) #### 二、最佳实践 1. **资源预留策略** - 通过`kubelet`配置`--system-reserved`和`--kube-reserved`参数,为系统/K8s组件保留资源 - 示例:预留10% CPU和15%内存防止资源争抢 ```yaml kubeletArguments: system-reserved: ["cpu=500m,memory=1Gi"] ``` 2. **监控调优** - 使用`kubectl top nodes`或`Prometheus`监控实时资源利用率[^1] - 通过`Vertical Pod Autoscaler(VPA)`自动调整Pod资源请求 3. **水平扩展原则** - 单节点资源上限建议: - CPU不超过64核(避免调度粒度问题) - 内存不超过256GB(防止垃圾回收延迟) 4. **存储配置建议** - 使用本地SSD或高性能云盘(如AWS EBS gp3) - 分离`/var/lib/kubelet`(Pod卷)和`/var/lib/docker`(镜像存储)的存储路径 #### 三、特殊场景要求 1. **有状态应用(如数据库)** - 配置`Local PersistentVolume`并绑定NUMA节点,减少跨CPU访问延迟 - 内存分配需包含缓存需求(如Redis建议预留30%额外内存) 2. **边缘计算场景** - 最小化节点配置(如1核2GB内存)时,需关闭非核心组件(如`kube-proxy`替换为`Cilium`) #### 四、配置验证方法 ```bash # 查看节点资源容量分配 kubectl describe nodes | grep -A 10 "Capacity" # 输出示例: # Capacity: # cpu: 8 # memory: 16302084Ki # Allocatable: # cpu: 7800m # memory: 14462244Ki ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值