階層型リソース割り当てを使用する

Kubernetes のリソースの割り当ては、管理者が複数のユーザー間で公平にリソースを共有できるようにするためのツールです。リソース割り当ては、ResourceQuota オブジェクトで定義され、単一の Namespace でのリソースの合計使用量を制限する制約を提供します。

Hierarchy Controller は、階層型 Namespace をサポートするために、Namespace ごとのリソース割り当てのコンセプトを拡張します。HierarchicalResourceQuota オブジェクトは、サブツリー内のすべての Namespace 間の合計リソース使用量を制限し、管理者は複数の関連する Namespace 間のリソース使用量を制限できるようになります。

階層型リソース割り当てが有効になると、Hierarchy Controller は 2 つの検証用アドミッション Webhook をインストールします。1 つはリソース使用の制限を実際に適用するもので、もう 1 つは階層型リソース割り当て自体を検証するものです。

階層型リソースの割り当てを有効にする

階層型リソース割り当ては、Hierarchy Controller によって提供されます。階層型リソース割り当てを有効にする手順は次のとおりです。

  1. Config Sync 1.6.2 以降を使用して、Hierarchy Controller をインストールします。

  2. ConfigManagement Operator の構成ファイルで、spec.hierarchyController オブジェクトの enableHierarchicalResourceQuota の値を true に設定します。

    # config-management.yaml
    
    apiVersion: configmanagement.gke.io/v1
    kind: ConfigManagement
    metadata:
      name: config-management
    spec:
      hierarchyController:
        enabled: true
        # Set to true to enable hierarchical resource quotas:
        enableHierarchicalResourceQuota: true
      # ...other fields...
    
  3. 構成を適用します。

    kubectl apply -f config-management.yaml
    

    約 1 分後に、Hierarchy Controller と階層型リソース割り当てがクラスタで使用できるようになります。

階層型リソース割り当てが有効になっていることを確認するには、次の手順を行います。

  1. 次のように、任意の Namespace に HierarchicalResourceQuota オブジェクトを作成します。

    cat > example-hrq.yaml <<EOF
    apiVersion: hierarchycontroller.configmanagement.gke.io/v1alpha1
    kind: HierarchicalResourceQuota
    metadata:
      name: example-hrq
    spec:
      hard:
        configmaps: "1"
    EOF
    
    kubectl apply -f example-hrq.yaml -n default
    
  2. gke-hc-hrq という新しい ResourceQuota オブジェクトが、同じ spec.hard に 1 つの configmap を持つ Namespace に作成されていることを確認します。次に例を示します。

    kubectl describe resourcequota gke-hc-hrq -n default
    

    出力:

    Name:           gke-hc-hrq
    Namespace:      default
    Resource        Used    Hard
    --------        ----    ----
    configmaps      0       1
    
  3. クリーンアップします。

    kubectl delete hrq -n default example-hrq
    

    自動的に作成されたオブジェクトが削除されたことを確認します。

    kubectl get resourcequota gke-hc-hrq -n default
    

    出力:

    Error from server (NotFound): resourcequotas "gke-hc-hrq" not found
    

階層型リソース割り当ての使用

割り当ての設定

HierarchicalResourceQuota の設定は通常の ResourceQuota の設定と同じですが、apiVersionkind が異なります。そのため、ResourceQuota の場合と同様に、spec.hard フィールドのリソースに上限を設定できます。

service-a という Service と、team-b というサブチームを持つ team-a というチームを考えてみましょう。これらは、次のように階層型 Namespace で表されます。

kubectl hns tree team-a

出力:

team-a
├── service-a
└── team-b

team-a 内の configmaps の数を制限する一方、子孫の数を制限しない場合、次のように通常の ResourceQuota を作成できます。

cat > team-a-rq.yaml <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-a-rq
  namespace: team-a
spec:
  hard:
    configmaps: "1"
EOF

kubectl apply -f team-a-rq.yaml

それに対し、team-a 内の configmaps と、その子孫結合の合計数を制限するには、前の例の apiVersionkind を次のように置き換えます。

cat > team-a-hrq.yaml <<EOF
# Modify the following two lines:
apiVersion: hierarchycontroller.configmanagement.gke.io/v1alpha1
kind: HierarchicalResourceQuota
# Everything below this line remains the same
metadata:
  name: team-a-hrq
  namespace: team-a
spec:
  hard:
    configmaps: "1"

EOF

kubectl apply -f team-a-hrq.yaml

これら 3 つの Namespace のいずれかで configmap を作成する最初の試行が成功します。たとえば、子の Namespace のいずれかに configmap を作成するとします。

kubectl create configmap config-1 --from-literal key=value -n team-b

出力:

confimap/config-1 created

ただし、兄弟または親の Namespace を含め、3 つの Namespace のいずれかに新しい configmap を作成しようとすると失敗します。

kubectl create configmap config-2 --from-literal key=value -n service-a
kubectl create configmap config-2 --from-literal key=value -n team-a

上の両方のコマンドによる出力:

Error from server (Forbidden): admission webhook "resourcesquotasstatus.hierarchycontroller.configmanagement.gke.io" denied the request: exceeded hierarchical quota in namespace "team-a": "team-a-hrq", requested: configmaps=1, used: configmaps=1, limited: configmaps=1

割り当てを検査する

HierarchicalResourceQuota の現在の上限と使用量を表示するには、kubectl describe コマンドを使用して通常のリソース割り当てを表示します。

kubectl describe hrq team-a-hrq -n team-a

出力:

# ...other fields...
Spec:
  Hard:
    Configmaps:  1
Status:
  Hard:
    Configmaps:  1
  Used:
    Configmaps:  1

Namespace の階層を更新する

Namespace には、常にその祖先内の HierarchicalResourceQuota が適用されます。Namespace 階層を変更すると、割り当ての使用量が再計算されます。

階層型割り当てのあるサブツリーから Namespace を削除する

Namespace が、祖先内で階層型割り当てを持つサブツリーから移動すると、これらの割り当ての対象ではなくなり、そのリソースは割り当ての使用量から除外されます。

たとえば、team-b を前のサブツリーから削除した場合、team-bconfigmap の使用量には制限がなくなります。この階層型割り当ての使用量は 0 にリセットされます。つまり team-aservice-a では合計でもう 1 つ configmap を使用できるようになります。

階層型割り当てのあるサブツリーに Namespace を追加する

Namespace が、階層型割り当てを持つサブツリーに追加されると、階層型割り当ての対象となり、リソースの使用量が割り当ての使用量に追加されます。

たとえば、以前のサブツリーに別の Namespace を追加した場合、新しく追加した Namespace では configmap を使用できなくなります。同様に、新しく追加した Namespace の既存の configmap 使用量は、階層型割り当ての使用量に追加されます。

階層型割り当てでは、新しい Namespace の使用量が階層型割り当ての上限を超えても、新しい Namespace をサブツリーに移動することは可能です。ただし、上限を超えた場合に、リソースの使用量が上限を下回るか上限が上がるまで、追加のリソースの使用が禁止されます。Namespace の既存の使用量よりも低い上限が設けられている場合、これは Kubernetes ResourceQuota の場合と似た動作になります。

一般規則

階層型リソース割り当ては、特殊なケースでも Kubernetes のリソースの割り当てと同じように動作します。次に例を示します。

  • 同じ Namespace に複数の階層型リソース割り当てが適用される場合、最も低いリソースの上限が優先されます。
  • すでに使用済みのリソース量未満の上限を作成すると、既存のリソースは削除されませんが、使用量が上限を下回るか、上限が上がるまで追加のリソースの使用が禁止されます。

トラブルシューティング

リソース使用時の InternalError

リソースの使用時(configmap 作成時など)、リクエストに対して 10 秒間応答しなくなり、次のエラー メッセージが表示されることがあります。

Error from server (InternalError): Internal error occurred: resource quota evaluates timeout

gke-hc-controller-manager Pod が不適切な状態でない限り、このエラー メッセージは表示されないと考えられます。

この問題を解決するには、権限のある管理者が hnc-system Namespace で gke-hc-controller-manager- 接頭辞を直接使用して Pod を削除します。Pod が自動的に再起動します。Pod の準備が完了するまでに、次の点に注意してください。

この方法でも問題が解決しない場合は、分析のために Google に報告してください。可能であれば、次のコマンドで取得できるログを添付してください。

kubectl logs -n hnc-system deployment/gke-hc-controller-manager -c manager

次のステップ