Namespace リソースクォータの適用

KubernetesBeginner
オンラインで実践に進む

はじめに

前回の実験では、個々の Pod や Deployment 内でのリソースリクエスト(requests)とリミット(limits)に焦点を当てました。ResourceQuota は、その考え方を名前空間(Namespace)レベルにまで拡張するものです。これにより、チームやプラットフォーム管理者は、その名前空間内に作成できる Pod の数や、要求可能な CPU 合計量、制限可能なメモリ上限などの境界を設定できます。

この実験では、名前空間に ResourceQuota を作成し、そのハードリミットを確認します。また、必要なリソース宣言を行っていない Pod が Kubernetes によって拒否される様子を観察し、最後に名前空間の Pod 数クォータに達するまで準拠した Pod を実行します。

クォータ練習用名前空間の準備

このステップでは、ResourceQuota の練習用にクリーンな名前空間を準備します。

/home/labex/project から開始します。このディレクトリ内にクォータと Pod のマニフェストを作成します。

mkdir -p /home/labex/project
cd /home/labex/project

Kubernetes API サーバーに接続できるか確認します。VM が起動した直後でノードの準備ができていない場合は、数秒待ってから再度コマンドを実行してください。

kubectl get nodes --request-timeout=5s

期待される出力例:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

アプリケーション Pod を作成する前に、クラスターのネットワーク Pod が Ready 状態になるまで待ちます。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

期待される出力:

pod/calico-node-... condition met

ckad-prep-quotas という名前の名前空間を作成します。

kubectl create namespace ckad-prep-quotas

この名前空間を現在のコンテキストの名前空間として設定します。

kubectl config set-context --current --namespace=ckad-prep-quotas

現在の名前空間を確認します。

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

期待される出力:

ckad-prep-quotas

Namespace リソースクォータの作成

このステップでは、オブジェクト数とリソース要求合計の両方を制限する ResourceQuota を作成します。

pods クォータは、名前空間内に存在できる Pod の数を制限します。requests.* および limits.* クォータは、一致するすべての Pod によって宣言されたリソース要求と制限の合計を追跡します。名前空間に CPU やメモリのリクエスト/リミットのクォータ設定がある場合、新しい Pod はそれらのフィールドを宣言しなければ、Kubernetes が集計を行うことができません。

app-resource-quota.yaml を作成します。

cat > app-resource-quota.yaml <<'EOF'
apiVersion: v1
kind: ResourceQuota
metadata:
  name: app-resource-quota
spec:
  hard:
    pods: "2"
    requests.cpu: "400m"
    requests.memory: 256Mi
    limits.cpu: "800m"
    limits.memory: 512Mi
EOF

クォータを適用します。

kubectl apply -f app-resource-quota.yaml

期待される出力:

resourcequota/app-resource-quota created

クォータを確認します。現時点では名前空間内で Pod が実行されていないため、使用量はゼロになっているはずです。

kubectl describe resourcequota app-resource-quota

期待される出力例:

Name:            app-resource-quota
Resource         Used  Hard
limits.cpu       0     800m
limits.memory    0     512Mi
pods             0     2
requests.cpu     0     400m
requests.memory  0     256Mi

クォータによって拒否される Pod の観察

このステップでは、リソースのリクエストとリミットを指定せずに Pod を作成してみます。

この Pod は意図的に不完全な状態にしています。名前空間のクォータは CPU とメモリのリクエストおよびリミットを追跡しているため、Kubernetes はこれらのフィールドを省略した Pod を受け入れることができません。これは CKAD のタスクにおいて認識しておくべき重要な失敗例です。マニフェスト自体は有効な YAML であっても、名前空間のポリシーによってアドミッション(受け入れ)が拒否される可能性があります。

no-resources-pod.yaml を作成します。

cat > no-resources-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: no-resources
  labels:
    app: no-resources
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'sleep 3600'
EOF

マニフェストを適用してみます。末尾の || true は、期待されるエラーが発生した後もシェルが終了しないようにし、結果を確認できるようにするためのものです。

kubectl apply -f no-resources-pod.yaml || true

期待される出力例:

Error from server (Forbidden): error when creating "no-resources-pod.yaml": pods "no-resources" is forbidden: failed quota

Pod が作成されていないことを確認します。

kubectl get pod no-resources

期待される出力例:

Error from server (NotFound): pods "no-resources" not found

クォータの使用量が依然としてゼロであることを確認します。

kubectl get resourcequota app-resource-quota -o 'jsonpath={.status.used.pods}{"\n"}'

期待される出力:

0

クォータが満杯になるまで準拠した Pod を実行する

このステップでは、リソースのリクエストとリミットを含んだ Pod を作成し、3 つ目の Pod が Pod 数クォータによって停止される様子を観察します。

以下の各有効な Pod は、100m CPU と 64Mi メモリをリクエストし、200m CPU と 128Mi メモリをリミットとして設定します。このような Pod は 2 つまでならクォータ内に収まります。3 つ目の Pod はリソースフィールドが有効であっても、名前空間が許可する Pod 数は 2 つまでであるため、拒否されます。

quota-workers.yaml を作成します。

cat > quota-workers.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: quota-worker-a
  labels:
    app: quota-worker
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command: ["/bin/sh", "-c", "echo worker-a-ready; sleep 3600"]
    resources:
      requests:
        cpu: 100m
        memory: 64Mi
      limits:
        cpu: 200m
        memory: 128Mi
---
apiVersion: v1
kind: Pod
metadata:
  name: quota-worker-b
  labels:
    app: quota-worker
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command: ["/bin/sh", "-c", "echo worker-b-ready; sleep 3600"]
    resources:
      requests:
        cpu: 100m
        memory: 64Mi
      limits:
        cpu: 200m
        memory: 128Mi
EOF

マニフェストを適用し、両方の Pod が起動するのを待ちます。

kubectl apply -f quota-workers.yaml
kubectl wait --for=condition=Ready pod/quota-worker-a pod/quota-worker-b --timeout=120s

期待される出力:

pod/quota-worker-a created
pod/quota-worker-b created
pod/quota-worker-a condition met
pod/quota-worker-b condition met

クォータの使用状況を確認します。

kubectl get resourcequota app-resource-quota -o 'jsonpath={.status.used.pods}{" "}{.status.used.requests\.cpu}{" "}{.status.used.requests\.memory}{" "}{.status.used.limits\.cpu}{" "}{.status.used.limits\.memory}{"\n"}'

期待される出力:

2 200m 128Mi 400m 256Mi

有効なリソース設定を持つ 3 つ目の Pod を作成します。

cat > quota-worker-c.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: quota-worker-c
  labels:
    app: quota-worker
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command: ["/bin/sh", "-c", "sleep 3600"]
    resources:
      requests:
        cpu: 100m
        memory: 64Mi
      limits:
        cpu: 200m
        memory: 128Mi
EOF
kubectl apply -f quota-worker-c.yaml || true

期待される出力例:

Error from server (Forbidden): error when creating "quota-worker-c.yaml": pods "quota-worker-c" is forbidden: exceeded quota

まとめ

名前空間の ResourceQuota を作成し、そのハードリミットを確認しました。また、必要なリソースフィールドを省略した Pod が Kubernetes によって拒否される様子を観察し、名前空間の Pod 数制限に達するまで準拠した Pod を実行しました。これにより、個々のコンテナのリソース設定と、名前空間レベルのリソースガバナンスがどのように結びついているかを理解できました。