第9章 クォータ

9.1. プロジェクトごとのリソースクォータ

ResourceQuota オブジェクトで定義される リソースクォータ は、プロジェクトごとにリソース消費量の総計を制限する制約を指定します。これは、タイプ別にプロジェクトで作成できるオブジェクトの数量を制限すると共に、そのプロジェクトのリソースが消費する可能性のあるコンピュートリソースおよびストレージの合計量を制限することができます。

本書では、リソースクォータの仕組みや、クラスター管理者がリソースクォータはプロジェクトごとにどのように設定し、管理できるか、および開発者やクラスター管理者がそれらをどのように表示できるかについて説明します。

9.1.1. クォータで管理されるリソース

以下では、クォータで管理できる一連のコンピュートリソースとオブジェクトタイプについて説明します。

注記

status.phase in (Failed、Succeeded) が true の場合、Pod は終了状態にあります。

表9.1 クォータで管理されるコンピュートリソース

リソース名説明

cpu

非終了状態のすべての Pod での CPU 要求の合計はこの値を超えることができません。cpu および requests.cpu は同じ値であり、相互に置き換え可能なものとして使用できます。

memory

非終了状態のすべての Pod でのメモリー要求の合計はこの値を超えることができません。memory および requests.memory は同じ値であり、相互に置き換え可能なものとして使用できます。

requests.cpu

非終了状態のすべての Pod での CPU 要求の合計はこの値を超えることができません。cpu および requests.cpu は同じ値であり、相互に置き換え可能なものとして使用できます。

requests.memory

非終了状態のすべての Pod でのメモリー要求の合計はこの値を超えることができません。memory および requests.memory は同じ値であり、相互に置き換え可能なものとして使用できます。

limits.cpu

非終了状態のすべての Pod での CPU 制限の合計はこの値を超えることができません。

limits.memory

非終了状態のすべての Pod でのメモリー制限の合計はこの値を超えることができません。

表9.2 クォータで管理されるストレージリソース

リソース名説明

requests.storage

任意の状態のすべての永続ボリューム要求 (PVC) でのストレージ要求の合計は、この値を超えることができません。

persistentvolumeclaims

プロジェクトに存在できる永続ボリューム要求 (PVC) の合計数です。

<storage-class-name>.storageclass.storage.k8s.io/requests.storage

一致するストレージクラスを持つ、任意の状態のすべての永続ボリューム要求 (PVC) でのストレージ要求の合計はこの値を超えることができません。

<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims

プロジェクトに存在できる、一致するストレージクラスを持つ Persistent Volume Claim (永続ボリューム要求、PVC) の合計数です。

ephemeral-storage

非終了状態のすべての Pod におけるローカルの一時ストレージ要求の合計は、この値を超えることができません。ephemeral-storage および requests.ephemeral-storage は同じ値であり、相互に置き換え可能なものとして使用できます。

requests.ephemeral-storage

非終了状態のすべての Pod における一時ストレージ要求の合計は、この値を超えることができません。ephemeral-storage および requests.ephemeral-storage は同じ値であり、相互に置き換え可能なものとして使用できます。

limits.ephemeral-storage

非終了状態のすべての Pod における一時ストレージ制限の合計は、この値を超えることができません。

表9.3 クォータで管理されるオブジェクト数

リソース名説明

pods

プロジェクトに存在できる非終了状態の Pod の合計数です。

replicationcontrollers

プロジェクトに存在できる ReplicationController の合計数です。

resourcequotas

プロジェクトに存在できるリソースクォータの合計数です。

services

プロジェクトに存在できるサービスの合計数です。

services.loadbalancers

プロジェクトに存在できるタイプ LoadBalancer のサービスの合計数です。

services.nodeports

プロジェクトに存在できるタイプ NodePort のサービスの合計数です。

secrets

プロジェクトに存在できるシークレットの合計数です。

configmaps

プロジェクトに存在できる ConfigMap オブジェクトの合計数です。

persistentvolumeclaims

プロジェクトに存在できる永続ボリューム要求 (PVC) の合計数です。

openshift.io/imagestreams

プロジェクトに存在できるイメージストリームの合計数です。

9.1.2. クォータのスコープ

各クォータには スコープ のセットが関連付けられます。クォータは、列挙されたスコープの交差部分に一致する場合にのみリソースの使用状況を測定します。

スコープをクォータに追加すると、クォータが適用されるリソースのセットを制限できます。許可されるセット以外のリソースを設定すると、検証エラーが発生します。

スコープ

説明

BestEffort

cpu または memory のいずれかについてのサービスの QoS (Quality of Service) が Best Effort の Pod に一致します。

NotBestEffort

cpu および memory についてのサービスの QoS (Quality of Service) が Best Effort ではない Pod に一致します。

BestEffort スコープは、以下のリソースに制限するようにクォータを制限します。

  • pods

NotBestEffort スコープは、以下のリソースを追跡するようにクォータを制限します。

  • pods
  • memory
  • requests.memory
  • limits.memory
  • cpu
  • requests.cpu
  • limits.cpu

9.1.3. クォータの実施

プロジェクトのリソースクォータが最初に作成されると、プロジェクトは、更新された使用状況の統計が計算されるまでクォータ制約の違反を引き起こす可能性のある新規リソースの作成機能を制限します。

クォータが作成され、使用状況の統計が更新されると、プロジェクトは新規コンテンツの作成を許可します。リソースを作成または変更する場合、クォータの使用量はリソースの作成または変更要求があるとすぐに増分します。

リソースを削除する場合、クォータの使用量は、プロジェクトのクォータ統計の次回の完全な再計算時に減分されます。設定可能な時間を指定して、クォータ使用量の統計値を現在確認されるシステム値まで下げるのに必要な時間を決定します。

プロジェクト変更がクォータ使用制限を超える場合、サーバーはそのアクションを拒否し、クォータ制約を違反していること、およびシステムで現在確認される使用量の統計値を示す適切なエラーメッセージがユーザーに返されます。

9.1.4. 要求 vs 制限

コンピュートリソースの割り当て時に、各コンテナーは CPU、メモリー、一時ストレージのそれぞれに要求値と制限値を指定できます。クォータはこれらの値のいずれも制限できます。

クォータに requests.cpu または requests.memory の値が指定されている場合、すべての着信コンテナーがそれらのリソースを明示的に要求することが求められます。クォータに limits.cpu または limits.memory の値が指定されている場合、すべての着信コンテナーがそれらのリソースの明示的な制限を指定することが求められます。

9.1.5. リソースクォータ定義の例

core-object-counts.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: core-object-counts
spec:
  hard:
    configmaps: "10" 1
    persistentvolumeclaims: "4" 2
    replicationcontrollers: "20" 3
    secrets: "10" 4
    services: "10" 5
    services.loadbalancers: "2" 6

1
プロジェクトに存在できる ConfigMap オブジェクトの合計数です。
2
プロジェクトに存在できる永続ボリューム要求 (PVC) の合計数です。
3
プロジェクトに存在できるレプリケーションコントローラーの合計数です。
4
プロジェクトに存在できるシークレットの合計数です。
5
プロジェクトに存在できるサービスの合計数です。
6
プロジェクトに存在できるタイプ LoadBalancer のサービスの合計数です。

openshift-object-counts.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: openshift-object-counts
spec:
  hard:
    openshift.io/imagestreams: "10" 1

1
プロジェクトに存在できるイメージストリームの合計数です。

compute-resources.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources
spec:
  hard:
    pods: "4" 1
    requests.cpu: "1" 2
    requests.memory: 1Gi 3
    limits.cpu: "2" 4
    limits.memory: 2Gi 5

1
プロジェクトに存在できる非終了状態の Pod の合計数です。
2
非終了状態のすべての Pod において、CPU 要求の合計は 1 コアを超えることができません。
3
非終了状態のすべての Pod において、メモリー要求の合計は 1 Gi を超えることができません。
4
非終了状態のすべての Pod において、CPU 制限の合計は 2 コアを超えることができません。
5
非終了状態のすべての Pod において、メモリー制限の合計は 2 Gi を超えることができません。

besteffort.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: besteffort
spec:
  hard:
    pods: "1" 1
  scopes:
  - BestEffort 2

1
プロジェクトに存在できるサービスの QoS (Quality of Service) が BestEffort の非終了状態の Pod の合計数です。
2
クォータを、メモリーまたは CPU のいずれかのサービスの QoS (Quality of Service) が BestEffort の一致する Pod のみに制限します。

compute-resources-long-running.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources-long-running
spec:
  hard:
    pods: "4" 1
    limits.cpu: "4" 2
    limits.memory: "2Gi" 3
  scopes:
  - NotTerminating 4

1
非終了状態の Pod の合計数です。
2
非終了状態のすべての Pod において、CPU 制限の合計はこの値を超えることができません。
3
非終了状態のすべての Pod において、メモリー制限の合計はこの値を超えることができません。
4
クォータを spec.activeDeadlineSecondsnil に設定されている一致する Pod のみに制限します。ビルド Pod は、RestartNever ポリシーが適用されない限り NotTerminating になります。

compute-resources-time-bound.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources-time-bound
spec:
  hard:
    pods: "2" 1
    limits.cpu: "1" 2
    limits.memory: "1Gi" 3
  scopes:
  - Terminating 4

1
終了状態の Pod の合計数です。
2
終了状態のすべての Pod において、CPU 制限の合計はこの値を超えることができません。
3
終了状態のすべての Pod において、メモリー制限の合計はこの値を超えることができません。
4
クォータを spec.activeDeadlineSeconds >=0 に設定されている一致する Pod のみに制限します。たとえば、このクォータはビルド Pod またはデプロイヤー Pod に影響を与えますが、web サーバーまたはデータベースなどの長時間実行されない Pod には影響を与えません。

storage-consumption.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-consumption
spec:
  hard:
    persistentvolumeclaims: "10" 1
    requests.storage: "50Gi" 2
    gold.storageclass.storage.k8s.io/requests.storage: "10Gi" 3
    silver.storageclass.storage.k8s.io/requests.storage: "20Gi" 4
    silver.storageclass.storage.k8s.io/persistentvolumeclaims: "5" 5
    bronze.storageclass.storage.k8s.io/requests.storage: "0" 6
    bronze.storageclass.storage.k8s.io/persistentvolumeclaims: "0" 7
    requests.ephemeral-storage: 2Gi 8
    limits.ephemeral-storage: 4Gi 9

1
プロジェクト内の永続ボリューム要求 (PVC) の合計数です。
2
プロジェクトのすべての永続ボリューム要求 (PVC) において、要求されるストレージの合計はこの値を超えることができません。
3
プロジェクトのすべての永続ボリューム要求 (PVC) において、gold ストレージクラスで要求されるストレージの合計はこの値を超えることができません。
4
プロジェクトのすべての永続ボリューム要求 (PVC) において、silver ストレージクラスで要求されるストレージの合計はこの値を超えることができません。
5
プロジェクトのすべての永続ボリューム要求 (PVC) において、silver ストレージクラスの要求の合計数はこの値を超えることができません。
6
プロジェクトのすべての永続ボリューム要求 (PVC) において、bronze ストレージクラスで要求されるストレージの合計はこの値を超えることができません。これが 0 に設定される場合、bronze ストレージクラスはストレージを要求できないことを意味します。
7
プロジェクトのすべての永続ボリューム要求 (PVC) において、bronze ストレージクラスで要求されるストレージの合計はこの値を超えることができません。これが 0 に設定される場合は、bronze ストレージクラスでは要求を作成できないことを意味します。
8
非終了状態のすべての Pod において、一時ストレージ要求の合計は 2 Gi を超えることができません。
9
非終了状態のすべての Pod において、一時ストレージ制限の合計は 4 Gi を超えることができません。

9.1.6. クォータの作成

特定のプロジェクトでリソースの使用を制限するためにクォータを作成することができます。

手順

  1. ファイルにクォータを定義します。
  2. クォータを作成し、これをプロジェクトに適用するためにファイルを使用します。

    $ oc create -f <file> [-n <project_name>]

    以下に例を示します。

    $ oc create -f core-object-counts.yaml -n demoproject

9.1.6.1. オブジェクトカウントクォータの作成

BuildConfig および DeploymentConfig オブジェクトなどの、OpenShift Container Platform の標準的な namespace を使用しているリソースタイプのすべてにオブジェクトカウントクォータを作成できます。オブジェクトクォータカウントは、定義されたクォータをすべての標準的な namespace を使用しているリソースタイプに設定します。

リソースクォータを使用する際に、オブジェクトは作成時クォータに基づいてチャージされます。以下のクォータのタイプはリソースが使い切られることから保護するのに役立ちます。クォータは、プロジェクト内に余分なリソースが十分にある場合にのみ作成できます。

手順

リソースのオブジェクトカウントクォータを設定するには、以下を実行します。

  1. 以下のコマンドを実行します。

    $ oc create quota <name> \
        --hard=count/<resource>.<group>=<quota>,count/<resource>.<group>=<quota> 1
    1
    <resource> 変数はリソースの名前であり、<group> は API グループです (該当する場合)。リソースおよびそれらの関連付けられた API グループのリストに oc api-resources コマンドを使用します。

    以下に例を示します。

    $ oc create quota test \
        --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4

    出力例

    resourcequota "test" created

    この例では、リスト表示されたリソースをクラスター内の各プロジェクトのハード制限に制限します。

  2. クォータが作成されていることを確認します。

    $ oc describe quota test

    出力例

    Name:                         test
    Namespace:                    quota
    Resource                      Used  Hard
    --------                      ----  ----
    count/deployments.extensions  0     2
    count/pods                    0     3
    count/replicasets.extensions  0     4
    count/secrets                 0     4

9.1.6.2. 拡張リソースのリソースクォータの設定

リソースのオーバーコミットは拡張リソースには許可されません。そのため、クォータで同じ拡張リソースについて requests および limits を指定する必要があります。現時点で、接頭辞 requests. のあるクォータ項目のみが拡張リソースに許可されます。以下は、GPU リソース nvidia.com/gpu のリソースクォータを設定する方法についてのシナリオ例です。

手順

  1. クラスター内のノードで利用可能な GPU の数を判別します。以下に例を示します。

    # oc describe node ip-172-31-27-209.us-west-2.compute.internal | egrep 'Capacity|Allocatable|gpu'

    出力例

                        openshift.com/gpu-accelerator=true
    Capacity:
     nvidia.com/gpu:  2
    Allocatable:
     nvidia.com/gpu:  2
      nvidia.com/gpu  0           0

    この例では、2 つの GPU が利用可能です。

  2. ResourceQuota オブジェクトを作成して、namespace nvidia にクォータを設定します。この例では、クォータは 1 です。

    出力例

    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: gpu-quota
      namespace: nvidia
    spec:
      hard:
        requests.nvidia.com/gpu: 1

  3. クォータを作成します。

    # oc create -f gpu-quota.yaml

    出力例

    resourcequota/gpu-quota created

  4. namespace に正しいクォータが設定されていることを確認します。

    # oc describe quota gpu-quota -n nvidia

    出力例

    Name:                    gpu-quota
    Namespace:               nvidia
    Resource                 Used  Hard
    --------                 ----  ----
    requests.nvidia.com/gpu  0     1

  5. 単一 GPU を要求する Pod を定義します。以下の定義ファイルのサンプルの名前は gpu-pod.yaml です。

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: gpu-pod-
      namespace: nvidia
    spec:
      restartPolicy: OnFailure
      containers:
      - name: rhel7-gpu-pod
        image: rhel7
        env:
          - name: NVIDIA_VISIBLE_DEVICES
            value: all
          - name: NVIDIA_DRIVER_CAPABILITIES
            value: "compute,utility"
          - name: NVIDIA_REQUIRE_CUDA
            value: "cuda>=5.0"
        command: ["sleep"]
        args: ["infinity"]
        resources:
          limits:
            nvidia.com/gpu: 1
  6. Pod を作成します。

    # oc create -f gpu-pod.yaml
  7. Pod が実行されていることを確認します。

    # oc get pods

    出力例

    NAME              READY     STATUS      RESTARTS   AGE
    gpu-pod-s46h7     1/1       Running     0          1m

  8. クォータ Used のカウンターが正しいことを確認します。

    # oc describe quota gpu-quota -n nvidia

    出力例

    Name:                    gpu-quota
    Namespace:               nvidia
    Resource                 Used  Hard
    --------                 ----  ----
    requests.nvidia.com/gpu  1     1

  9. nvidia namespace で 2 番目の GPU Pod の作成を試行します。2 つの GPU があるので、これをノード上で実行することは可能です。

    # oc create -f gpu-pod.yaml

    出力例

    Error from server (Forbidden): error when creating "gpu-pod.yaml": pods "gpu-pod-f7z2w" is forbidden: exceeded quota: gpu-quota, requested: requests.nvidia.com/gpu=1, used: requests.nvidia.com/gpu=1, limited: requests.nvidia.com/gpu=1

    クォータが 1 GPU であり、この Pod がそのクォータを超える 2 つ目の GPU の割り当てを試行したため、Forbidden エラーメッセージが表示されることが予想されます。

9.1.7. クォータの表示

Web コンソールでプロジェクトの Quota ページに移動し、プロジェクトのクォータで定義されるハード制限に関連する使用状況の統計を表示できます。

CLI を使用してクォータの詳細を表示することもできます。

手順

  1. プロジェクトで定義されるクォータのリストを取得します。たとえば、demoproject というプロジェクトの場合、以下を実行します。

    $ oc get quota -n demoproject

    出力例

    NAME                           AGE    REQUEST                                                                                                      LIMIT
    besteffort                     4s     pods: 1/2
    compute-resources-time-bound   10m    pods: 0/2                                                                                                    limits.cpu: 0/1, limits.memory: 0/1Gi
    core-object-counts             109s   configmaps: 2/10, persistentvolumeclaims: 1/4, replicationcontrollers: 1/20, secrets: 9/10, services: 2/10

  2. 関連するクォータについて記述します。たとえば、core-object-counts クォータの場合、以下を実行します。

    $ oc describe quota core-object-counts -n demoproject

    出力例

    Name:			core-object-counts
    Namespace:		demoproject
    Resource		Used	Hard
    --------		----	----
    configmaps		3	10
    persistentvolumeclaims	0	4
    replicationcontrollers	3	20
    secrets			9	10
    services		2	10

9.1.8. 明示的なリソースクォータの設定

プロジェクト要求テンプレートで明示的なリソースクォータを設定し、新規プロジェクトに特定のリソースクォータを適用します。

前提条件

  • cluster-admin ロールを持つユーザーとしてのクラスターへのアクセスがあること。
  • OpenShift CLI (oc) がインストールされている。

手順

  1. プロジェクト要求テンプレートにリソースクォータ定義を追加します。

    • プロジェクト要求テンプレートがクラスターに存在しない場合:

      1. ブートストラッププロジェクトテンプレートを作成し、これを template.yaml というファイルに出力します。

        $ oc adm create-bootstrap-project-template -o yaml > template.yaml
      2. リソースクォータの定義を template.yaml に追加します。以下の例では、storage-consumption という名前のリソースクォータを定義します。テンプレートの parameters: セクションの前に定義を追加する必要があります。

        - apiVersion: v1
          kind: ResourceQuota
          metadata:
            name: storage-consumption
            namespace: ${PROJECT_NAME}
          spec:
            hard:
              persistentvolumeclaims: "10" 1
              requests.storage: "50Gi" 2
              gold.storageclass.storage.k8s.io/requests.storage: "10Gi" 3
              silver.storageclass.storage.k8s.io/requests.storage: "20Gi" 4
              silver.storageclass.storage.k8s.io/persistentvolumeclaims: "5" 5
              bronze.storageclass.storage.k8s.io/requests.storage: "0" 6
              bronze.storageclass.storage.k8s.io/persistentvolumeclaims: "0" 7
        1
        プロジェクト内の永続ボリューム要求 (PVC) の合計数です。
        2
        プロジェクトのすべての永続ボリューム要求 (PVC) において、要求されるストレージの合計はこの値を超えることができません。
        3
        プロジェクトのすべての永続ボリューム要求 (PVC) において、gold ストレージクラスで要求されるストレージの合計はこの値を超えることができません。
        4
        プロジェクトのすべての永続ボリューム要求 (PVC) において、silver ストレージクラスで要求されるストレージの合計はこの値を超えることができません。
        5
        プロジェクトのすべての永続ボリューム要求 (PVC) において、silver ストレージクラスの要求の合計数はこの値を超えることができません。
        6
        プロジェクトのすべての永続ボリューム要求 (PVC) において、bronze ストレージクラスで要求されるストレージの合計はこの値を超えることができません。この値が 0 に設定される場合、bronze ストレージクラスはストレージを要求できません。
        7
        プロジェクトのすべての永続ボリューム要求 (PVC) において、bronze ストレージクラスで要求されるストレージの合計はこの値を超えることができません。この値が 0 に設定される場合、bronze ストレージクラスは要求を作成できません。
      3. openshift-config namespace の変更された template.yaml ファイルでプロジェクト要求テンプレートを作成します。

        $ oc create -f template.yaml -n openshift-config
        注記

        設定を kubectl.kubernetes.io/last-applied-configuration アノテーションとして追加するには、 --save-config オプションを oc create コマンドに追加します。

        デフォルトでは、テンプレートは project-request という名前になります。

    • プロジェクト要求テンプレートがクラスター内にすでに存在する場合は、以下を実行します。

      注記

      設定ファイルを使用してクラスター内のオブジェクトを宣言的または命令的に管理する場合は、これらのファイルを使用して既存のプロジェクト要求テンプレートを編集します。

      1. openshift-config namespace のテンプレートをリスト表示します。

        $ oc get templates -n openshift-config
      2. 既存のプロジェクト要求テンプレートを編集します。

        $ oc edit template <project_request_template> -n openshift-config
      3. 前述の storage-consumption の例などのリソースクォータ定義を既存のテンプレートに追加します。テンプレートの parameters: セクションの前に定義を追加する必要があります。
  2. プロジェクト要求テンプレートを作成した場合は、クラスターのプロジェクト設定リソースでこれを参照します。

    1. 編集するプロジェクト設定リソースにアクセスします。

      • Web コンソールの使用

        1. AdministrationCluster Settings ページに移動します。
        2. Configuration をクリックし、すべての設定リソースを表示します。
        3. Project のエントリーを見つけ、Edit YAML をクリックします。
      • CLI の使用

        1. project.config.openshift.io/cluster リソースを編集します。

          $ oc edit project.config.openshift.io/cluster
    2. プロジェクト設定リソースの spec セクションを更新し、projectRequestTemplate および name パラメーターを追加します。以下の例は、project-request というデフォルトのプロジェクト要求テンプレートを参照します。

      apiVersion: config.openshift.io/v1
      kind: Project
      metadata:
      #  ...
      spec:
        projectRequestTemplate:
          name: project-request
  3. プロジェクトの作成時にリソースクォータが適用されていることを確認します。

    1. プロジェクトを作成します。

      $ oc new-project <project_name>
    2. プロジェクトのリソースクォータをリスト表示します。

      $ oc get resourcequotas
    3. リソースクォータを詳細に記述します。

      $ oc describe resourcequotas <resource_quota_name>