Kubernetes 资源配额使用指南

2021-01-12
4分钟阅读时长

资源配额控制应用的 CPU 或内存使用情况,防止资源被过量使用或被抢占。

当 Kubernetes 集群运行过一段时间或者在被开发者大量使用后,Kubernetes 资源(例如 CPU 和内存)的控制的问题就会显现出来。而在大多情况下只有集群出问题后,我们才会意识到资源控制的重要性。

Kubernetes 部署过程如果没有能充分考虑到将来的扩展性,资源类问题将会非常常见,此类问题与集群的管理和部署团队的经验有关。

如果不加以合理控制,一个暴力的应用或者开发者可能影响到共享该集群的所有业务,大家因此会相互埋怨、指责并保护性地抢占资源。这对于集群管理和开发人员都是非常难以处理的场景。

在 Kubernetes 环境中控制应用的计算资源使用有多种方式。大部分情况下,我们可以使用“资源控制”和“限制范围”。注意存储管理不在我们讨论范围之内,存储管理可以通过 持久卷 Persistent Volume 件,以实现针对不同的存储控制需求。

资源配额是一种控制 Kubernetes 计算资源的方法。本文告诉你如何使用该功能来管理开发人员行为并控制应用的资源使用。

什么是资源配额

简而言之,资源配额 提供了限制每个命名空间资源消耗的约束条件,它们只能在命名空间级别上应用,这意味着它们可以应用于计算资源,并限制命名空间内的对象数量。

Kubernetes资源配额通过 ResourceQuota 对象来为每个命名空间设置资源配额,对以下对象类型的 CPU 和内存进行限制:

  • 吊舱 Pod
  • 服务 Service
  • 机密信息 Secret
  • 持久卷断言 Persistent Volume Claim (PVC)
  • 配置映射 ConfigMap

Kubernetes 通过 requestlimit 两个参数对 CPU 和内存进行限制(参考 LimitRange 文档)。前者表示容器最小被保证资源,后者表示容器最大可用资源。实际上最大可用资源还受限于其它容器的实际使用情况。

下一张图片解释了配额中 requestlimit 的区别:

Requests and limits in Kubernetes resource quotas

下面我们就通过一个例子来说明如何设置资源配额来创建约束,将应用程序限制在某些资源上,它还展示了实现资源配额以获得对 Kubernetes 的控制的有用性。

准备环境

首先你需要一个 Kubernetes 环境。以下是我使用 Kubernetes 环境:

  • Minikube v1.14.2
  • Fedora 33 操作系统
  • 互联网接入

如果你想在 Linux 机器上通过 Minikube 搭建 Kubernetes 测试环境,可以参考 Bryant Son 的《Minikube 入门》 一文。Window 或者 macOS 用户可以参考这篇文章

设置资源配额

这里我们仅展示 CPU 配额设置步骤,配置内存配额或两者的组合与之类似。

在生产环境中,CPU 是最需要被控制的资源,尤其是在多应用的场景下特别需要注意防止某些应用消耗太多 CPU 而影响到其它应用。

首先我们创建一个命名空间,在其中设置 CPU 配额:

$ kubectl create namespace quota-test
namespace/quota-test created

准备 cpu-quota.yaml 文件,内容如下:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: test-cpu-quota
spec:
  hard:
    requests.cpu: "100m"  
    limits.cpu: "200m"

应用 CPU 配额到 Kubernetes 集群:

$ kubectl apply -f cpu-qouta.yaml
resourcequota/test-cpu-quota created

使用 kubectl describe 检查配额配置情况:

$ kubectl describe resourcequota/test-cpu-quota --namespace quota-test
Name:         test-cpu-quota
Namespace:    quota-test
Resource      Used  Hard
--------      ----  ----
limits.cpu    0     200m
requests.cpu  0     100m

Used resources 列中显示了当前情况,该列值会随着 吊舱 Pod 的部署而变化。

下面是我们来验证限额管理的场景。我们将在同一命名空间下部署三个不同的吊舱,为它们配置以不同的资源限制如下:

  • PodA:第一个被实例化,使用 50% 可用 CPU 资源
  • PodB:第二个被实例化,使用其余 50% 可用 CPU 资源
  • PodC:没有可用 CPU 资源,因此不会被部署

部署吊舱

PodA:

$ kubectl create -n quota-test -f - << EOF
apiVersion: v1
kind: Pod
metadata:
  name: poda
spec:
  containers:
  - name: quota-test
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Pod is Running ; sleep 5000']
    resources:
      requests:
        cpu: "50m"
      limits:
        cpu: "100m"
  restartPolicy: Never
EOF

部署 PodA 后,再次查看配额描述信息中的 Used CPU 信息:

$ kubectl describe resourcequota/test-cpu-quota --namespace quota-test
Name:         test-cpu-quota
Namespace:    quota-test
Resource      Used  Hard
--------      ----  ----
limits.cpu    100m  200m
requests.cpu  50m   100m

PodB:

$ kubectl create -n quota-test -f - << EOF
apiVersion: v1
kind: Pod
metadata:
  name: podb
spec:
  containers:
  - name: quota-test
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Pod is Running ; sleep 5000']
    resources:
      requests:
        cpu: "50m"
      limits:
        cpu: "100m"
  restartPolicy: Never
EOF

再次查看 CPU 资源使用,此时 PodB 启动后 CPU 限制已经达到上限:

$ kubectl describe resourcequota/test-cpu-quota --namespace quota-test
Name:         test-cpu-quota
Namespace:    quota-test
Resource      Used  Hard
--------      ----  ----
limits.cpu    200m  200m
requests.cpu  100m  100m

PodC:

试着创建 PodC,此时 CPU 配额已经被 PodA 和 PodB 用尽:

$ kubectl create -n quota-test -f - << EOF
apiVersion: v1
kind: Pod
metadata:
  name: podc
spec:
  containers:
  - name: quota-test
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Pod is Running ; sleep 5000']
    resources:
      requests:
        cpu: "5m"
      limits:
        cpu: "10m"
  restartPolicy: Never
EOF

正我们期望,第三个 Pod 无法被启动,配额限制了吊舱的创建:

Error from server (Forbidden): error when creating "STDIN": pods "podc" is forbidden: exceeded quota: test-cpu-quota, requested: limits.cpu=10m,requests.cpu=5m, used: limits.cpu=200m,requests.cpu=100m, limited: limits.cpu=200m,requests.cpu=100m

如我们的例子所示,定义合理的资源配额限制开发者行为对 Kubernetes 管理十分重要。

清理

删除刚才创建的命名空间 quota-test:

$ kubectl delete -n quota-test

规划资源配额

Kubernetes 中提供多种方式来控制资源的抢占和使用,合理的规划和配置配额、限制范围和其它原生参数对保持集群的稳定性十分必要。

你应该十分谨慎地控制计算资源的资源配额,特别是关键业务的生产应用环境。

在规划资源配额时,开发人员的参与很重要,需要他们预估并给出最合理的资源使用值。


via: https://opensource.com/article/20/12/kubernetes-resource-quotas

作者:Mike Calizo 选题:lujun9972 译者:larryzju 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出