使用Capacity Scheduling

ACS通过Kubernetes原生的ResourceQuota机制限制和控制命名空间中的资源使用。通过ResourceQuota,您可以限制和监控命名空间中各种资源的使用情况,如CPU、内存、存储、副本数和服务数。这样就可以防止某个命名空间中的资源被其他应用程序过度占用,从而保证应用程序的稳定性和可靠性。

资源配额(ResourceQuota)

您可以在ACS集群中使用Kubernetes原生的资源配额机制来控制每个命名空间的资源消耗总量。通过定义ResourceQuota对象,可以先在命名空间中某种资源类型的总量上限,包括CPU、内存和扩展资源等。当在命名空间下创建Pod、Services等K8s资源时,Kubernetes的配额系统会跟踪集群的资源使用情况,并保证资源总用量不超过命名空间下ResourceQuota定义的硬性(Hard)限额。

在使用资源配额时:

  • 每个团队或者应用使用独立的命名空间。

  • 集群管理员针对不同的命名空间创建一个或者多个ResourceQuota对象。

  • 如果用量超过了ResourceQuota的硬性限额时,后续新建的资源会被拒绝。

  • 如果使用ResourceQuota配置了CPU和内存,创建的Pod必须要设置request和limit,否则将会拒绝创建。

说明
  • 对于其他资源(例如扩展资源):无需为该资源设置request和limit。提示:可使用LimitRanger准入控制器来为没有设置计算资源需求的Pod设置默认值。

  • ResourceQuota对象的名称必须是合法的DNS子域名

  • 配额的修改不会影响已经创建的资源使用对象。

启用资源配额

通过ACS控制台创建的Kubernetes集群已经默认开启了资源配额机制。您只需要在新增的命名空间下创建ResourceQuota对象,这个命名空间而言就开启了资源配额。

支持的资源类型

ACS完全兼容Kubernetes原生资源配额机制,因此标准资源类型和扩展资源都可以通过ResourceQuota进行配置。

标准资源类型

资源名称

描述

limits.cpu

所有非终止状态的Pod,其CPU限额总量不能超过该值。

limits.memory

所有非终止状态的Pod,其内存限额总量不能超过该值。

requests.cpu

所有非终止状态的Pod,其CPU需求总量不能超过该值。

requests.memory

所有非终止状态的Pod,其内存需求总量不能超过该值。

hugepages-<size>

对于所有非终止状态的Pod,针对指定大小的HugePage请求总数不能超过此值。

cpu

requests.cpu相同。

memory

requests.memory相同。

扩展资源的资源配额

因为K8s不支持扩展资源超量分配(即limit>request),因此只需要配置前缀为requests.的配额项。

说明

有关更多详细信息,请参阅资源配额

示例

以下演示如何通过kubectl查看和创建ResourceQuota。

  1. 执行以下命令,创建命名空间test。

  2. kubectl create namespace test
  3. 创建ResourceQuota,限制命名空间test最多只能使用4000m CPU。

  4. cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: test-quota
      namespace: test
    spec:
      hard:
        requests.cpu: "4000m"
        limits.cpu: "4000m"
    EOF
  5. 执行以下命令,查看ResourceQuota。

    kubectl -n test describe resourcequota test-quota

    预期输出:

    Namespace:    test
    Resource      Used  Hard
    --------      ----  ----
    limits.cpu    0     4
    requests.cpu  0     4
  6. 创建4个Pod,每个Pod使用1000m cpu。

  7. cat << EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: test-app
      name: test-app
      namespace: test
    spec:
      replicas: 5
      selector:
        matchLabels:
          app: test-app
      template:
        metadata:
          labels:
            app: test-app
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2
            imagePullPolicy: IfNotPresent
            name: test
            command:
            - sleep
            - "360000000"
            resources:
              limits:
                cpu: "1"
    EOF
  8. 执行以下命令,查看Pod创建结果。

    kubectl -n test get pod

    预期输出:

    NAME                        READY   STATUS    RESTARTS   AGE
    test-app-5ddc68c994-jdv4m   1/1     Running   0          35s
    test-app-5ddc68c994-jhmtb   1/1     Running   0          35s
    test-app-5ddc68c994-mr8vq   1/1     Running   0          35s
    test-app-5ddc68c994-pjdfn   1/1     Running   0          35s

    可以看出4个Pod都处于Running状态。

  9. 执行以下命令,查看ResourceQuota状态。

    kubectl -n test describe resourcequota

    预期输出:

    Name:         test-quota
    Namespace:    test
    Resource      Used  Hard
    --------      ----  ----
    limits.cpu    4     4
    requests.cpu  4     4

    可以看到test-quota的Used资源量与Hard资源量相等。

  10. 再尝试扩容一个新的Pod,验证ResourceQuota的准入控制器拦截功能。

    1. 先尝试扩容一个新的Pod。

      kubectl -n test scale deploy test-app --replicas 5
    2. 查看对应的ReplicaSet,发现DESIRED是5,但CURRENT是4,证明有个Pod有异常。

      kubectl -n test get rs
      NAME                  DESIRED   CURRENT   READY   AGE
      test-app-5ddc68c994   5         4         4       3m10s
    3. 查看ReplicaSet的Event,可以发现新的Pod被ResourceQuota的准入控制器拦截了

      k -n test describe rs test-app-5ddc68c994
      Name:           test-app-5ddc68c994
      Namespace:      test
      Selector:       app=test-app,pod-template-hash=5ddc68c994
      Labels:         app=test-app
                      pod-template-hash=5ddc68c994
      Annotations:    deployment.kubernetes.io/desired-replicas: 5
                      deployment.kubernetes.io/max-replicas: 7
                      deployment.kubernetes.io/revision: 1
      Controlled By:  Deployment/test-app
      Replicas:       4 current / 5 desired
      Pods Status:    4 Running / 0 Waiting / 0 Succeeded / 0 Failed
      Pod Template:
        Labels:  app=test-app
                 pod-template-hash=5ddc68c994
        Containers:
         test:
          Image:      busybox:latest
          Port:       <none>
          Host Port:  <none>
          Command:
            sleep
            360000000
          Limits:
            cpu:        1
          Environment:  <none>
          Mounts:       <none>
        Volumes:        <none>
      Conditions:
        Type             Status  Reason
        ----             ------  ------
        ReplicaFailure   True    FailedCreate
      Events:
        Type     Reason            Age                    From                   Message
        ----     ------            ----                   ----                   -------
        Normal   SuccessfulCreate  3m18s                  replicaset-controller  Created pod: test-app-5ddc68c994-pjdfn
        Normal   SuccessfulCreate  3m18s                  replicaset-controller  Created pod: test-app-5ddc68c994-jdv4m
        Normal   SuccessfulCreate  3m18s                  replicaset-controller  Created pod: test-app-5ddc68c994-jhmtb
        Normal   SuccessfulCreate  3m18s                  replicaset-controller  Created pod: test-app-5ddc68c994-mr8vq
        Warning  FailedCreate      3m18s                  replicaset-controller  Error creating: pods "test-app-5ddc68c994-5s4ph" is forbidden: exceeded quota: test-quota, requested: limits.cpu=1,requests.cpu=1, used: limits.cpu=4,requests.cpu=4, limited: limits.cpu=4,requests.cpu=