K8S资源限制

一、ResourceQuota核心作用

1.1 资源公平性保障

在k8s集群中,多个团队或者项目可能共享同一个集群。如果没有资源限制,某个团队可能因误配置或恶意行为占用大量资源(如CPU、内存、存储)导致其他应用无法正常运行。ResourceQuota通过为每个命名空间设置资源上限,确保资源分配的公平性。

1.2 成本控制

在云环境中,资源使用直接关联费用。ResourceQuota可限制命名空间的资源消耗,避免因资源滥用导致成本超支。

1.3 防止资源枯竭

Kubernetes 节点资源有限,ResourceQuota 可防止以下问题:

  • 节点资源耗尽:例如,某命名空间创建大量 Pod,占用所有节点的 CPU 或内存。
  • 存储资源耗尽:例如,某应用创建过多持久卷(PVC),耗尽存储后端容量。
  • 对象数量爆炸:例如,某服务生成大量 ConfigMapSecret,影响 API Server 性能。

1.4 多租户支持

在 SaaS 或 PaaS 平台中,ResourceQuota 可为不同租户分配独立资源池,实现逻辑隔离。

二、ResourceQuota支持的资源类型

ResourceQuota 支持对以下四类资源进行限制:

2.1 计算资源(Compute Resources)

  • CPU:以核(Cores)或毫核(millicores)为单位,例如 1 或 1000m
  • 内存:以字节为单位,例如 1Gi512Mi
  • 临时存储(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 对象:如 IngressRoleRoleBinding 等。

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。
      • 存储:同上,但需注意存储后端是否支持动态扩展。

四、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 时:

  1. 自动填充默认值
    • 若容器未指定 requestslimits,LimitRange 会自动填充 defaultRequestdefault
  • 2. 强制校验规则
    • 若容器的 requestslimits 超出 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 最低为 200mlimits.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.

image

八. 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 资源不足时的具体行为

场景:节点内存耗尽

  1. kubelet 触发驱逐:当节点内存使用量超过 --eviction-hard 阈值(默认 memory.available<100Mi)时,kubelet 开始按 QoS 终止 Pod。
  2. 驱逐顺序
    • 优先终止 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
  • 驱逐顺序
    1. pod-1(BestEffort)。
    2. pod-2(Burstable,使用量超出请求量的 60%)。
    3. 若资源仍不足,继续按超用比例终止其他 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 的实际资源使用量。
Text
kubectl 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