kubernets资源预留

一、  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 Capacity

--------------------------------

|     kube-reserved         |

|-------------------------------|

|     system-reserved      |

|-------------------------------|

|    eviction-threshold     |

|-------------------------------|

|      allocatable              |

|   (available for pods)   |

--------------------------------

可分配资源

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

二、  Kubernetes配置资源预留

以下均为kubelet组件参数

  • --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,感兴趣的同学自己去走读一遍。

示例:

以如下的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。

1.    Kube Reserved

Kubelet Flag: --kube-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
Kubelet Flag: --kube-reserved-cgroup=

kube-reserved 是为了给诸如 kubelet、container runtime、node problem detector 等 kubernetes 系统守护进程争取资源预留。这并不代表要给以 pod 形式运行的系统守护进程保留资源。kube-reserved 通常是节点上的一个 pod 密度(pod density) 功能。 这个性能仪表盘 从 pod 密度的多个层面展示了 kubelet 和 docker engine 的 cpu 和 memory使用情况。

要选择性的在系统守护进程上执行 kube-reserved,需要把 kubelet 的 --kube-reserved-cgroup 标志的值设置为 kube 守护进程的父控制组。

 推荐将 kubernetes 系统守护进程放置于顶级控制组之下(例如 systemd 机器上的 runtime.slice)。理想情况下每个系统守护进程都应该在其自己的子控制组中运行。请参考这篇文档,获取更过关于推荐控制组层次结构的细节。

 请注意,如果 --kube-reserved-cgroup 不存在,Kubelet 将不会创建它。如果指定了一个无效的 cgroup,Kubelet 将会失败。

2.    系统预留值(System Reserved)

Kubelet Flag: --system-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
Kubelet Flag: --system-reserved-cgroup=

system-reserved 用于为诸如 sshd、udev 等系统守护进程争取资源预留。system-reserved 也应该为 kernel 预留 内存,因为目前 kernel 使用的内存并不记在 Kubernetes 的 pod 上。同时还推荐为用户登录会话预留资源(systemd 体系中的 user.slice)。

要想在系统守护进程上可选地执行 system-reserved,请指定 --system-reserved-cgroup kubelet 标志的值为 OS 系统守护进程的父级控制组。

推荐将 OS 系统守护进程放在一个顶级控制组之下(例如 systemd 机器上的system.slice)。

请注意,如果 --system-reserved-cgroup 不存在,Kubelet 不会创建它。如果指定了无效的 cgroup,Kubelet 将会失败。

3.    驱逐阈值(Eviction Thresholds)

Kubelet Flag: --eviction-hard=[memory.available<10%][,][ephemeral-storage<1Gi]

节点级别的内存压力将导致系统内存不足(System OOMs),这将影响到整个节点及其上运行的所有 pod。节点可以暂时离线直到内存已经回收为止。为了防止(或减少可能性)系统内存不足,kubelet 提供了 资源不足(Out of Resource) 管理。驱逐(Eviction)操作只支持 memory 和ephemeral-storage。通过 --eviction-hard 标志预留一些内存后,当节点上的可用内存降至保留值以下时,kubelet 将尝试 驱逐 pod。假设,如果节点上不存在系统守护进程,pod 将不能使用超过 capacity-eviction-hard 的资源。因此,为驱逐而预留的资源对 pod 是不可用的。

eviction-hard的值支持1Gi或者10%格式。

kubelet的默认eviction-hard值如下:

  • memory.available<100Mi
  • nodefs.available<10%
  • nodefs.inodesFree<5%
  • imagefs.available<15%

1.    执行节点 Allocatable

Kubelet Flag: --enforce-node-allocatable=pods[,][system-reserved][,][kube-reserved]

调度器将 Allocatable 按 pod 的可用 capacity 对待。

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。

三、  一般原则

系统守护进程期望被按照类似 Guaranteed pod 一样对待。系统守护进程可以在其范围控制组中爆发式增长,您需要将这个行为作为 kubernetes 部署的一部分进行管理。例如,kubelet 应该有它自己的控制组并和容器运行时(container runtime)共享 Kube-reserved 资源。然而,如果执行了 kube-reserved,则 kubelet 不能突然爆发并耗尽节点的所有可用资源。

在执行 system-reserved 预留操作时请加倍小心,因为它可能导致节点上的关键系统服务 CPU 资源短缺或因为内存不足(OOM)而被终止。

在 pods 上执行 Allocatable 作为开始。

一旦足够用于追踪系统守护进程的监控和告警的机制到位,请尝试基于用量探索(usage heuristics)方式执行 kube-reserved。

随着时间推进,如果绝对必要,可以执行 system-reserved。

随着时间的增长以及越来越多特性的加入,kube 系统守护进程对资源的需求可能也会增加。以后 kubernetes 项目将尝试减少对节点系统守护进程的利用,但目前那并不是优先事项。所以,请期待在将来的发布中将 Allocatable 容量降低。

四、  示例场景

这是一个用于说明节点 Allocatable 计算方式的示例:

节点拥有 32Gi 内存,16 核 CPU 和 100Gi 存储

--kube-reserved 设置为 cpu=1,memory=2Gi,storage=1Gi

--system-reserved 设置为 cpu=500m,memory=1Gi,storage=1Gi

--eviction-hard 设置为 memory.available<500Mi,nodefs.available<10%

在这个场景下,Allocatable 将会是 14.5 CPUs、28.5Gi 内存以及 98Gi 存储。调度器保证这个节点上的所有 pod 请求的内存总量不超过 28.5Gi,存储不超过 88Gi。当 pod 的内存使用总量超过 28.5Gi 或者磁盘使用总量超过 88Gi 时,Kubelet 将会驱逐它们。如果节点上的所有进程都尽可能多的使用 CPU,则 pod 加起来不能使用超过 14.5 CPUs 的资源。

当没有执行 kube-reserved 和/或 system-reserved 且系统守护进程使用量超过其预留时,如果节点内存用量高于 31.5Gi 或存储大于 90Gi,kubelet 将会驱逐 pod。

可用特性

截至 Kubernetes 1.2 版本,已经可以可选的指定 kube-reserved 和 system-reserved 预留。当在相同的发布中都可用时,调度器将转为使用 Allocatable 替代 Capacity。

截至 Kubernetes 1.6 版本,eviction-thresholds 是通过计算 Allocatable 进行考虑。要使用旧版本的行为,请设置 --experimental-allocatable-ignore-eviction kubelet 标志为 true。

截至 Kubernetes 1.6 版本,kubelet 使用控制组在 pod 上执行 Allocatable。要使用旧版本行为,请取消设置 --enforce-node-allocatable kubelet 标志。请注意,除非 --kube-reserved 或者 --system-reserved 或者 --eviction-hard 标志没有默认参数,否则 Allocatable 的实施不会影响已经存在的 deployment。

截至 Kubernetes 1.6 版本,kubelet 在 pod 自己的 cgroup 沙箱中启动它们,这个 cgroup 沙箱在 kubelet 管理的 cgroup 层次结构中的一个独占部分中。在从前一个版本升级 kubelet之前,要求操作员 drain 节点,以保证 pod 及其关联的容器在 cgroup 层次结构中合适的部分中启动。

截至 Kubernetes 1.7 版本,kubelet 支持指定 storage 为 kube-reserved 和 system-reserved 的资源。

五、  Openshift配置

在kubelet中新增参数system-reserved和kube-reserved,

可以在每个node节点的/etc/origin/node/node-config.yaml修改,但是这是临时生效,

想要永久生效,需要修改openshift-node命名空间里的configmap,想改哪个group的参数就修改哪个configmap。

在openshift中新增或者修改kubelet的参数都可以通过这种方式。

例如:给compute-normal group新增system-reserved和kube-reserved参数:

kubectl edit -n openshift-node cm node-config-compute-normal

    kubeletArguments:
      bootstrap-kubeconfig:
      - /etc/origin/node/bootstrap.kubeconfig
      cert-dir:
      - /etc/origin/node/certificates
      enable-controller-attach-detach:
      - 'true'
      feature-gates:
      - RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true
      node-labels:
      - node-role.kubernetes.io/compute-normal=true
      pod-manifest-path:
      - /etc/origin/node/pods
      rotate-certificates:
      - 'true'
      evction-hard:
      - 'memory.available<500Mi,nodefs.available<10%'
      system-reserved:
      - 'cpu=200m,memory=1Gi'
      kube-reserved:
      - "cpu=200m,memory=1Gi"

如果修改的是master组件的参数,而不是kubelet的,则按照下面的方法。

修改master的配置在每个master的/etc/origin/master/master-config.yaml

kubernetesMasterConfig:
  controllerArguments: 
    node-monitor-period:
    - "10m"

重启相关组件

# master-restart api

# master-restart controllers

修改pod-evction-timeout参数:

1.修改每个master上/etc/origin/master/master-config.yaml

  podEvictionTimeout: "2m0s"

2.重启controller:

master-restart controllers

六、  参数资料

http://docs.kubernetes.org.cn/723.html

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

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

https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/

原文地址:https://www.cnblogs.com/yehaifeng/p/10715192.html