首页 容器计算服务 操作指南 调度 使用 Capacity Scheduling

使用 Capacity Scheduling

更新时间: 2023-10-27 17:23:18

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

资源配额 (ResourceQuota)

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

在使用资源配额时:

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

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

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

  • 如果使用 ResourceQuota 配置了 cpu 和 memory,创建的 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. 创建 Namespace

  2. kubectl create namespace test
  3. 创建 ResourceQuota,限制 Namespace 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

  6. kubectl -n test describe resourcequota test-quota
    Name:         test-quota
    Namespace:    test
    Resource      Used  Hard
    --------      ----  ----
    limits.cpu    0     4
    requests.cpu  0     4
  7. 创建 4 个 Pod,每个 Pod 使用 1000m cpu。

  8. 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: busybox:latest
            imagePullPolicy: IfNotPresent
            name: test
            command:
            - sleep
            - "360000000"
            resources:
              limits:
                cpu: "1"
    EOF
  9. 查看Pod创建结果,可以看到4个Pod都处于Running状态。

  10. 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
  11. 查看 ResourceQuota 状态,可以看到 ResourceQuota test-quota 的 Used 等于 Hard。

  12. kubectl -n test describe resourcequota
    Name:         test-quota
    Namespace:    test
    Resource      Used  Hard
    --------      ----  ----
    limits.cpu    4     4
    requests.cpu  4     4
  13. 再尝试扩容一个新的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=