了解 Kubernetes 的 limits 和 requests

在 Kubernetes 中, 如何合理的设置容器资源请求和限制,对于优化应用程序和 k8s 集群性能至关重要。

Namespace quotas(名称空间配额)

Kubernetes 允许管理人员对特定的命令空间(namespace)设置配额, 以此对资源使用进行严格限制。如果在某命名空间下设置了 CPU 请求配额(request quotas), 那么该命名空间下的所有 Pod 都需要在其定义中设置 CPU 资源情况,否则将不会对其进行调度。

示例如下:

apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu-example namespace: example spec: hard: requests.cpu: 2 requests.memory: 2Gi limits.cpu: 3 limits.memory: 4Gi

如果将此 yaml 文件应用于 example 命名空间下, 则将设置如下要求:

所有 Pod 中的容器必须对 CPU 和 memory 设置 requests 和 limits 。所有 CPU requests 总和不能超过 2 cores 。所有 CPU limits 总和不能超过 3 cores。所有 memory requests 总和不能超过 2 GiB。所有 memory limits 总和不能超过 4GiB。

假设我们已经将 1.9 cores CPU 分配给了该命名空间下的 pods, 现在需要分配 200m(0.2 cores) CPU requests 给一个新的 pod,那么该pod将不会被调度并且一直保持 pending 状态。

pod requests and limits

示例如下:

kind: Deployment apiVersion: extensions/v1beta1 metadata: name: redis labels: name: redis-deployment app: example-voting-app spec: replicas: 1 selector: matchLabels: name: redis role: redisdb app: example-voting-app template: spec: containers: – name: redis image: redis:5.0.3-alpine resources: limits: memory: 600Mi cpu: 1 requests: memory: 300Mi cpu: 500m – name: busybox image: busybox:1.28 resources: limits: memory: 200Mi cpu: 300m requests: memory: 100Mi cpu: 100m

假设有一个 4 cores 16GB 的 Kubernetes 集群节点在运行, 从下图我们可以获取很多信息:

该 pod 中运行 2 个容器, 分别为 redis 和 busybox , 且各自对资源进行了限制。

Pod 的 memory requests 为 400 MiB 且 CPU requests 为 600 millicores。 所以首先需要一个具有足够可用资源的节点来调度 Pod。

2. Redis 容器的 CPU 占比将为 512, busybox 容器的占比为102。 因为 Kubernetes 始终为每一个 CPU core 分配 1024 的配比, 因此:

redis: 1024/0.5core≈5121024 / 0.5core \approx512 busybox: 1024/0.1cores≈1021024 / 0.1cores \approx 102

3. Redis 容器将被 OOM killed 。如果该容器尝试分配超过 600MB 的内存,这很可能会都导致 Pod 启动失败。

4. Redis 使用 CPU 将会受限。如果 Redis 容器尝试每 100ms 内 使用超过 100m 的 CPU 的话(示例节点是 4 cores, 所以每 100ms 将会有 400m CPU 处于可用状态 ), 将会导致服务性能下降。

5. Busybox 容器将被 OOM killed 。如果该容器尝试分配超过 200MB 的内存,这很可能会都导致 Pod 启动失败。

6. Busybox 使用 CPU 将会受限。如果该容器尝试每 100ms 内 使用超过 30m 的 CPU 的话,将会导致服务性能下降。

为了发现潜在的问题,我们需要将节点和 Pod 的资源消耗情况进行监控和分析。

节点 CPU 和 Memory 使用情况。即使所用容器资源消耗都在限制之下,但是如果 Kubernetes 节点内存爆满, 内存压力也会导致容器发生 OOM 而被终止, CPU压力将限制进程并影响性能,并不会使容器终止。
节点磁盘空间。如果节点磁盘爆满,Kubernetes 将尝试驱逐其上的 Pod 进行空间释放。
每个容器使用的CPU配额百分比。监视Pod CPU使用率可能会导致错误。Kubernetes限制是针对每个容器而不是每个 Pod。
每个容器的内存使用情况。可以将此值和容器限制值相关联。但不要使用Pod内存使用量。示例中的 Pod 可以使用300MiB 的 RAM,低于 Pod 的有效限制(400MiB),但是如果Redis容器使用 100MiB,而 busybox 容器使用 200MiB,则该Pod将失败。
集群中节点资源分配百分比。可以将其表示为总可用资源中各物理节点分配的资源所占百分比。告警阈值为(n-1)/ n * 100,其中n是节点数。超过此阈值,万一节点发生故障,则将无法在其余节点中重新分配工作负载。

合理选择 requests 和 limits

在工作中使用了一段时间的 Kubernetes 集群后,发现合理设置 requests 和 limits 对应用程序和集群性能至关重要。

理想情况下,应用程序应该持续准确地使用请求(requests)的资源量。但现实往往不可预估,容器对资源的使用从来都不是经常性的或可预测的。一般可以考虑在求值上下浮动25%视为运行良好情况。如果资源使用量远低于设置的请求量,则资源存在极大浪费。如果资源使用量比请求量很多,则存在应用程序和节点性能下降风险。

关于限制(limits), 没有一个标准答案,需要大家在工作中不断尝试去摸索,找出适合自己业务的最佳点。因为其取决于应用程序的性质,需求模型,对错误的容忍度以及许多其他因素。

总结

对工作负载进行容器资源限制,包括 limits 和 releases 至关重要, 器对服务和节点性能影响非常大。如何设置这两个值,应根据不同业务类型,并配合如上所讲的监控进行动态调配,以寻求一个合理值。设置名称空间配额将强制名称空间中的所有工作负载在每个容器中都必须设置requests和limits, 否则 Pod 将无法进行调配。

    THE END
    喜欢就支持一下吧
    点赞9 分享
    评论 抢沙发
    头像
    欢迎您留下宝贵的见解!
    提交
    头像

    昵称

    取消
    昵称表情代码图片

      暂无评论内容