正确配置Kubelet可一定程度防止K8S集群雪崩

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

Kubelet Node Allocatable

  • Kubelet Node Allocatable用来为Kube组件和System进程预留资源,从而保证当节点出现满负荷时也能保证Kube和System进程有足够的资源。
  • 目前支持cpu, memory, ephemeral-storage三种资源预留。
  • Node Capacity是Node的所有硬件资源,kube-reserved是给kube组件预留的资源,system-reserved是给System进程预留的资源, eviction-threshold是kubelet eviction的阈值设定,allocatable才是真正scheduler调度Pod时的参考值(保证Node上所有Pods的request resource不超过Allocatable)。
  • Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold

输入图片说明

如何配置

  • --enforce-node-allocatable,默认为pods,要为kube组件和System进程预留资源,则需要设置为pods,kube-reserved,system-reserve
  • --cgroups-per-qos,Enabling QoS and Pod level cgroups,默认开启。开启后,kubelet会将管理所有workload Pods的cgroups。
  • --cgroup-driver,默认为cgroupfs,另一可选项为systemd。取决于容器运行时使用的cgroup driver,kubelet与其保持一致。比如你配置docker使用systemd cgroup driver,那么kubelet也需要配置--cgroup-driver=systemd。
  • --kube-reserved,用于配置为kube组件(kubelet,kube-proxy,dockerd等)预留的资源量,比如—kube-reserved=cpu=1000m,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=500m,memory=4Gi,ephemeral-storage=4Gi。
  • --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到此节点。关于Kubelet Eviction的更多解读,请参考我的相关博文。
  • Kubelet Node Allocatable的代码很简单,主要在pkg/kubelet/cm/node_container_manager.go,感兴趣的同学自己去走读一遍。

关于如何规划Node的Cgroup结构,请参考官方建议: recommended-cgroups-setup

Sample

以如下的kubelet资源预留为例,Node Capacity为memory=32Gi, cpu=16, ephemeral-storage=100Gi,我们对kubelet进行如下配置:

--enforce-node-allocatable=pods,kube-reserved,system-reserved
--kube-reserved-cgroup=/kubelet.service
--system-reserved-cgroup=/system.slice
--kube-reserved=cpu=1,memory=2Gi,ephemeral-storage=1Gi
--system-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi
--eviction-hard=memory.available<500Mi,nodefs.available<10%

NodeAllocatable = NodeCapacity - Kube-reserved - system-reserved - eviction-threshold =
cpu=14.5,memory=28.5Gi,ephemeral-storage=98Gi.

Scheduler会确保Node上所有的Pod Resource Request不超过NodeAllocatable。Pods所使用的memory和storage之和超过NodeAllocatable后就会触发kubelet Evict Pods。

我踩的坑

kube-reserved-cgroup及system-reserved-cgroup配置

最开始,我只对kubelet做了如下配置--kube-reserved, --system-reserved,我就以为kubelet会自动给kube和system创建对应的Cgroup,并设置对应的cpu share, memory limit等,然后高枕无忧了。

然而实际上并非如此,直到在线上有一次某个TensorFlow worker的问题,无限制的使用节点的cpu,导致节点上cpu usage持续100%运行,并且压榨到了kubelet组件的cpu使用,导致kubelet与APIServer的心跳断了,这个节点便Not Ready了。

接着,Kubernetes会在其他某个最优的Ready Node上启动这个贪婪的worker,进而把这个节点的cpu也跑满了,节点Not Ready了。

如此就出现了集群雪崩,集群内的Nodes逐个的Not Ready了,后果非常严重。

把kublet加上如下配置后,即可保证在Node高负荷时,也能保证当kubelet需要cpu时至少能有--kube-reserved设置的cpu cores可用。

--enforce-node-allocatable=pods,kube-reserved,system-reserved
--kube-reserved-cgroup=/kubelet.service
--system-reserved-cgroup=/system.slice

注意,因为kube-reserved设置的cpu其实最终是写到kube-reserved-cgroup下面的cpu shares。了解cpu shares的同学知道,只有当集群的cpu跑满需要抢占时才会起作用,因此你会看到Node的cpu usage还是有可能跑到100%的,但是不要紧,kubelet等组件并没有收到影响,如果kubelet此时需要更多的cpu,那么它就能抢到更多的时间片,最多可以抢到kube-reserved设置的cpu nums。

Kubernetes会检查的cgroup subsystem

  • 在Kubernetes 1.7版本,Kubelet启动会检查以下cgroup subsystem的存在:

输入图片说明

  • 在Kubernetes 1.8及1.9版本,Kubelet启动会检查以下cgroup subsystem的存在:

输入图片说明

对于Centos系统,cpuset和hugetlb subsystem是默认没有初始化system.slice,因此需要手动创建,否则会报Failed to start ContainerManager Failed to enforce System Reserved Cgroup Limits on "/system.slice": "/system.slice" cgroup does not exist的错误日志。

我们可以通过在kubelet service中配置ExecStartPre来实现。

输入图片说明

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
9天前
|
Kubernetes 监控 Cloud Native
Kubernetes集群的高可用性与伸缩性实践
Kubernetes集群的高可用性与伸缩性实践
37 1
|
30天前
|
JSON Kubernetes 容灾
ACK One应用分发上线:高效管理多集群应用
ACK One应用分发上线,主要介绍了新能力的使用场景
|
1月前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。
|
15天前
|
Kubernetes 监控 Java
如何在Kubernetes中配置镜像和容器的定期垃圾回收
如何在Kubernetes中配置镜像和容器的定期垃圾回收
|
1月前
|
Kubernetes 安全 Cloud Native
云上攻防-云原生篇&K8s安全-Kubelet未授权访问、API Server未授权访问
本文介绍了云原生环境下Kubernetes集群的安全问题及攻击方法。首先概述了云环境下的新型攻击路径,如通过虚拟机攻击云管理平台、容器逃逸控制宿主机等。接着详细解释了Kubernetes集群架构,并列举了常见组件的默认端口及其安全隐患。文章通过具体案例演示了API Server 8080和6443端口未授权访问的攻击过程,以及Kubelet 10250端口未授权访问的利用方法,展示了如何通过这些漏洞实现权限提升和横向渗透。
159 0
云上攻防-云原生篇&K8s安全-Kubelet未授权访问、API Server未授权访问
|
1月前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
611 1
|
1月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
76 3
|
1月前
|
Kubernetes Cloud Native 微服务
微服务实践之使用 kube-vip 搭建高可用 Kubernetes 集群
微服务实践之使用 kube-vip 搭建高可用 Kubernetes 集群
114 1
|
1月前
|
Kubernetes Ubuntu Linux
Centos7 搭建 kubernetes集群
本文介绍了如何搭建一个三节点的Kubernetes集群,包括一个主节点和两个工作节点。各节点运行CentOS 7系统,最低配置为2核CPU、2GB内存和15GB硬盘。详细步骤包括环境配置、安装Docker、关闭防火墙和SELinux、禁用交换分区、安装kubeadm、kubelet、kubectl,以及初始化Kubernetes集群和安装网络插件Calico或Flannel。
155 0
|
1月前
|
弹性计算 Kubernetes Linux
如何使用minikube搭建k8s集群
如何使用minikube搭建k8s集群
下一篇
无影云桌面