介绍
之前的实验重点介绍了单个 Pod 和 Deployment 内部的资源请求(requests)与限制(limits)。ResourceQuota 将这一概念提升到了命名空间(namespace)级别。它允许团队或平台所有者设置边界,例如在一个命名空间中可以存在多少个 Pod、可以请求多少 CPU,以及可以限制多少内存。
在本实验中,你将创建一个命名空间 ResourceQuota,检查其硬性限制,观察 Kubernetes 如何拒绝一个未声明所需资源的 Pod,然后运行合规的 Pod,直到命名空间达到其 Pod 数量配额。
准备配额练习命名空间
在此步骤中,你将准备一个干净的命名空间,用于进行 ResourceQuota 练习。
从 /home/labex/project 开始。你将在此目录中编写配额和 Pod 的清单文件。
mkdir -p /home/labex/project
cd /home/labex/project
检查 Kubernetes API 服务器是否可达。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再运行该命令。
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
创建命名空间资源配额
在此步骤中,你将创建一个同时限制对象数量和总请求资源的 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 允许你的 shell 在预期的错误发生后继续执行,以便你可以检查结果。
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
检查配额,确认已使用的 Pod 数量仍为零:
kubectl get resourcequota app-resource-quota -o 'jsonpath={.status.used.pods}{"\n"}'
预期输出:
0
运行合规的 Pod 直到配额耗尽
在此步骤中,你将创建包含资源请求和限制的 Pod,然后观察 Pod 数量配额如何阻止第三个 Pod 的创建。
下面每个有效的 Pod 都请求 100m CPU 和 64Mi 内存,并将自身限制为 200m CPU 和 128Mi 内存。两个这样的 Pod 符合配额要求。第三个 Pod 虽然具有有效的资源字段,但由于命名空间只允许两个 Pod,因此它会被拒绝。
创建 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
创建一个具有有效资源的第三个 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,检查了其硬性限制,观察了 Kubernetes 如何拒绝一个省略了必要资源字段的 Pod,并运行了合规的 Pod 直到命名空间达到其 Pod 数量限制。这建立了单个容器资源设置与命名空间级资源治理之间的联系。


