问题

默认kubelet没有配置资源预留,host上所有的资源(cpu, 内存, 磁盘) 都是可以给 pod 使用的。而当一个节点上的 pod 将资源吃满时,系统层面可能会干掉 k8s 核心组件进程, 从而导致改节点 not ready,此时 k8s 会将改节点的所有 pod 调度到其他节点重建,如果其他节点资源也不够,那么其他节点也会 not ready,进而引起集群雪崩效应。

如何避免

通过为 k8s 设置 kube 组件资源预留和 system 系统资源预留,保证节点的 pod 不会吃满节点资源

目前支持cpu, memory, ephemeral-storage 三种资源预留。

  1. cpu: cpu是配置cpu shares,实际上对应的是cpu的优先级,简单来说,这个在cpu繁忙时,它能有更高优先级获取更多cpu资源。
  2. memory: k8s默认不使用 swap,这里指的就是实际的内存
  3. ephemeral-storagekubernetes1.8开始引入的一个资源限制的对象,kubernetes 1.10版本中kubelet默认已经打开的了,到目前1.11还是beta阶段,主要是用于对本地临时存储使用空间大小的限制,如对podempty dir/var/lib/kubelet、日志、容器可读写层的使用大小的限制。

Node CapacityNode的所有硬件资源,kube-reserved是给kube组件预留的资源,system-reserved是给System进程预留的资源, eviction-thresholdkubelet eviction的阈值设定,allocatable才是真正scheduler调度Pod时的参考值(保证Node上所有Podsrequest resource不超过Allocatable

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

      Node Capacity
---------------------------
|     kube-reserved       |
|-------------------------|
|     system-reserved     |
|-------------------------|
|    eviction-threshold   |
|-------------------------|
|                         |
|      allocatable        |
|   (available for pods)  |
|                         |
|                         |
---------------------------

eviction-threshold实际上是对pod limit_resource的补充,因为limit_resource只能针对单个pod做资源限制,当这个pod达到限制的阀值后,kubelet便会oom_killer掉这个pod,而eviction-threshold根据事先设定的Eviction Thresholds来触发Eviction,调用算法筛选出合适的几个podkill掉一个或多个pod回收资源,被eviction掉的pod会被kube-scheduler在其他节点重新调度起来

eviction-threshold 分为两类:

Soft Eviction Thresholds

达到触发值后,发送信号给 pod, 并不是马上去驱逐pod,而是等待一个缓冲时间 grace period,

配置 eviction-soft 必须指定 grace period

Hard Eviction Thresholds

达到触发值后,直接筛选出对应的pod kill

配置

  • --enforce-node-allocatable,默认为pods,要为kube组件和System进程预留资源,则需要设置为pods,kube-reserved,system-reserve
  • --cgroups-per-qosEnabling QoS and Pod level cgroups,默认开启。开启后,kubelet将会管理所有workload Podscgroups
  • --cgroup-driver,默认为cgroupfs,另一可选项为systemd。取决于容器运行时使用的cgroup driverkubelet与其保持一致。比如你配置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=/system.slice/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,用来配置kubelethard eviction条件,只支持memoryephemeral-storage两种不可压缩资源。当出现MemoryPressure时,Scheduler不会调度新的Best-Effort QoS Pods到此节点。当出现DiskPressure时,Scheduler不会调度任何新Pods到此节点。

配置示例

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
# CPUAccounting=true
# MemoryAccounting=true
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/pids/system.slice/kubelet.service
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpu/system.slice/kubelet.service
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpuacct/system.slice/kubelet.service
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/memory/system.slice/kubelet.service
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/systemd/system.slice/kubelet.service
ExecStart=/usr/local/bin/kubelet \--cgroup-driver=systemd \--enforce-node-allocatable=pods,kube-reserved,system-reserved \--kube-reserved-cgroup=/system.slice/kubelet.service \--system-reserved-cgroup=/system.slice \--kube-reserved=cpu=1000m,memory=2Gi,ephemeral-storage=1Gi \--system-reserved=cpu=1000m,memory=2Gi,ephemeral-storage=1Gi \--max-pods=100 \--eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<3% \--eviction-max-pod-grace-period=40 \--eviction-minimum-reclaim=memory.available=1Gi,nodefs.available=5Gi,imagefs.available=5Gi \--eviction-soft-grace-period=memory.available=30s,nodefs.available=2m,imagefs.available=2m,nodefs.inodesFree=2m \--eviction-soft=imagefs.available<20%,memory.available<1Gi,nodefs.available<15%,nodefs.inodesFree<5% \--experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \--rotate-certificates \--cert-dir=/etc/kubernetes/ssl \--cluster_dns=10.96.0.2 \--cluster_domain=cluster.local. \--hairpin-mode=promiscuous-bridge \--allow-privileged=true \--fail-swap-on=false \--serialize-image-pulls=false \--logtostderr=true \--network-plugin=cni \--cni-conf-dir=/etc/cni/net.d \--cni-bin-dir=/opt/cni/bin \--v=1
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

注意: 如果设置完资源预留,重启 kubelet 之后,发现 node 变成 not readykubectl describe node 查看, 报错为:

failed to write 6442450944 to memory.limit_in_bytes: write /sys/fs/cgroup/memory/system.slice/memory.limit_in_bytes: device or resource busy

是因为实际系统内存使用量大于 --system-reserved=cpu=1000m,memory=6Gi 的配置,将 6g 改大之后重启kubelet即可,当然具体改为多少,要看节点上实际系统占用内存(笔者测试机上装有 ceph, 所以系统部分所需内存较大)

测试

环境

hostname role cpu memory –kube-reserved=cpu –kube-reserved=memory –system-reserved=cpu –system-reserved=memory
k8s1 master 12 47G 1000m 2Gi 1000m 15Gi
k8s2 master 32 31G 1000m 2Gi 1000m 8Gi
k8s3 node 16 62G 1000m 2Gi 1000m 8Gi

describe node

# k8s1
Addresses:InternalIP:  10.10.1.223Hostname:    k8s1
Capacity:cpu:                12ephemeral-storage:  574727312Kihugepages-1Gi:      0hugepages-2Mi:      0memory:             49425780Ki # k8s1 实际总内存: 47Gpods:               110
Allocatable:cpu:                10ephemeral-storage:  523226238919hugepages-1Gi:      0hugepages-2Mi:      0memory:             31292788Ki # k8s1 节点可以分配给 pod 的总内存: 30Gpods:               110
...
Allocated resources:(Total limits may be over 100 percent, i.e., overcommitted.)Resource           Requests            Limits--------           --------            ------cpu                8023m (80%)         35643m (356%)memory             32389500928 (101%)  75199505664 (234%)ephemeral-storage  0 (0%)              0 (0%)# k8s2
Capacity:cpu:                32ephemeral-storage:  459378800Kihugepages-1Gi:      0hugepages-2Mi:      0memory:             32906916Kipods:               110
Allocatable:cpu:                30ephemeral-storage:  416921050436hugepages-1Gi:      0hugepages-2Mi:      0memory:             22113956Kipods:               110
...
Allocated resources:(Total limits may be over 100 percent, i.e., overcommitted.)Resource           Requests          Limits--------           --------          ------cpu                8123m (27%)       30203m (100%)memory             22098028Ki (99%)  60566922496 (267%)ephemeral-storage  0 (0%)            0 (0%)# k8s3
Capacity:cpu:                16ephemeral-storage:  575257712Kihugepages-1Gi:      0hugepages-2Mi:      0memory:             65916188Kipods:               110
Allocatable:cpu:                14ephemeral-storage:  523715055558hugepages-1Gi:      0hugepages-2Mi:      0memory:             55123228Kipods:               110
...
Allocated resources:(Total limits may be over 100 percent, i.e., overcommitted.)Resource           Requests          Limits--------           --------          ------cpu                12785m (91%)      71410m (510%)memory             54820406Ki (99%)  155630527744 (275%)ephemeral-storage  0 (0%)            0 (0%)

k8s1 节点实际总内存 47G,减去 --kube-reserved=memory=2Gi, 再减去 --system-reserved=memory=15Gi, 为 k8s1 可以分配给 pod 的总内存 30G,并且该 30G 就是节点 resource requests 的上限

可以看到为 kube 和系统配置的资源预留确实生效了

再看下节点 podrequests

kube-scheduler 根据 pod 设置的 resource requestspod 选取合适的节点,现在 3台节点上requests 都满了,故无法再为新的 pod 调度,这时候新建 pod 会处于 Pending 状态,describe pod 会显示

Events:Type     Reason            Age        From               Message----     ------            ----       ----               -------Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 Insufficient memory.

而实际上各节点的 free -h 输出如下:

# k8s1
root@k8s1:~# free -htotal        used        free      shared  buff/cache   available
Mem:            47G         25G         14G         13M        7.7G         21G
Swap:            0B          0B          0B# k8s2
root@k8s2:~# free -htotal        used        free      shared  buff/cache   available
Mem:            31G         27G        210M         13M        4.2G        5.1G
Swap:            0B          0B          0B# k8s3
root@k8s3:~# free -htotal        used        free      shared  buff/cache   available
Mem:            62G         36G         12G        134M         14G         29G
Swap:            0B          0B          0B

会发现实际上,除去 --kube-reserved=memory--system-reserved=memory ,还有可用内存。

所以我们将上图中那些resource requests设置不合理的podrequests memory 设置小一点,就可以调度新的 pod

所以这里要清楚,k8s 通过 pod 配置的 resource requests 值来调度 pod 到资源有余的合适的节点,而节点可用的总资源就是节点实际总资源减去为 kubesystem 预留的资源

使用 kubectl top pod -A 查看 pod 实际资源使用,这里面显示的值就是 resource limit oom killer 依据的值

root@k8s1:/opt/kubespray# kubectl top pod
NAME                      CPU(cores)   MEMORY(bytes)
whoami-5b4bb9c787-m2vdt   0m           3Mi

注意:kubectl top node 显示的资源值,并不是节点上所有pod所使用资源的总和

参考

从一次集群雪崩看Kubelet资源预留的正确姿势

kubernetes集群节点资源预留

为系统守护进程预留计算资源

Configure Out of Resource Handling

从kubectl top看K8S监控

kubernetes集群节点资源预留相关推荐

  1. Promethus搭建 K8S 集群节点资源监控系统

    对于集群的监控一般我们需要考虑以下几个方面: Kubernetes 节点的监控:比如节点的 cpu.load.disk.memory 等指标 内部系统组件的状态:比如 kube-scheduler.k ...

  2. 零停机给Kubernetes集群节点打系统补丁

    点击上方 "编程技术圈"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 每日英文 A person who knows how to laugh a ...

  3. 如何利用Kubernetes集群提升资源利用率?

    导语 | 近日,云+社区技术沙龙"高效智能运维"圆满落幕.本期沙龙围绕运维展开了一场技术盛宴,从AIOps.Serverless DevOps.蓝鲸PaaS平台.K8S等分享关于业 ...

  4. kubelet 配置节点资源预留

    kubelet 配置节点资源预留 Kubernetes 的节点可以按照节点的资源容量进行调度,默认情况下 Pod 能够使用节点全部可用容量.这样就会造成一个问题,因为节点自己通常运行了不少驱动 OS ...

  5. 如何部署一个Kubernetes集群

    来源 | 无敌码农 责编 | 寇雪芹 头图 | 下载于视觉中国 在上一篇文章<Kubernetes和Docker的关系是什么?>中,和大家分享了关于Kubernetes的基本系统架构以及关 ...

  6. 中通快递关键业务和复杂架构挑战下的 Kubernetes 集群服务暴露实践

    本文是上海站 Meetup 讲师王文虎根据其分享内容整理的文章. KubeSphere 社区的小伙伴们,大家好.我是中通快递容器云平台的研发工程师王文虎,主要负责中通快递容器云平台开发.应用容器化推广 ...

  7. 初试 Kubernetes 集群使用 CephFS 文件存储

    目录 Kubernetes PersistentVolumes 介绍 环境.软件准备 单节点使用 CephFS Kubernetes PV & PVC 方式使用 CephFS 测试跨节点使用 ...

  8. 云原生第4课:Kubernetes 集群管理

    本篇文章来自<华为云云原生王者之路训练营>黄金系列课程第4课,由华为云Kubernetes容器平台技术专家Alan主讲,详细介绍Kubernetes集群和Kubernetes节点的生命周期 ...

  9. vivo AI计算平台 Kubernetes集群Ingress网关实践

    1.背景 vivo 人工智能计算平台小组从 2018 年底开始建设 AI 计算平台至今,已经在 kubernetes 集群.以及离线的深度学习模型训练等方面,积累了众多宝贵的开发.运维经验,并逐步打造 ...

最新文章

  1. 手动创建servlet
  2. 文件内容、关键字匹配,split 和 indexOf 均可实现
  3. python rest 框架_python-更新用户REST框架Django
  4. c语言继承与派生作用,C++中继承与派生是如何实现的?
  5. android全方位性能优化方法
  6. iOS 基础 第五天(0811)
  7. 广播接收者的特点和版本差异
  8. You need to use a Theme.AppCompat theme (or descendant) with this activity
  9. 谷歌浏览器如何长截屏
  10. Excel表VLOOKUP多个条件匹配数据
  11. 无人车之美——技术要点速览
  12. office365打开服务器文件出错,Microsoft Office 365个人版打开显示错误
  13. 路由器怎么连接台式电脑
  14. android 监听本机网络请求_前端系列课程(2)-网络基础概念(URL)
  15. 人工智能,机器学习,深度学习(笔记)
  16. 基于京东云GPU云主机搭建TensorFlow深度学习环境
  17. 算法与数据结构入门一篇就搞定
  18. 乙腈和水共沸_常用有机溶剂共沸点
  19. Sql Server级联操作
  20. python中累加函数_对Python实现累加函数的方法详解

热门文章

  1. 计算机硬件的漏洞,震惊了硬件圈子的CPU漏洞,到底是个什么鬼?
  2. 修理电脑笔记 -- 驱动的问题(如触摸屏 指纹解锁之类的驱动在重装系统之后无法使用)
  3. win7 pe 修改服务器地址,pe下修改win7服务器地址
  4. python+Linux centos7搭建服务器
  5. 搭建项目-快速搭建电商平台后台管理系统及逆向生成微服务基本功能
  6. pip使用163源(linux)
  7. 【论文-笔记】软件化雷达显控终端的研究
  8. 五子棋AI - 局面状态
  9. linux的dev中有video,为啥我的/dev/video0打不开!
  10. EXCEL中合并同列中连续相同内容的单元格