十、K8s集群资源合理化分配
文章目录
- 十、K8s集群资源合理化分配
- 1、K8s 资源限制 ResourceQuota
- 1.1 什么是ResourceQuota?
- 1.2 ResourceQuota通常用于如下场景:
- 1.3 基于租户和团队的资源限制
- 1.4 基于命名空间的资源限制
- 2、K8s 资源限制 LimitRange
- 2.1 设置容器默认的资源配置
- 2.2 限制容器可以使用的最大和最小资源
- 2.3 限制存储使用的大小范围
- 3、K8s资源限制Qos
- 3.1 什么是QoS?
- 3.2 Qos级别
- 3.3 实现 QoS 为 Guaranteed 的 Pod
- 3.4 实现 QoS 为 Burstable 的 Pod
- 3.5 实现 QoS 为 BestEffort 的 Pod
- 4、常见问题
- 4.1 说一下ResourceQuota、LimitRange、QoS是什么?使用场景等
- 4.2 在生产环境中如何合理的资源限制?
- 4.3 如何配置每个服务的内存和CPU?
1、K8s 资源限制 ResourceQuota
1.1 什么是ResourceQuota?
ResourceQuota是一个K8s用于资源管理的对象,主要用于限制命名空间中的资源使用量。K8s管理员可以使用ResourceQuota控制命名空间中的资源使用量,确保资源的合理分配和使用,防止某个命名空间或用户过度消耗集群资源。
1.2 ResourceQuota通常用于如下场景:
- 限制资源使用:控制命名空间中可以使用的CPU、内存、存储等资源的总量。
- 限制对象数量:控制命名空间中可以创建的对象数量,如Pod、ConfigMap、Secret、Service等。
- 资源公平分配:确保资源在不同命名空间之间公平分配,避免资源争抢。
- 防止资源耗尽:防止某个命名空间或者用户过度消耗资源,导致其他应用无法获得所需的资源。
1.3 基于租户和团队的资源限制
在一个 Kubernetes 集群中,可能会有不同的团队或者不同的租户共同使用,此时可以针对不同的租户和不同的团队进行资源限制。
# 首先创建一个 Namespace 模拟租户:
[root@k8s-master01 ~]# kubectl create namespace customer# 配置租户的资源限制
[root@k8s-master01 ~]# vim customer-resourcequota.yaml
[root@k8s-master01 ~]# cat customer-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:name: customer-quotanamespace: customer
spec:hard:requests.cpu: "1" # 限制最高CPU请求数requests.memory: 2Gi # 限制最高内存的请求数limits.cpu: "2" # 限制最高CPU的limits上限limits.memory: 4Gi # 限制最高内存的limits上限pods: "50" # 限制最多启动Pod的个数persistentvolumeclaims: "10"requests.storage: 40Gi # PVC存储请求的总和services: "40"count/replicasets.apps: 1k# `count/<resource>.<group>`:用于非核心组的资源
# `count/<resource>`:用于核心组的资源[root@k8s-master01 ~]# kubectl create -f customer-resourcequota.yaml
# 查看限制详情
[root@k8s-master01 ~]# kubectl get resourcequota -n customer
NAME AGE REQUEST LIMIT
customer-quota 2m44s count/replicasets.apps: 0/1k, persistentvolumeclaims: 0/10, pods: 0/50, requests.cpu: 0/1, requests.memory: 0/2Gi, requests.storage: 0/40Gi, services: 0/40 limits.cpu: 0/2, limits.memory: 0/4Gi
# 创建一个 Deployment 测试
[root@k8s-master01 ~]# kubectl create deploy nginx --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable -n customer# 此时并没有 Pod 产生
[root@k8s-master01 ~]# kubectl get pod -n customer
No resources found in customer namespace.[root@k8s-master01 ~]# kubectl get rs -n customer
NAME DESIRED CURRENT READY AGE
nginx-67bfb68c7d 1 0 0 10m[root@k8s-master01 ~]# kubectl describe rs nginx -n customer
....Warning FailedCreate 4m34s (x8 over 9m59s) replicaset-controller (combined from similar events): Error creating: pods "nginx-67bfb68c7d-8m2gh" is forbidden: failed quota: customer-quota: must specify limits.cpu for: nginx; limits.memory for: nginx; requests.cpu for: nginx; requests.memory for: nginx
[root@k8s-master01 ~]# kubectl edit deploy nginx -n customer
....resources: requests:cpu: "1"memory: "512Mi"limits:cpu: "2"memory: "1024Mi"
....# pod已经成功创建
[root@k8s-master01 ~]# kubectl get pod -n customer
NAME READY STATUS RESTARTS AGE
nginx-7b95565d67-2kjlf 1/1 Running 0 85s# 查看目前空间资源使用情况
[root@k8s-master01 ~]# kubectl get resourcequota -n customer
NAME AGE REQUEST LIMIT
customer-quota 19m count/replicasets.apps: 2/1k, persistentvolumeclaims: 0/10, pods: 1/50, requests.cpu: 1/1, requests.memory: 512Mi/2Gi, requests.storage: 0/40Gi, services: 0/40 limits.cpu: 2/2, limits.memory: 1Gi/4Gi
和租户与团队一致,一个集群也可能同时存在多个环境和项目,此时也可以基于环境和项目进行资源限制。
1.4 基于命名空间的资源限制
通常情况下,出于稳定性和安全性考虑,应该对每个 Namespace 不受控制的资源进行限制,比如 Pod 和 ReplicaSet,防止异常创建导致集群故障。
[root@k8s-master01 ~]# cat default-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:name: default-quota
spec:hard:count/pods: "1000" # 限制pod数量count/replicasets.apps: 2k # 限制rs的数量
2、K8s 资源限制 LimitRange
2.1 设置容器默认的资源配置
在 Kubernetes 集群中部署任何的服务,都建议添加 resources 参数,也就是配置内存和 CPU资源的请求和限制。
如果不想给每个容器都手动添加资源配置,此时可以使用 limitRange 实现给每个容器自动添加资源配置。
比如默认给每个容器默认添加 cpu 请求 0.5 核,内存请求 256Mi,cpu 最大使用量 1 核,内存最大使用量 512Mi:
[root@k8s-master01 ~]# vim cpu-mem-limit-range.yaml
[root@k8s-master01 ~]# cat cpu-mem-limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:name: cpu-mem-limit-range
spec:limits:- default:cpu: 1memory: 512MidefaultRequest:cpu: 0.5memory: 256Mitype: Container[root@k8s-master01 ~]# kubectl create -f cpu-mem-limit-range.yaml
[root@k8s-master01 ~]# kubectl get limitRange
NAME CREATED AT
cpu-mem-limit-range 2025-06-25T12:07:26Z
# 创建一个没有资源配置的服务
[root@k8s-master01 ~]# kubectl create deploy redis --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5[root@k8s-master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-564b7bcf74-knw2l 1/1 Running 0 61s# 此时 Pod 里面的容器会被添加默认的 resources 配置(多个容器也会同时添加,已配置的参
数不会覆盖)
[root@k8s-master01 ~]# kubectl get po -oyaml | grep resources -A 6resources:limits:cpu: "1"memory: 512Mirequests:cpu: 500mmemory: 256Mi
2.2 限制容器可以使用的最大和最小资源
除了给容器配置默认的资源请求和限制,limitRange 还可以限制容器能使用的最大资源及可以配置的最小资源。
比如限制容器能配置最大内存是 1G,最大 CPU 是 800m,最小内存是 128M,最小 CPU 是10m:
[root@k8s-master01 ~]# vim min-max.yaml
[root@k8s-master01 ~]# cat min-max.yaml
apiVersion: v1
kind: LimitRange
metadata:name: min-max
spec:limits:- max:cpu: "800m"memory: "1Gi"min:cpu: "10m"memory: "128Mi"type: Container[root@k8s-master01 ~]# kubectl create -f min-max.yaml
[root@k8s-master01 ~]# kubectl get limitRange
NAME CREATED AT
cpu-mem-limit-range 2025-06-25T12:07:26Z
min-max 2025-06-25T12:16:06Z
[root@k8s-master01 ~]# kubectl edit deploy redis
....resources: limits:cpu: "2"memory: 2Girequests:cpu: 1mmemory: 1Mi
....# 但实际并没有更新
[root@k8s-master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-564b7bcf74-knw2l 1/1 Running 0 4m18s# 查看rs更新了
[root@k8s-master01 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
....
redis-74c66496 1 0 0 14s# 查看报错日志
[root@k8s-master01 ~]# kubectl describe rs redis-74c66496
....Warning FailedCreate 13s (x4 over 31s) replicaset-controller (combined from similar events): Error creating: pods "redis-74c66496-tvc77" is forbidden: [minimum cpu usage per Container is 10m, but request is 1m, minimum memory usage per Container is 128Mi, but request is 1Mi, maximum cpu usage per Container is 800m, but limit is 2, maximum memory usage per Container is 1Gi, but limit is 2Gi]
# 改回正常配置
[root@k8s-master01 ~]# kubectl edit deploy redis
....resources:limits:cpu: 600mmemory: 512Mirequests:cpu: 100mmemory: 128Mi
....# pod已经更新
[root@k8s-master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-675c6487c6-d9xxx 1/1 Running 0 61s
2.3 限制存储使用的大小范围
除了限制 CPU 和内存,也会限制 PVC 的大小范围,此时把 type 改为 PersistentVolumeClaim 即可。
# 比如限制每个 PVC 只能使用大于等于 1G,小于等于 3G 的空间:
[root@k8s-master01 ~]# vim storage-limit.yaml
[root@k8s-master01 ~]# cat storage-limit.yaml
apiVersion: v1
kind: LimitRange
metadata:name: storagelimits
spec:limits:- max:storage: 3Gimin:storage: 1Gitype: PersistentVolumeClaim[root@k8s-master01 ~]# kubectl create -f storage-limit.yaml
[root@k8s-master01 ~]# kubectl get limitRange
NAME CREATED AT
cpu-mem-limit-range 2025-06-25T12:07:26Z
min-max 2025-06-25T12:26:28Z
storagelimits 2025-06-25T12:52:33Z
# 创建一个申请 5G 的 PVC:
[root@k8s-master01 ~]# vim pvc-test.yaml
[root@k8s-master01 ~]# cat pvc-test.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc-test
spec:resources:requests:storage: 5GivolumeMode: FilesystemstorageClassName: local-storageaccessModes:- ReadWriteMany# 此时会有如下报错:
[root@k8s-master01 ~]# kubectl create -f pvc-test.yaml
Error from server (Forbidden): error when creating "pvc-test.yaml": persistentvolumeclaims "pvc-test" is forbidden: maximum storage usage per PersistentVolumeClaim is 3Gi, but request is 5Gi# 此时把 storage 改为限制范围内即可正常创建。
3、K8s资源限制Qos
3.1 什么是QoS?
Qos:Quality of Service,表示程序的服务质量。K8s集群中的每个Pod,都会有对应的Qos级别(在K8s中通过Resources参数即可配置QoS的级别),可用于决定Pod在资源紧张时的处理顺序,同时可以确保关键服务的稳定性和可靠性。
3.2 Qos级别
- Guaranteed:最高服务质量,当宿主机内存不够时,会先kill掉QoS为 BestEffort 和 Bursttable 的Pod,如果内存还是不够,才会kill掉 Guaranteed ,该级别Pod的资源占用量一般比较明确,即 requests 的 cpu 和 memory 和 limits 的 cpu 和 memory 配置一致。
- Bursttable:服务质量低于 Guaranteed ,当宿主机内存不够时,会先kill掉QoS为 BestEffort 的Pod,如果内存还是不够之后就会kill掉QoS级别为 Bursttable 的Pod,用来保证QoS质量为 Guaranteed 的Pod。该级别Pod一般知道最小资源使用量,但是当机器资源充足时,还是想尽可能的使用更多的资源,即 limits 字段的 cpu 和 memory 大于 requests 的 cpu 和 memory 的配置。
- BestEffort:尽量而为,当宿主机内存不够时,首先kill的就是Qos的Pod,用以保证 Bursttable 和 Guaranteed 级别的Pod正常运行。
3.3 实现 QoS 为 Guaranteed 的 Pod
Guaranteed 级别的 Pod 具有最高的优先级,Kubernetes 会确保这些 Pod 获得足够的资源,也就是 Kubernetes 调度器会确保这些 Pod 调度到能够提供所需资源的节点上。
配置 Guaranteed 级别的 Pod,需要满足如下条件:
- Pod 中的每个容器必须指定 limits.memory 和 requests.memory,并且两者需要相等
- Pod 中的每个容器必须指定 limits.cpu 和 requests.cpu,并且两者需要相等
# 修改配置
[root@k8s-master01 ~]# kubectl describe deploy redis
....resources:limits:cpu: 200mmemory: 512Mirequests:cpu: 200mmemory: 512Mi
....# 查看级别
[root@k8s-master01 ~]# kubectl describe po redis-765db65df4-rkbkg | grep "QoS Class"
QoS Class: Guaranteed
3.4 实现 QoS 为 Burstable 的 Pod
Burstable 级别的 Pod 具有中等优先级,Kubernetes 会尽量满足其资源请求,但在资源紧张时可能会被驱逐,Kubernetes 调度器会确保这些 Pod 调度到能够提供所需资源的节点上,如果节点上有额外的资源,这些 Pod 可以使用超过其请求的资源。
配置 Burstable 级别的 Pod,需要满足如下条件:
- Pod 不符合 Guaranteed 的配置要求
- Pod 中至少有一个容器配置了 requests.cpu 或 requests.memory
# 修改配置
[root@k8s-master01 ~]# kubectl describe deploy redis
....resources:limits:cpu: 200mmemory: 512Mirequests:cpu: 100mmemory: 512Mi
....# 查看级别
[root@k8s-master01 ~]# kubectl describe po redis-7c578fff48-7hnnx | grep "QoS Class"
QoS Class: Burstable
3.5 实现 QoS 为 BestEffort 的 Pod
BestEffort 级别的 Pod 是最低优先级,Kubernetes 不保证这些 Pod 获得任何资源,在资源紧张时,这些 Pod 最先被驱逐。同时 Kubernetes 调度器会尝试将这些 Pod 调度到任何节点上,但不保证节点上有足够的资源。
配置 BestEffort 级别的 Pod,不配置 resources 字段即可。
4、常见问题
4.1 说一下ResourceQuota、LimitRange、QoS是什么?使用场景等
ResourceQuota资源限制、LimitRange资源使用范围及默认值、QoS服务质量。ResourceQuota用于在多租户环境下为命名空间设置资源总量限制,避免某个租户过度使用资源。LimitRange可以确保命名空间内的Pod有合理的资源请求和限制范围,避免不合理的配置。QoS用于根据Pod的资源配置确定其在资源紧张的优先级,确保关键任务的Pod能够获得资源。
4.2 在生产环境中如何合理的资源限制?
每个空间都需要限制Pod和RS的资源,之后根据需要限制内存和CPU。
4.3 如何配置每个服务的内存和CPU?
根据实际情况配置、适当超分、重要服务采用 Guaranteed 级别的服务
此博客来源于:https://edu.51cto.com/lecturer/11062970.html