K8S资源限制及服务保障
K8S资源限制
一、ResourceQuota核心作用
1.1 资源公平性保障
在k8s集群中,多个团队或者项目可能共享同一个集群。如果没有资源限制,某个团队可能因误配置或恶意行为占用大量资源(如CPU、内存、存储)导致其他应用无法正常运行。ResourceQuota
通过为每个命名空间设置资源上限,确保资源分配的公平性。
1.2 成本控制
在云环境中,资源使用直接关联费用。ResourceQuota
可限制命名空间的资源消耗,避免因资源滥用导致成本超支。
1.3 防止资源枯竭
Kubernetes
节点资源有限,ResourceQuota
可防止以下问题:
- 节点资源耗尽:例如,某命名空间创建大量
Pod
,占用所有节点的 CPU 或内存。 - 存储资源耗尽:例如,某应用创建过多持久卷
(PVC)
,耗尽存储后端容量。 - 对象数量爆炸:例如,某服务生成大量
ConfigMap
或Secret
,影响 API Server 性能。
1.4 多租户支持
在 SaaS 或 PaaS 平台中,ResourceQuota 可为不同租户分配独立资源池,实现逻辑隔离。
二、ResourceQuota支持的资源类型
ResourceQuota 支持对以下四类资源进行限制:
2.1 计算资源(Compute Resources)
- CPU:以核(Cores)或毫核(millicores)为单位,例如
1
或1000m
。 - 内存:以字节为单位,例如
1Gi
、512Mi
。 - 临时存储(Ephemeral Storage):用于 Pod 临时目录的存储限制。
- 扩展资源(Extended Resources):如 GPU、FPGA 等自定义资源。
2.2 存储资源(Storage Resources)
- 持久卷声明(PVC)数量:限制命名空间内可创建的 PVC 总数。
- 存储类(StorageClass)限制:按存储类限制 PVC 的总容量或数量。
- 动态存储分配:限制每个存储类允许的动态存储总量。
2.3 对象数量(Object Counts)
- Pod:限制命名空间内可运行的 Pod 数量。
- Service:限制 Service 数量(包括 LoadBalancer 和 NodePort)。
- ConfigMap/Secret:限制配置对象数量。
- Deployment/StatefulSet/Job:限制控制器对象的数量。
- 其他 API 对象:如
Ingress
、Role
、RoleBinding
等。
2.4 服务质量(QoS)级别
- 资源配额按 QoS 划分:可为不同 QoS 级别(Guaranteed、Burstable、BestEffort)的 Pod 设置独立配额。
三、ResourceQuota的语法与配置
3.1 ResourceQuota的Yaml定义
以下是一个完整的 ResourceQuota 配置文件示例:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# cat team-a-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
# 计算资源
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
requests.ephemeral-storage: "50Gi"
limits.ephemeral-storage: "100Gi"
# 存储资源
persistentvolumeclaims: "10"
requests.storage: "1Ti"
gold.storageclass.storage.k8s.io/requests.storage: "500Gi"
# 对象数量
pods: "50"
services: "20"
services.loadbalancers: "5"
services.nodeports: "10"
configmaps: "100"
secrets: "50"
3.2 字段解析
spec.hard
:定义资源硬性限制,键值对形式。- 前缀规则:
requests.<resource>
:限制资源请求总量(如requests.cpu
)。limits.<resource>
:限制资源限制总量(如limits.memory
)。<storage-class-name>.<type>.storage.k8s.io/<resource>
:按存储类限制资源。
- 资源单位:
- CPU:
1
= 1 核,1000m
= 1 核。 - 内存:
1Gi
= 1024Mi,1Mi
= 1024Ki。 - 存储:同上,但需注意存储后端是否支持动态扩展。
- CPU:
- 前缀规则:
四、ResourceQuota使用方法
4.1 创建 ResourceQuota
步骤1:定义命名空间
kubectl create namespace team-a
步骤2:应用ResourceQuota
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl apply -f team-a-quota.yaml
resourcequota/team-a-quota created
步骤3:验证配额状态
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl describe resourcequota team-a-quota -n team-a
Name: team-a-quota
Namespace: team-a
Resource Used Hard
-------- ---- ----
configmaps 1 100
gold.storageclass.storage.k8s.io/requests.storage 0 500Gi
limits.cpu 0 20
limits.ephemeral-storage 0 100Gi
limits.memory 0 40Gi
persistentvolumeclaims 0 10
pods 0 50
requests.cpu 0 10
requests.ephemeral-storage 0 50Gi
requests.memory 0 20Gi
requests.storage 0 1Ti
secrets 1 50
services 0 20
services.loadbalancers 0 5
services.nodeports 0 10
4.2 配额生效逻辑
- 即时生效:创建或更新
ResourceQuota
后,所有新创建的 Pod 必须满足配额限制。 - 现有资源处理:若已有资源超出配额,后续操作(如扩容)将被拒绝,但现有资源不受影响。
4.3 配额冲突处理
若 Pod 的资源请求(requests
)或限制(limits
)超过配额,Kubernetes API Server 将返回错误:
Error from server (Forbidden): error when creating "pod.yaml": pods "example" is forbidden: exceeded quota: team-a-quota, requested: requests.cpu=2, used: requests.cpu=8, limited: requests.cpu=10
4.5 使用案例
4.5.1 基于租户和团队的资源限制
在一个k8s集群中,可能会有多个不同的团队或不同的租户共同使用,此时可以针对不同的租户和不同的团队进行资源限制。
首先创建两个namespace模拟两个租户:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl create ns customer1
namespace/customer1 created
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl create ns customer2
namespace/customer2 created
配置租户1 的资源限制:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# cat customer1-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: customer1-quota
namespace: customer1
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "50"
persistentvolumeclaims: "10"
requests.storage: 400Gi
services: "40"
count/replicasets.apps: 1k
配置租户2的资源限制:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# cat customer2-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: customer2-quota
namespace: customer2
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "50"
count/replicasets.apps: 1k
创建一个deployment测试:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl create deploy test-quota --image=registry.cn-beijing.aliyuncs.com/dotbalo/redis:7.2.5 -n customer1
deployment.apps/test-quota created
此时没有任何Pod产生,因为没有配置resources
添加资源限制:
resources:
requests:
cpu: "3"
memory: "10Mi"
limits:
cpu: "4"
memory: "1024Mi"
由于资源请求大于资源限制,所以也不会产生 Pod,此时可以查看 RS 的日志:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get rs -n customer1
NAME DESIRED CURRENT READY AGE
test-quota-58b44df65d 1 0 0 2m26s
test-quota-5bc9c9f97b 1 0 0 9s
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl describe rs -n customer1 test-quota-5bc9c9f97b
Name: test-quota-5bc9c9f97b
Namespace: customer1
Selector: app=test-quota,pod-template-hash=5bc9c9f97b
Labels: app=test-quota
pod-template-hash=5bc9c9f97b
Annotations: deployment.kubernetes.io/desired-replicas: 1
deployment.kubernetes.io/max-replicas: 2
deployment.kubernetes.io/revision: 2
Controlled By: Deployment/test-quota
Replicas: 0 current / 1 desired
Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=test-quota
pod-template-hash=5bc9c9f97b
Containers:
redis:
Image: registry.cn-beijing.aliyuncs.com/dotbalo/redis:7.2.5
Port: <none>
Host Port: <none>
Limits:
cpu: 4
memory: 1Gi
Requests:
cpu: 3
memory: 10Mi
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
ReplicaFailure True FailedCreate
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-hktrf" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-wt69t" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-l8qdb" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-fdc9t" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-b29l8" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-nsl6k" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-tsltf" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 16s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-mqlng" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 15s replicaset-controller Error creating: pods "test-quota-5bc9c9f97b-64tgn" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
Warning FailedCreate 6s (x3 over 14s) replicaset-controller (combined from similar events): Error creating: pods "test-quota-5bc9c9f97b-dnhvn" is forbidden: exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
4.5.2 基于命名空间的资源限制
通常情况下,出于稳定性和安全性考虑,应该对每个 Namespace 不受控制的资源进行限制,比如 Pod 和 ReplicaSet,防止异常创建导致集群故障。
模拟故障:对yaml文件配置错误,比如配置了内核参数,会导致生成大量状态为SysctlForbidden
的Pod产生,此时如果没有配置ResourceQuota,pod会无限制增大,最终导致集群发生不可逆错误。
# 模拟故障
securityContext:
sysctls:
- name: net.core.somaxconn
value: "1024"
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get pods -n customer1
NAME READY STATUS RESTARTS AGE
test-quota-6bf7688cf4-c272r 0/1 SysctlForbidden 0 0s
test-quota-6bf7688cf4-c9pdk 0/1 SysctlForbidden 0 5s
test-quota-6bf7688cf4-cd8dr 0/1 SysctlForbidden 0 3s
test-quota-6bf7688cf4-dr924 0/1 SysctlForbidden 0 0s
test-quota-6bf7688cf4-drqnq 0/1 SysctlForbidden 0 5s
test-quota-6bf7688cf4-f9wgh 0/1 SysctlForbidden 0 3s
test-quota-6bf7688cf4-hflbf 0/1 SysctlForbidden 0 4s
test-quota-6bf7688cf4-j6ldp 0/1 SysctlForbidden 0 0s
test-quota-6bf7688cf4-k4749 0/1 SysctlForbidden 0 3s
test-quota-6bf7688cf4-k4pfd 0/1 SysctlForbidden 0 4s
test-quota-6bf7688cf4-k5ghv 0/1 SysctlForbidden 0 2s
test-quota-6bf7688cf4-lbbbs 0/1 SysctlForbidden 0 5s
test-quota-6bf7688cf4-mfk87 0/1 SysctlForbidden 0 5s
test-quota-6bf7688cf4-n55wn 0/1 SysctlForbidden 0 2s
test-quota-6bf7688cf4-qrfxl 0/1 SysctlForbidden 0 4s
test-quota-6bf7688cf4-qs8qz 0/1 SysctlForbidden 0 1s
test-quota-6bf7688cf4-rlvkn 0/1 SysctlForbidden 0 2s
test-quota-6bf7688cf4-tbxbf 0/1 SysctlForbidden 0 2s
test-quota-6bf7688cf4-tdztv 0/1 SysctlForbidden 0 3s
test-quota-6bf7688cf4-tvmfl 0/1 SysctlForbidden 0 2s
test-quota-6bf7688cf4-v7zhp 0/1 SysctlForbidden 0 1s
test-quota-6bf7688cf4-wkj6k 0/1 SysctlForbidden 0 0s
test-quota-6bf7688cf4-wzzcj 0/1 SysctlForbidden 0 5s
test-quota-6bf7688cf4-xs7wb 0/1 SysctlForbidden 0 2s
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get pods -n customer1 |wc -l
80
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota#
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get pods -n customer1 |wc -l
88
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get pods -n customer1 |wc -l
91
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get pods -n customer1 |wc -l
94
此时可以给每个 Namespace 添加一个默认的资源限制:
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# cat default-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: default-quota
namespace: customer1
spec:
hard:
count/pods: "100"
count/replicasets.apps: 2k
此时再去修改deployment的securityContext,然后查看pod直接到100就不会在创建了
root@VM-26-130-ubuntu:/usr/local/src/k8s/resourcequota# kubectl get pods -n customer1 |wc -l
100
五、LimitRange
5.1 LimitRange 核心作用
5.1.1 强制资源分配规则
- 为没有指定资源请求(
requests
)或限制(limits
)的容器提供默认值。 - 限制单个容器或Pod的最小/最大资源使用量,避免资源浪费或过度占用。
5.1.2 防止资源分配不均匀
- 确保所有容器至少有最低资源保障(如
50m CPU
),防止低优先级任务因资源不足被驱逐。 - 防止单个容器独占节点资源(如限制最大内存为
4Gi
)。
5.1.3 统一资源管理
- 在团队协作中,强制统一资源分配策略,减少配置错误。
5.2. LimitRange 支持的资源类型
LimitRange 可针对以下三类对象设置资源规则:
对象类型 | 支持的资源类型 | 作用范围 |
---|---|---|
Container | CPU、内存、临时存储(Ephemeral Storage) | 容器级别的资源请求和限制 |
Pod | CPU、内存、临时存储 | Pod 内所有容器的资源总和 |
PersistentVolumeClaim | 存储容量(Storage) | PVC 的存储请求大小 |
5.3 LimitRange语法yu配置
5.3.1 LimitRange 的 YAML 定义
apiVersion: v1
kind: LimitRange
metadata:
name: example-limitrange
namespace: team-a
spec:
limits:
# 容器级别的资源限制
- type: Container
default:
cpu: "100m"
memory: "256Mi"
defaultRequest:
cpu: "50m"
memory: "128Mi"
max:
cpu: "2"
memory: "4Gi"
min:
cpu: "10m"
memory: "64Mi"
# Pod 级别的资源限制
- type: Pod
max:
cpu: "4"
memory: "8Gi"
# PVC 存储限制
- type: PersistentVolumeClaim
max:
storage: "100Gi"
min:
storage: "10Gi"
root@VM-26-130-ubuntu:/usr/local/src/k8s/limitrange# kubectl apply -f limitrange.yaml
limitrange/example-limitrange created
root@VM-26-130-ubuntu:/usr/local/src/k8s/limitrange#
root@VM-26-130-ubuntu:/usr/local/src/k8s/limitrange# kubectl get limitranges -n team-a
NAME CREATED AT
example-limitrange 2025-03-28T01:28:04Z
root@VM-26-130-ubuntu:/usr/local/src/k8s/limitrange# kubectl describe limitranges -n team-a example-limitrange
Name: example-limitrange
Namespace: team-a
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 10m 2 50m 100m -
Container memory 64Mi 4Gi 128Mi 256Mi -
Pod cpu - 4 - - -
Pod memory - 8Gi - - -
PersistentVolumeClaim storage 10Gi 100Gi - - -
5.3.1 字段解析
####### 容器级别(type: Container
)
字段 | 描述 |
---|---|
default | 未指定 limits 时,自动为容器设置 CPU/内存的限制值。 |
defaultRequest | 未指定 requests 时,自动为容器设置 CPU/内存的请求值。 |
max | 容器允许的最大资源量(limits 不可超过此值)。 |
min | 容器必须至少请求的资源量(requests 不可低于此值)。 |
####### Pod 级别(type: Pod
)
字段 | 描述 |
---|---|
max | Pod 内所有容器的 limits 总和不可超过此值。 |
####### PVC 级别(type: PersistentVolumeClaim
)
字段 | 描述 |
---|---|
max | PVC 的存储容量请求不可超过此值。 |
min | PVC 的存储容量请求不可低于此值。 |
5.4 资源分配逻辑
####### 当用户创建 Pod 时:
- 自动填充默认值:
- 若容器未指定
requests
或limits
,LimitRange 会自动填充defaultRequest
和default
。
- 若容器未指定
- 2. 强制校验规则:
- 若容器的
requests
或limits
超出min
/max
范围,Pod 创建会被拒绝。
- 若容器的
示例:未指定资源的 Pod
root@VM-26-130-ubuntu:/usr/local/src/k8s/limitrange# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: team-a
spec:
containers:
- name: nginx
image: nginx
应用后,容器的资源请求和限制会被自动填充:
root@VM-26-130-ubuntu:/usr/local/src/k8s/limitrange# kubectl get pod -n team-a test-pod -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"test-pod","namespace":"team-a"},"spec":{"containers":[{"image":"nginx","name":"nginx"}]}}
kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu, memory request for container
nginx; cpu, memory limit for container nginx'
tke.cloud.tencent.com/networks-status: |-
[{
"name": "tke-bridge",
"interface": "eth0",
"ips": [
"10.16.4.17"
],
"mac": "b6:9e:b9:dd:30:34",
"default": true,
"dns": {}
}]
creationTimestamp: "2025-03-28T01:32:55Z"
name: test-pod
namespace: team-a
resourceVersion: "5647733"
selfLink: /api/v1/namespaces/team-a/pods/test-pod
uid: 6fdf5742-4916-4cb5-831b-3ff53c1331d9
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: 100m
memory: 256Mi
requests:
cpu: 50m
memory: 128Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-m4qsd
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: 10.122.26.140
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: kube-api-access-m4qsd
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
六. LimitRange 与 ResourceQuota 的协同
6.1 协同逻辑
- LimitRange:确保单个 Pod/容器的资源请求合理。
- ResourceQuota:确保命名空间内所有 Pod 的资源总和不超过配额。
示例场景
若命名空间的 ResourceQuota 限制 requests.cpu=10
,而 LimitRange 设置容器 defaultRequest.cpu=1
,则最多只能运行 10 个默认配置的 Pod。
6.2 协同配置示例
ResourceQuota 定义
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
LimitRange 定义
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
- type: Container
default:
cpu: "500m"
memory: "1Gi"
defaultRequest:
cpu: "200m"
memory: "512Mi"
max:
cpu: "2"
memory: "4Gi"
协同效果
- 每个容器的
requests.cpu
最低为200m
,limits.cpu
最高为2
。 - 命名空间总
requests.cpu
不超过10
,最多运行10 / 0.2 = 50
个容器。
七. 实际应用场景与示例
7.1 场景 1:统一开发环境资源分配
需求:确保所有开发人员的测试 Pod 至少请求 0.5 CPU
,防止因资源不足被驱逐。
LimitRange 配置
spec:
limits:
- type: Container
min:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "1"
memory: "1Gi"
验证
若用户创建以下 Pod:
containers:
- name: app
image: my-app
resources:
requests:
cpu: "300m" # 低于 min.cpu=500m,会被拒绝
错误信息:
Error from server: Pod "test-pod" is invalid: spec.containers[0].resources.requests: Invalid value: "300m": must be greater than or equal to 500m.
6.2 场景 2:限制 GPU 资源使用
需求:仅允许特定容器使用 GPU,且最多使用 2
个 GPU。
LimitRange 配置
spec:
limits:
- type: Container
max:
nvidia.com/gpu: "2"
min:
nvidia.com/gpu: "0"
验证
若用户请求 3
个 GPU:
resources:
limits:
nvidia.com/gpu: "3"
错误信息:
Error from server: Pod "gpu-pod" is invalid: spec.containers[0].resources.limits: Invalid value: "3": must be less than or equal to 2.
八. Kubernetes中的QoS(服务质量)
8.1 核心作用
8.1.1 资源竞争时的优先级控制
当节点资源不足时(如内存耗尽),kubelet会根据QoS级别选择终止优先级最低的Pod,确保核心业务持续运行。例如:
- 关键服务(如数据库)应设置为高优先级(
Guaranteed
),避免被意外终止。 - 非关键任务(如日志收集)可设置为低优先级(
BestEffort
),允许在资源紧张时优先释放资源。
8.1.2 资源分配的公平性
QoS 通过资源请求(requests
)和限制(limits
)的配置,确保 Pod 获得承诺的资源量:
Guaranteed
:严格保证资源供应,适用于对稳定性要求高的应用。Burstable
:允许在资源充足时超出请求量,适用于弹性伸缩的业务。BestEffort
:无资源保证,适用于低优先级任务。
8.1.3 优化节点资源利用率
通过合理设置 QoS,节点可动态分配空闲资源,提高资源利用率。例如:
Burstable
Pod 可借用其他 Pod 未使用的资源。- 当节点资源不足时,优先回收低优先级 Pod 的资源。
8.2. QoS 的分类与定义
Kubernetes 将 Pod 的 QoS 分为三个级别,按优先级从高到低排序:
QoS 级别 | 定义条件 | 资源保证性 |
---|---|---|
Guaranteed | Pod 中所有容器均满足: 1. 为 CPU 和内存均设置 requests 和 limits 。2. 且 requests == limits 。 |
资源严格保证,优先级最高。 |
Burstable | Pod 中至少一个容器满足: 1. 设置了 requests 或 limits ,但未达到 Guaranteed 的条件。 |
资源部分保证,优先级次之。 |
BestEffort | Pod 中所有容器均未设置 requests 和 limits 。 |
无资源保证,优先级最低。 |
8.2.1 QoS 判定逻辑详解
示例 1:Guaranteed
containers:
- name: app
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "1"
memory: "1Gi"
- 条件满足:所有容器的
requests
和limits
相等,且同时指定了 CPU 和内存。
示例 2:Burstable
containers:
- name: app
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
- 条件满足:容器的
requests
和limits
不相等,但仍设置了资源请求。
示例 3:BestEffort
containers:
- name: app
resources: {}
- 条件满足:未设置任何
requests
和limits
。
8.3. QoS 的优先级与驱逐策略
8.3.1 驱逐优先级顺序
当节点资源不足时,Pod 的终止顺序为:
BestEffort → Burstable → Guaranteed
8.3.2 资源不足时的具体行为
场景:节点内存耗尽
- kubelet 触发驱逐:当节点内存使用量超过
--eviction-hard
阈值(默认memory.available<100Mi
)时,kubelet 开始按 QoS 终止 Pod。 - 驱逐顺序:
- 优先终止
BestEffort
Pod。 - 若仍不足,终止
Burstable
Pod(按资源使用量超出requests
的比例排序)。 - 最后终止
Guaranteed
Pod。
- 优先终止
示例:节点有 10 个 Pod
Pod 名称 | QoS 级别 | 内存使用量 | 内存请求量(requests) |
---|---|---|---|
pod-1 | BestEffort | 500Mi | 0 |
pod-2 | Burstable | 800Mi | 500Mi |
pod-3 | Guaranteed | 1Gi | 1Gi |
… | … | … | … |
- 驱逐顺序:
pod-1
(BestEffort)。pod-2
(Burstable,使用量超出请求量的 60%)。- 若资源仍不足,继续按超用比例终止其他 Burstable Pod。
8.4. QoS 的配置方法
8.4.1 配置原则
- Guaranteed:适用于核心服务(如数据库、API 网关)。
- Burstable:适用于弹性业务(如 Web 服务、批处理作业)。
- BestEffort:适用于非关键任务(如日志收集、临时测试)。
8.4.2 配置示例
示例 1:Guaranteed
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "1"
memory: "1Gi"
示例 2:Burstable
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "2Gi"
示例 3:BestEffort
apiVersion: v1
kind: Pod
metadata:
name: best-effort-pod
spec:
containers:
- name: nginx
image: nginx
8.5 QoS的监控与调试
8.5.1 查看 Pod 的 QoS 级别
kubectl get pod <pod-name> -o jsonpath='{.status.qosClass}'
输出示例:
Guaranteed
8.5.2 监控资源使用情况
- kubectl top:查看 Pod 的实际资源使用量。
Textkubectl top pod <pod-name>
- Prometheus + Grafana:监控节点的资源压力与 Pod 驱逐事件。
8.5.3 调试驱逐事件
kubectl get events --field-selector reason=Evicted
输出示例
LAST SEEN TYPE REASON OBJECT MESSAGE
5m Warning Evicted pod/web-xxx The node was low on resource: memory.
九. QoS 与 ResourceQuota/LimitRange 的协同
9.1 与 ResourceQuota 的协同
- ResourceQuota:限制命名空间的资源总量。
- QoS:决定单个 Pod 的资源优先级。
示例场景
- 目标:限制命名空间的 CPU 使用量,并确保核心服务不被驱逐。
# ResourceQuota 限制总量
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
spec:
hard:
requests.cpu: "10"
limits.cpu: "20"
# Pod 配置为 Guaranteed
containers:
- resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "1"
memory: "1Gi"
9.2 与 LimitRange 的协同
- LimitRange:设置默认的
requests
和limits
,影响 QoS 级别。 - QoS:基于 LimitRange 填充的值确定优先级。
# LimitRange 配置默认值
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- type: Container
default:
cpu: "100m"
memory: "256Mi"
defaultRequest:
cpu: "50m"
memory: "128Mi"
# Pod 未指定资源,自动填充后 QoS 为 Burstable
containers:
- name: app
image: nginx