k8s资源需求和限制, 以及pod驱逐策略

 

容器的资源需求和资源限制

  • requests:需求,最低保障, 保证被调度的节点上至少有的资源配额
  • limits:限制,硬限制, 容器可以分配到的最大资源配额

apiVersion: v1
kind: Pod
metadata:
    name: pod-demo
    labels:
        app: myapp
        tier: fronted
spec:
    containers:
    - name: myapp
      image: ikubernetes/stress-ng
      command: ["/usr/bin/stress-ng", "-m 1", "-c 1", "--metrics-brief"]
      resources:
        requests:
          cpu: "200m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "200Mi"
kubectl exec pod-demo -- top

这是一个CPU为2核的节点, 分配给容器500m的CPU, 也就是0.5个CPU, 所以看到的进程CPU占用率约为26%

QoS Classes分类

Guaranteed

如果Pod中所有Container的所有Resource的limitrequest都相等且不为0,则这个Pod的QoS Class就是Guaranteed。

注意,如果一个容器只指明了limit,而未指明request,则表明request的值等于limit的值。

containers:
    name: foo
        resources:
            limits:
                cpu: 10m
                memory: 1Gi
    name: bar
        resources:
            limits:
                cpu: 100m
                memory: 100Mi
            requests:
                cpu: 100m
                memory: 100Mi

Burstable

至少有一个容器设置CPU或内存资源的requests属性

Best-Effort

如果Pod中所有容器的所有Resource的request和limit都没有赋值,则这个Pod的QoS Class就是Best-Effort.

containers:
    name: foo
        resources:
    name: bar
        resources:

kubernetes之node资源紧缺时pod驱逐机制

Qos Class优先级排名

Guaranteed > Burstable > Best-Effort

可压缩资源与不可压缩资源

Pod 使用的资源最重要的是 CPU、内存和磁盘 IO,这些资源可以被分为可压缩资源(CPU)不可压缩资源(内存,磁盘 IO)

  • 可压缩资源(CPU)不会导致pod被驱逐

    因为当 Pod 的 CPU 使用量很多时,系统可以通过重新分配权重来限制 Pod 的 CPU 使用

  • 不可压缩资源(内存)则会导致pod被驱逐

    于不可压缩资源来说,如果资源不足,也就无法继续申请资源(内存用完就是用完了),此时 Kubernetes 会从该节点上驱逐一定数量的 Pod,以保证该节点上有充足的资源。

存储资源不足

下面是 kubelet 默认的关于节点存储的驱逐触发条件:

  • nodefs.available<10%(容器 volume 使用的文件系统的可用空间,包括文件系统剩余大小和 inode 数量)
  • imagefs.available<15%(容器镜像使用的文件系统的可用空间,包括文件系统剩余大小和 inode 数量)

imagefs 使用量达到阈值时,kubelet 会尝试删除不使用的镜像来清理磁盘空间。

nodefs 使用量达到阈值时,kubelet 就会拒绝在该节点上运行新 Pod,并向 API Server 注册一个 DiskPressure condition。然后 kubelet 会尝试删除死亡的 Pod 和容器来回收磁盘空间,如果此时 nodefs 使用量仍然没有低于阈值,kubelet 就会开始驱逐 Pod。kubelet 驱逐 Pod 的过程中不会参考 Pod 的 QoS,只是根据 Pod 的 nodefs 使用量来进行排名,并选取使用量最多的 Pod 进行驱逐。所以即使 QoS 等级为 Guaranteed 的 Pod 在这个阶段也有可能被驱逐(例如 nodefs 使用量最大)。如果驱逐的是 Daemonset,kubelet 会阻止该 Pod 重启,直到 nodefs 可用量超过阈值。

如果一个 Pod 中有多个容器,kubelet 会根据 Pod 中所有容器的 nodefs 使用量之和来进行排名。即所有容器的 container_fs_usage_bytes 指标值之和。

举例

Pod NamePod QoSnodefs usage
ABest Effort800M
BGuaranteed1.3G
CBurstable1.2G
DBurstable700M
EBest Effort500M
FGuaranteed1G

当 nodefs 的使用量超过阈值时,kubelet 会根据 Pod 的 nodefs 使用量来对 Pod 进行排名,首先驱逐使用量最多的 Pod。排名如下图所示:

Pod NamePod QoSnodefs usage
BGuaranteed1.3G
CBurstable1.2G
FGuaranteed1G
ABest Effort800M
DBurstable700M
EBest Effort500M

内存资源不足

下面是 kubelet 默认的关于节点内存资源的驱逐触发条件:

  • memory.available<100Mi

当内存使用量超过阈值时,kubelet 就会向 API Server 注册一个 MemoryPressure condition,此时 kubelet 不会接受新的 QoS 等级为 Best Effort 的 Pod 在该节点上运行,并按照以下顺序来驱逐 Pod:

  • Pod 的内存使用量是否超过了 request 指定的值
  • 根据 priority 排序,优先级低的 Pod 最先被驱逐
  • 比较它们的内存使用量与 request 指定的值之差。

按照这个顺序,可以确保 QoS 等级为 Guaranteed 的 Pod 不会在 QoS 等级为 Best Effort 的 Pod 之前被驱逐,但不能保证它不会在 QoS 等级为 Burstable 的 Pod 之前被驱逐。

如果一个 Pod 中有多个容器,kubelet 会根据 Pod 中所有容器相对于 request 的内存使用量与之和来进行排名。即所有容器的 (container_memory_usage_bytes 指标值与 container_resource_requests_memory_bytes 指标值的差)之和。

举例

Pod NamePod QoSMemory requestedMemory limitsMemory usage
ABest Effort00700M
BGuaranteed2Gi2Gi1.9G
CBurstable1Gi2Gi1.8G
DBurstable1Gi2Gi800M
EBest Effort00300M
FGuaranteed2Gi2Gi1G

当节点的内存使用量超过阈值时,kubelet 会根据 Pod 相对于 request 的内存使用量来对 Pod 进行排名。排名如下所示:

Pod NamePod QoSMemory requestedMemory limitsMemory usage内存相对使用量
CBurstable1Gi2Gi1.8G800M
ABest Effort00700M700M
EBest Effort00300M300M
BGuaranteed2Gi2Gi1.9G-100M
DBurstable1Gi2Gi800M-200M
FGuaranteed2Gi2Gi1G-1G

当内存资源不足时,kubelet 在驱逐 Pod 时只会考虑 requests 和 Pod 的内存使用量,不会考虑 limits。

Node OOM (Out Of Memory)

因为 kubelet 默认每 10 秒抓取一次 cAdvisor 的监控数据,所以有可能在 kubelet 驱逐 Pod 回收内存之前发生内存使用量激增的情况,这时就有可能触发内核 OOM killer。这时删除容器的权利就由kubelet 转交到内核 OOM killer 手里,但 kubelet 仍然会起到一定的决定作用,它会根据 Pod 的 QoS 来设置其 oom_score_adj 值:

QoSoom_score_adj
Guaranteed-998
Burstablemin(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)
pod-infra-container-998
kubelet, docker daemon, systemd service-999

如果该节点在 kubelet 通过驱逐 Pod 回收内存之前触发了 OOM 事件,OOM killer 就会采取行动来降低系统的压力,它会根据下面的公式来计算 oom_score 的值:

容器使用的内存占系统内存的百分比 + oom_score_adj = oom_score>

OOM killer 会杀掉 oom_score_adj 值最高的容器,如果有多个容器的 oom_score_adj 值相同,就会杀掉内存使用量最多的容器(其实是因为内存使用量最多的容器的 oom_score 值最高)。关于 OOM 的更多内容请参考:Kubernetes 内存资源限制实战

假设某节点运行着 4 个 Pod,且每个 Pod 中只有一个容器。每个 QoS 类型为 Burstable 的 Pod 配置的内存 requests 是 4Gi,节点的内存大小为 30Gi。每个 Pod 的 oom_score_adj 值如下所示:

Pod NamePod QoSoom_score_adj
ABest Effort1000
BGuaranteed-998
CBurstable867(根据上面的公式计算)
DBest Effort1000

当调用 OOM killer 时,它首先选择 oom_score_adj 值最高的容器(1000),这里有两个容器的 oom_score_adj 值都是 1000,OOM killer 最终会选择内存使用量最多的容器。

总结

  • 因为 kubelet 默认每 10 秒抓取一次 cAdvisor 的监控数据,所以可能在资源使用量低于阈值时,kubelet 仍然在驱逐 Pod。
  • kubelet 将 Pod 从节点上驱逐之后,Kubernetes 会将该 Pod 重新调度到另一个资源充足的节点上。但有时候 Scheduler 会将该 Pod 重新调度到与之前相同的节点上,比如设置了节点亲和性,或者该 Pod 以 Daemonset 的形式运行。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Kubernetes中,硬盘到达一定使用量后会驱逐Pod,以避免磁盘空间不足的情况。默认情况下,硬盘使用量达到80%时,Kubernetes会开始清理不需要的数据以释放磁盘空间。如果硬盘使用量达到85%,Kubernetes会开始驱逐Pod。如果需要更改这些默认配置,可以通过修改kubelet的启动参数来实现。 以下是修改kubelet启动参数的步骤: 1. 编辑kubelet的启动配置文件,例如: ``` vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf ``` 2. 找到“ExecStart=/usr/bin/kubelet”这一行,添加需要更改的参数,例如: ``` ExecStart=/usr/bin/kubelet --eviction-hard="memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<10%" --eviction-soft="memory.available<200Mi,nodefs.available<20%,nodefs.inodesFree<20%" --eviction-soft-grace-period=1m --eviction-pressure-transition-period=5m ``` 在上述示例中,我们添加了4个参数: - `--eviction-hard`:定义硬阈值,即当内存可用空间小于100Mi或节点文件系统可用空间小于10%或节点文件系统可用inode数量小于10%时,将立即驱逐Pod。 - `--eviction-soft`:定义软阈值,即当内存可用空间小于200Mi或节点文件系统可用空间小于20%或节点文件系统可用inode数量小于20%时,将开始驱逐Pod。 - `--eviction-soft-grace-period`:定义软阈值容忍时间,即当软阈值条件满足后,Kubernetes将等待1分钟后再开始驱逐Pod。 - `--eviction-pressure-transition-period`:定义硬阈值到软阈值的过渡时间,即当内存可用空间小于100Mi或节点文件系统可用空间小于10%或节点文件系统可用inode数量小于10%时,Kubernetes将等待5分钟后再开始驱逐Pod。 3. 修改完成后,保存文件并重新加载kubelet的配置文件: ``` systemctl daemon-reload ``` 4. 重启kubelet服务: ``` systemctl restart kubelet ``` 修改完成后,Kubernetes将根据新的配置来判断何时开始驱逐Pod,从而避免磁盘空间不足的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值