すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:ack-kube-queueを使用したジョブキューの管理

最終更新日:Dec 17, 2024

ack-kube-queueは、KubernetesでAI、機械学習、バッチワークロードを管理するように設計されています。 これにより、システム管理者はジョブキュー管理をカスタマイズし、キューの柔軟性を向上できます。 クォータシステムと統合されたack-kube-queueは、ワークロードとリソースクォータの管理を自動化および最適化して、Kubernetesクラスターでのリソース使用率を最大化します。 このトピックでは、ack-kube-queueをインストールして使用する方法について説明します。

前提条件

クラウドネイティブAIスイートが有効化されました

制限事項

Kubernetesバージョンが1.18.aliyun.1以降のContainer Service for Kubernetes (ACK) Proクラスターのみがサポートされています。

ack-kube-queueのインストール

このセクションでは、2つのシナリオでack-kube-queueをインストールする方法について説明します。

シナリオ1: クラウドネイティブAIスイートがインストールされていない

  1. ACK コンソールにログインします。 左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、管理するクラスターの名前をクリックします。 左側のウィンドウで、[アプリケーション] > [クラウドネイティブAIスイート] を選択します。

  3. クラウドネイティブAI Suiteページの下部で、[デプロイ] をクリックします。

  4. [スケジューリング] セクションで、[キューキュー] を選択します。 [インタラクティブモード] セクションで、[アリーナ] を選択します。 ページの下部で、[クラウドネイティブAIスイートのデプロイ] をクリックします。

シナリオ2: クラウドネイティブAIスイートがインストールされている

  1. ACK コンソールにログインします。 左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、管理するクラスターの名前をクリックします。 左側のウィンドウで、[アプリケーション] > [クラウドネイティブAIスイート] を選択します。

  3. ack-arenaack-kube-queueをインストールします。

    • [クラウドネイティブAI Suite] ページで、[ack-arena] を見つけ、[操作] 列の [デプロイ] をクリックします。 [パラメーター] パネルで、[OK] をクリックします。

    • Cloud-native AI Suiteページで、ack-kube-queueを見つけ、[操作] 列の [デプロイ] をクリックします。 表示されるメッセージで、[確認] をクリックします。

    ack-arenaack-kube-queueをインストールすると、[コンポーネント] セクションの [ステータス] 列にデプロイ済みが表示されます。

サポートされるジョブタイプ

ack-kube-queueは、TensorFlowジョブ、PyTorchジョブ、MPIジョブ、Argoワークフロー、Rayジョブ、Sparkアプリケーション、およびKubernetesネイティブジョブをサポートします。

制限事項

  • TensorFlowジョブ、PyTorchジョブ、およびMPIジョブをキューに送信するには、ack-arenaが提供するオペレーターを使用する必要があります。

  • Kubernetesネイティブジョブをキューに送信するには、Kubernetesバージョンのクラスターが1.22以降であることを確認します。

  • MPIジョブをキューに送信するには、アリーナを使用します。

  • Argoワークフローのみをキューに送信できます。 Argoワークフローのステップをキューに送信することはできません。 次のアノテーションを追加して、Argoワークフローによって要求されたリソースを宣言できます。

    ```
     annotations:
       kube-queue/min-resources: |
         cpu: 5
         memory: 5G
    ```

さまざまな種類のジョブをキューに送信する

デフォルトでは、ack-kube-queueはTensorFlowジョブとPyTorchジョブをサポートしています。 ack-kube-queueでサポートされているジョブタイプは、必要に応じて変更できます。

v0.4.0より前のバージョン

各ジョブタイプのkubeキュー機能は、個々の配置によって制御されます。 拡張セクションのレプリケートされたポッドの数を0に設定して、kube-queue機能を無効にすることができます。

バージョンv0.4.0以降

Argoワークフローを除き、他のジョブタイプのkube-queue機能はjob-Extensionsによって制御されます。 コマンドの -- enabled-extensionsの値を変更することで、ジョブの種類の機能を有効または無効にできます。 異なるジョブタイプはコンマ (,) で区切ります。 コマンドで使用するジョブの種類と名前を次の表に示します。

TfJob

tfjob

Pytorchjob

pytorchjob

ジョブ

job

SparkApplication

sparkapp

RayJob

rayjob

RayJob(v1alpha 1)

rayjobv1alpha1

MpiJob

mpiv1

TensorFlowジョブ、PyTorchジョブ、およびMPIジョブをキューに送信する

ジョブにscheduling.x-k8s.io/suspend="true" の注釈を追加する必要があります。 次のサンプルコードは、TensorFlowジョブをキューに送信します。

apiVersion: "kubeflow.org/v1"
kind: "TFJob"
metadata:
  name: "job1"
  annotations:
    scheduling.x-k8s.io/suspend: "true"
spec:
  ...

Kubernetesネイティブジョブをキューに送信する

ジョブの中断フィールドをtrueに設定する必要があります。 次のサンプルコードは、Kubernetesネイティブジョブをキューに送信します。

apiVersion: batch/v1
kind: Job
metadata:
  generateName: pi-
spec:
  suspend: true
  completions: 1
  parallelism: 1
  template:
    spec:
      schedulerName: default-scheduler
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["sleep",  "3s"]
        resources:
          requests:
            cpu: 100m
          limits:
            cpu: 100m
      restartPolicy: Never

上の例では、CPUリソースの100mを要求するジョブがキューに入れられます。 ジョブがデキューされると、ジョブの中断フィールドの値はfalseに変更され、ジョブはクラスタコンポーネントによって実行されます。

Argoワークフローをキューに送信する

説明

コンソールのマーケットプレイスからack-workflowをインストールします。

ワークフローを送信するときに、kube-queue-suspendというカスタム中断テンプレートをArgoワークフローに追加し、中断フィールドをtrueに設定する必要があります。 例:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: $example-name
spec:
  suspend: true # Set this field to true.
  entrypoint: $example-entrypoint
  templates:
  # Add a suspend template named kube-queue-suspend.
  - name: kube-queue-suspend
    suspend: {}
  - name: $example-entrypoint
  ...

Sparkアプリケーションをキューに送信する

説明

コンソールのマーケットプレイスからack-spark-operatorをインストールします。

Sparkアプリケーションにscheduling.x-k8s.io/suspend="true" アノテーションを追加する必要があります。

apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
  generateName: spark-pi-suspend-
  namespace: spark-operator
  annotations:
    scheduling.x-k8s.io/suspend: "true"
spec:
  type: Scala
  mode: cluster
  image: registry-cn-beijing.ack.aliyuncs.com/acs/spark:v3.1.1
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.1.1.jar
  sparkVersion: "3.1.1"
  driver:
    cores: 1
    coreLimit: "1200m"
    memory: "512m"
    serviceAccount: ack-spark-operator3.0-spark
  executor:
    cores: 1
    instances: 1
    memory: "512m"

キューにRayジョブを送信する

説明

コンソールのマーケットプレイスからack-kuberay-operatorをインストールします。

Rayジョブをキューに送信するときは、Rayジョブのspec.suspendフィールドをtrueに設定する必要があります。

apiVersion: ray.io/v1
kind: RayJob
metadata:
  name: rayjob-sample
spec:
  entrypoint: python /home/ray/samples/sample_code.py
  runtimeEnvYAML: |
    pip:
      - requests==2.26.0
      - pendulum==2.1.2
    env_vars:
      counter_name: "test_counter"

  # Suspend specifies whether the RayJob controller should create a RayCluster instance.
  # If a job is applied with the suspend field set to true, the RayCluster will not be created and we will wait for the transition to false.
  # If the RayCluster is already created, it will be deleted. In the case of transition to false, a new RayCluste rwill be created.
  suspend: true

  rayClusterSpec:
    rayVersion: '2.9.0' # should match the Ray version in the image of the containers
    headGroupSpec:
      rayStartParams:
        dashboard-host: '0.0.0.0'
      template:
        spec:
          containers:
            - name: ray-head
              image: rayproject/ray:2.9.0
              ports:
                - containerPort: 6379
                  name: gcs-server
                - containerPort: 8265 # Ray dashboard
                  name: dashboard
                - containerPort: 10001
                  name: client
              resources:
                limits:
                  cpu: "1"
                requests:
                  cpu: "200m"
              volumeMounts:
                - mountPath: /home/ray/samples
                  name: code-sample
          volumes:
            # You set volumes at the Pod level, then mount them into containers inside that Pod
            - name: code-sample
              configMap:
                # Provide the name of the ConfigMap you want to mount.
                name: ray-job-code-sample
                # An array of keys from the ConfigMap to create as files
                items:
                  - key: sample_code.py
                    path: sample_code.py
    workerGroupSpecs:
      - replicas: 1
        minReplicas: 1
        maxReplicas: 5
        groupName: small-group
        rayStartParams: {}
        template:
          spec:
            containers:
              - name: ray-worker # must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name',  or '123-abc'
                image: rayproject/ray:2.9.0
                lifecycle:
                  preStop:
                    exec:
                      command: [ "/bin/sh","-c","ray stop" ]
                resources:
                  limits:
                    cpu: "1"
                  requests:
                    cpu: "200m"

クォータシステムのタイプを変更する

クラスターが複数のユーザーによって使用されている場合、ユーザーがリソースを求めて競合する場合に備えて、各ユーザーに一定量のリソースを割り当てる必要があります。 従来の方法では、Kubernetesリソースクォータを使用して、各ユーザーに固定量のリソースを割り当てます。 しかしながら、リソース要件は、ユーザ間で異なり得る。 デフォルトでは、ack-kube-queueはエラスティッククォータを使用して、全体的なリソース使用率を改善します。 Kubernetesリソースのクォータを使用する場合は、次の手順を実行します。elasticクォータの詳細については、「ElasticQuota」をご参照ください。

  1. 次のコマンドを実行して、エラスティッククォータからKubernetesリソースクォータに切り替えます。

    kubectl edit deploy kube-queue-controller -nkube-queue
  2. から環境変数を変更します。elasticquotaresourcequota.

    env:
    - name: QueueGroupPlugin
        value: resourcequota
  3. 設定を変更した後、ファイルを保存します。 kube-queue-controllerが起動するのを待ちます。 次に、Kubernetesリソースクォータを使用してリソースを割り当てます。

ブロックキューの有効化

ack-kube-queueは、kube-schedulerと同じように、デフォルトでラウンドロビン方式でジョブを処理します。 キュー内のジョブは、リソースを1つずつ要求します。 リソースの取得に失敗したジョブは、スケジュール不可キューに送信され、次のジョブスケジューリングを待機します。 リソース需要が低い多数のジョブがクラスタに含まれている場合、これらのジョブをラウンドロビン方式で処理するには時間がかかります。 このシナリオでは、リソース需要が高いジョブは、リソース需要が低いジョブがリソースを求めて競合するため、保留になる可能性が高くなります。 この問題を回避するために、ack-kube-queueはブロッキングキューを提供します。 この機能を有効にすると、キュー内の最初のジョブのみがスケジュールされます。 このようにして、より多くのリソースをリソース需要の高いジョブにスケジュールできます。

手順

  1. ACKコンソールにログインします。 左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、管理するクラスターの名前をクリックします。 左側のウィンドウで、[ワークロード] > [デプロイ] を選択します。

  3. Namespaceパラメーターをkube-queueに設定します。 次に、kube-queue-controller[操作] 列で [編集] をクリックします。

  4. [環境変数] の右側にある [追加] をクリックし、次の環境変数を追加します。

    パラメーター

    Type

    Custom

    変数キー

    厳密な優先順位

    値 /ValueFrom

    true

  5. ページの右側にある [更新] をクリックします。 [OK] メッセージで、[確認] をクリックします。

厳格な優先スケジューリングの有効化

既定では、リソースの取得に失敗したジョブはスケジュール不可キューに送信され、次のジョブスケジューリングを待機します。 ジョブが完了すると、ジョブによって占有されたリソースが解放されます。 これらのジョブはまだスケジュール不可キューにあるため、これらのリソースは優先度の高いジョブにスケジュールされません。 その結果、アイドルリソースは優先度の低いジョブにスケジューリングされる。 アイドルリソースを優先度の高いジョブに好ましくスケジュールするために、ack-kube-queueは厳格な優先度スケジューリング機能を提供します。 ジョブがリソースを解放した後、システムは、キュー内の最初のジョブである最も優先度の高いジョブにリソースをスケジュールしようとします。 これにより、アイドルリソースが優先度の高いジョブにスケジューリングされることが好ましい。

説明

低優先度のジョブは、アイドルリソースが高優先度のジョブを満たすには不十分である場合、アイドルリソースを求めて競合することができる。

手順

  1. ACKコンソールにログインします。 左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、管理するクラスターの名前をクリックします。 左側のウィンドウで、[ワークロード] > [デプロイ] を選択します。

  3. Namespaceパラメーターをkube-queueに設定します。 次に、kube-queue-controller[操作] 列で [編集] をクリックします。

  4. [環境変数] の右側にある [追加] をクリックし、次の環境変数を追加します。

    パラメーター

    Type

    Custom

    変数キー

    厳密な一貫性

    値 /ValueFrom

    true

  5. ページの右側にある [更新] をクリックします。 [OK] メッセージで、[確認] をクリックします。

リソースクォータのユースケース

ElasticQuota

  1. 次のYAMLテンプレートを使用してElasticQuotaTreeを作成します。

    YAMLコンテンツの表示

    apiVersion: v1
    kind: List
    metadata:
      resourceVersion: ""
      selfLink: ""
    items:
      - apiVersion: scheduling.sigs.k8s.io/v1beta1
        kind: ElasticQuotaTree
        metadata:
          name: elasticquotatree
          namespace: kube-system
        spec:
          root: # The resource quota of the root is the total resource quota of the quota group. The maximum amount of resources of the root must be equal to or larger than the sum of the maximum resources of all leaves below the root. 
            name: root
            namespaces: []
            max:
              cpu: "4"
              memory: 4Gi
              nvidia.com/gpu: "64"
              aliyun.com/gpu-mem: "32"
            min:
              cpu: "0"
              memory: 0M
              nvidia.com/gpu: "0"
              aliyun.com/gpu-mem: "0"
            children: # You can specify multiple leaves. In most cases, each leaf corresponds to one namespace. 
              - name: root.defaultQuotaGroup
                namespaces:
                  - default
                max:
                  cpu: "4"
                  memory: 4Gi
                  nvidia.com/gpu: "64"
                  aliyun.com/gpu-mem: "16"
                min:
                  cpu: "0"
                  memory: 0M
                  nvidia.com/gpu: "0"
                  aliyun.com/gpu-mem: "0"
                children: null
  2. 次のコマンドを実行して、ElasticQuotaTreeが作成されているかどうかを確認します。

    kubectl get elasticquotatree -A

    期待される出力:

    NAMESPACE     NAME               AGE
    kube-system   elasticquotatree   7s

    ElasticQuotaTreeが作成されます。

  3. ジョブを作成します。

    説明
    • ack-kube-queueのジョブキュー管理機能をテストするには、作成するジョブのリソースクォータを、ジョブが要求するリソースの合計量よりも少なくする必要があります。

    • テストを簡単にするために、TensorFlowジョブで使用されるTensorFlowイメージはBusyBoxイメージに置き換えられます。 各コンテナは30秒間スリープし、トレーニングプロセスをシミュレートします。

    1. 次のYAMLテンプレートを使用して、2つのTensorFlowジョブを作成します。

      YAMLコンテンツの表示

      apiVersion: "kubeflow.org/v1"
      kind: "TFJob"
      metadata:
        name: "job1"
        annotations:
          scheduling.x-k8s.io/suspend: "true"
      spec:
        tfReplicaSpecs:
          PS:
            replicas: 1
            restartPolicy: Never
            template:
              spec:
                containers:
                  - name: tensorflow
                    image: busybox
                    command:
                      - /bin/sh
                      - -c
                      - --
                    args:
                      - "sleep 30s"
                    resources:
                      requests:
                        cpu: 1
                        memory: 1Gi
                      limits:
                        cpu: 1
                        memory: 1Gi
      
          Worker:
            replicas: 2
            restartPolicy: Never
            template:
              spec:
                containers:
                  - name: tensorflow
                    image: busybox
                    command:
                      - /bin/sh
                      - -c
                      - --
                    args:
                      - "sleep 30s"
                    resources:
                      requests:
                        cpu: 1
                        memory: 1Gi
                      limits:
                        cpu: 1
                        memory: 1Gi
      --
      apiVersion: "kubeflow.org/v1"
      kind: "TFJob"
      metadata:
        name: "job2"
        annotations:
          scheduling.x-k8s.io/suspend: "true"
      spec:
        tfReplicaSpecs:
          PS:
            replicas: 1
            restartPolicy: Never
            template:
              spec:
                containers:
                  - name: tensorflow
                    image: busybox
                    command:
                      - /bin/sh
                      - -c
                      - --
                    args:
                      - "sleep 30s"
                    resources:
                      requests:
                        cpu: 1
                        memory: 1Gi
                      limits:
                        cpu: 1
                        memory: 1Gi
      
          Worker:
            replicas: 2
            restartPolicy: Never
            template:
              spec:
                containers:
                  - name: tensorflow
                    image: busybox
                    command:
                      - /bin/sh
                      - -c
                      - --
                    args:
                      - "sleep 30s"
                    resources:
                      requests:
                        cpu: 1
                        memory: 1Gi
                      limits:
                        cpu: 1
                        memory: 1Gi
    2. ジョブを送信した後、ジョブのステータスを照会します。

      1. 次のコマンドを実行して、ジョブのステータスを照会します。

        kubectl get tfjob

        期待される出力:

        NAME   STATE     AGE
        job1   Running   3s
        job2   Queuing   2s

        出力は、job1がRunning状態で、job2がQueuing状態であることを示します。 これは、各TensorFlowジョブが3つのvCoresを要求するが、作成したElasticQuotaTreeが4つのvCoresをデフォルトの名前空間に割り当てるためです。 したがって、2つのTensorFlowジョブを同時に実行することはできません。

      2. しばらく待ってから、次のコマンドを再度実行します。

        kubectl get tfjob

        期待される出力:

        NAME   STATE       AGE
        job1   Succeeded   77s
        job2   Running     77s

        出力は、job1が完了したことを示します。 job1が完了すると、job2の実行が開始されます。 出力は、ack-kube-queueが期待どおりにジョブキューを管理することを示します。

ResourceQuota

  1. 次のYAMLテンプレートを使用してResourceQuotaを作成します。

    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: default
    spec:
      hard:
        cpu: "4"
        memory: 4Gi
  2. 次のコマンドを実行して、ResourceQuotaが作成されているかどうかを確認します。

    kubectl get resourcequota default -o wide

    期待される出力:

    NAME      AGE   REQUEST                   LIMIT
    default   76s   cpu: 0/4, memory: 0/4Gi

    ResourceQuotaが作成されます。

  3. 次のYAMLテンプレートを使用して、2つのTensorFlowジョブを作成します。

    YAMLコンテンツの表示

    apiVersion: "kubeflow.org/v1"
    kind: "TFJob"
    metadata:
      name: "job1"
      annotations:
        scheduling.x-k8s.io/suspend: "true"
    spec:
      tfReplicaSpecs:
        PS:
          replicas: 1
          restartPolicy: Never
          template:
            spec:
              containers:
                - name: tensorflow
                  image: busybox:stable
                  command:
                    - /bin/sh
                    - -c
                    - --
                  args:
                    - "sleep 30s"
                  resources:
                    requests:
                      cpu: 1
                      memory: 1Gi
                    limits:
                      cpu: 1
                      memory: 1Gi
    
        Worker:
          replicas: 2
          restartPolicy: Never
          template:
            spec:
              containers:
                - name: tensorflow
                  image: busybox:stable
                  command:
                    - /bin/sh
                    - -c
                    - --
                  args:
                    - "sleep 30s"
                  resources:
                    requests:
                      cpu: 1
                      memory: 1Gi
                    limits:
                      cpu: 1
                      memory: 1Gi
    --
    apiVersion: "kubeflow.org/v1"
    kind: "TFJob"
    metadata:
      name: "job2"
      annotations:
        scheduling.x-k8s.io/suspend: "true"
    spec:
      tfReplicaSpecs:
        PS:
          replicas: 1
          restartPolicy: Never
          template:
            spec:
              containers:
                - name: tensorflow
                  image: busybox:stable
                  command:
                    - /bin/sh
                    - -c
                    - --
                  args:
                    - "sleep 30s"
                  resources:
                    requests:
                      cpu: 1
                      memory: 1Gi
                    limits:
                      cpu: 1
                      memory: 1Gi
    
        Worker:
          replicas: 2
          restartPolicy: Never
          template:
            spec:
              containers:
                - name: tensorflow
                  image: busybox:stable
                  command:
                    - /bin/sh
                    - -c
                    - --
                  args:
                    - "sleep 30s"
                  resources:
                    requests:
                      cpu: 1
                      memory: 1Gi
                    limits:
                      cpu: 1
                      memory: 1Gi
  4. 2つのジョブが送信されたら、次のコマンドを実行してジョブのステータスを照会します。

    kubectl get tfjob
    NAME   STATE     AGE
    job1   Running   5s
    job2   Queuing   5s
    
    kubectl get pods
    NAME            READY   STATUS    RESTARTS   AGE
    job1-ps-0       1/1     Running   0          8s
    job1-worker-0   1/1     Running   0          8s
    job1-worker-1   1/1     Running   0          8s

    job1はRunning状態で、job2はQueuing状態です。 結果は、ack-kube-queueが期待どおりにジョブキューを管理することを示しています。 これは、各TensorFlowジョブが3つのvCoreを要求するためです。パラメーターサーバーポッドに1つのvCore、2つのワーカーポッドに1つのvCoreです。 ただし、作成したElasticQuotaTreeは、4つのvCoresをデフォルトの名前空間に割り当てます。 したがって、2つのTensorFlowジョブを同時に実行することはできません。

  5. しばらく待ってから、次のコマンドを実行します。

    kubectl get tfjob
    NAME   STATE       AGE
    job1   Succeeded   77s
    job2   Running     77s
    
    kubectl get pods
    NAME            READY   STATUS      RESTARTS   AGE
    job1-worker-0   0/1     Completed   0          54s
    job1-worker-1   0/1     Completed   0          54s
    job2-ps-0       1/1     Running     0          22s
    job2-worker-0   1/1     Running     0          22s
    job2-worker-1   1/1     Running     0          21s

    job1が完了しました。 job2は、job1の完了後に実行を開始します。 結果は、ack-kube-queueが期待どおりにジョブキューを管理することを示しています。

    同時にデキューできるジョブ数の制限

    アプリケーションが自動的にスケーリングされ得るシナリオでは、アプリケーションによって必要とされるリソースの量は、予測不可能であり得る。 この場合、デキューされるジョブの数を制限できます。 キュー内のジョブ数を制限するには、ElasticQuotaTreeでkube-queue/max-jobsリソースを定義する必要があります。 制限が設定された後、クォータ以下でデキューできるキューユニットの数は、キュー内のジョブの最大数にオーバーコミット率を掛けたものを超えることはできません。 例:

    YAMLコンテンツの表示

    apiVersion: v1
    kind: List
    metadata:
      resourceVersion: ""
      selfLink: ""
    items:
      - apiVersion: scheduling.sigs.k8s.io/v1beta1
        kind: ElasticQuotaTree
        metadata:
          name: elasticquotatree
          namespace: kube-system
        spec:
          root: # The resource quota of the root is the total resource quota of the quota group. The maximum amount of resources of the root must be equal to or larger than the sum of the maximum resources of all leaves below the root. 
            name: root
            namespaces: []
            max:
              kube-queue/max-jobs: 10
              cpu: "4"
              memory: 4Gi
              nvidia.com/gpu: "64"
              aliyun.com/gpu-mem: "32"
            min:
              cpu: "0"
              memory: 0M
              nvidia.com/gpu: "0"
              aliyun.com/gpu-mem: "0"
            children: # You can specify multiple leaves. In most cases, each leaf corresponds to one namespace. 
              - name: root.defaultQuotaGroup
                namespaces:
                  - default
                max:
              		kube-queue/max-jobs: 10
                  cpu: "4"
                  memory: 4Gi
                  nvidia.com/gpu: "64"
                  aliyun.com/gpu-mem: "16"
                min:
                  cpu: "0"
                  memory: 0M
                  nvidia.com/gpu: "0"
                  aliyun.com/gpu-mem: "0"
                children: null