当 Kubernetes 集群运行过一段时间或者在被开发者大量使用后,Kubernetes 资源(例如 CPU 和内存)的控制的问题就会显现出来。而在大多情况下只有集群出问题后,我们才会意识到资源控制的重要性。
Kubernetes 部署过程如果没有能充分考虑到将来的扩展性,资源类问题将会非常常见,此类问题与集群的管理和部署团队的经验有关。
如果不加以合理控制,一个暴力的应用或者开发者可能影响到共享该集群的所有业务,大家因此会相互埋怨、指责并保护性地抢占资源。这对于集群管理和开发人员都是非常难以处理的场景。
在 Kubernetes 环境中控制应用的计算资源使用有多种方式。大部分情况下,我们可以使用“资源控制”和“限制范围”。注意存储管理不在我们讨论范围之内,存储管理可以通过持久卷Persistent Volume 件,以实现针对不同的存储控制需求。
资源配额是一种控制 Kubernetes 计算资源的方法。本文告诉你如何使用该功能来管理开发人员行为并控制应用的资源使用。
什么是资源配额
简而言之,资源配额 提供了限制每个命名空间资源消耗的约束条件,它们只能在命名空间级别上应用,这意味着它们可以应用于计算资源,并限制命名空间内的对象数量。
Kubernetes资源配额通过 ResourceQuota 对象来为每个命名空间设置资源配额,对以下对象类型的 CPU 和内存进行限制:
- 吊舱Pod
- 服务Service
- 机密信息Secret
- 持久卷断言Persistent Volume Claim(PVC)
- 配置映射ConfigMap
Kubernetes 通过 request 和 limit 两个参数对 CPU 和内存进行限制(参考 LimitRange 文档)。前者表示容器最小被保证资源,后者表示容器最大可用资源。实际上最大可用资源还受限于其它容器的实际使用情况。
下一张图片解释了配额中 request 和 limit 的区别:
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 中提供多种方式来控制资源的抢占和使用,合理的规划和配置配额、限制范围和其它原生参数对保持集群的稳定性十分必要。
你应该十分谨慎地控制计算资源的资源配额,特别是关键业务的生产应用环境。
在规划资源配额时,开发人员的参与很重要,需要他们预估并给出最合理的资源使用值。