はじめに
前回の実験では、個々の 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 を実行しました。これにより、個々のコンテナのリソース設定と、名前空間レベルのリソースガバナンスがどのように結びついているかを理解できました。


