소개
이전 실습에서는 개별 파드와 디플로이먼트 내부의 리소스 요청 (requests) 및 제한 (limits) 에 대해 다루었습니다. ResourceQuota 는 이러한 개념을 네임스페이스 수준으로 확장합니다. 이를 통해 팀이나 플랫폼 운영자는 특정 네임스페이스 내에 존재할 수 있는 파드의 개수, 요청 가능한 CPU 총량, 제한 가능한 메모리 총량 등과 같은 경계를 설정할 수 있습니다.
이번 실습에서는 네임스페이스 ResourceQuota 를 생성하고, 하드 제한을 확인하며, 필수 리소스를 선언하지 않은 파드가 Kubernetes 에 의해 거부되는 과정을 관찰합니다. 마지막으로, 네임스페이스의 파드 개수 쿼터에 도달할 때까지 규정을 준수하는 파드를 실행해 봅니다.
쿼터 실습을 위한 네임스페이스 준비
이 단계에서는 ResourceQuota 실습을 위한 깨끗한 네임스페이스를 준비합니다.
/home/labex/project 디렉토리에서 시작합니다. 이 디렉토리에 쿼터 및 파드 매니페스트를 작성할 것입니다.
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...
애플리케이션 파드를 생성하기 전에 클러스터 네트워킹 파드가 준비 (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 생성
이 단계에서는 객체 개수와 총 요청 리소스를 모두 제한하는 ResourceQuota 를 생성합니다.
pods 쿼터는 네임스페이스 내에 존재할 수 있는 파드의 개수를 제한합니다. requests.* 및 limits.* 쿼터는 일치하는 모든 파드가 선언한 리소스 요청 및 제한의 합계를 추적합니다. 네임스페이스에 CPU 및 메모리 요청이나 제한에 대한 쿼터 항목이 있는 경우, 새로운 파드는 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
쿼터를 확인합니다. 현재 네임스페이스에서 실행 중인 파드가 없으므로 사용량은 0 이어야 합니다.
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
쿼터에 의해 거부되는 파드 관찰
이 단계에서는 리소스 요청 및 제한이 없는 파드를 생성해 봅니다.
이 파드는 의도적으로 불완전하게 작성되었습니다. 네임스페이스 쿼터가 CPU 및 메모리 요청과 제한을 추적하기 때문에, Kubernetes 는 해당 필드가 누락된 파드를 허용할 수 없습니다. 이는 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
파드가 생성되지 않았음을 확인합니다:
kubectl get pod no-resources
예상 출력:
Error from server (NotFound): pods "no-resources" not found
쿼터에서 여전히 사용 중인 파드가 0 개인지 확인합니다:
kubectl get resourcequota app-resource-quota -o 'jsonpath={.status.used.pods}{"\n"}'
예상 출력:
0
쿼터가 가득 찰 때까지 규정 준수 파드 실행
이 단계에서는 리소스 요청 및 제한을 포함하는 파드를 생성하고, 세 번째 파드가 파드 개수 쿼터에 의해 차단되는 것을 관찰합니다.
아래의 각 유효한 파드는 100m CPU 와 64Mi 메모리를 요청하며, 200m CPU 와 128Mi 메모리로 제한합니다. 이러한 파드 두 개는 쿼터 내에 적합합니다. 세 번째 파드 역시 유효한 리소스 필드를 가지고 있지만, 네임스페이스는 최대 두 개의 파드만 허용합니다.
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
매니페스트를 적용하고 두 파드가 준비될 때까지 기다립니다:
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
유효한 리소스를 가진 세 번째 파드를 생성합니다:
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 에 의해 거부되는 것을 관찰했습니다. 또한 네임스페이스의 파드 개수 제한에 도달할 때까지 규정을 준수하는 파드를 실행해 보았습니다. 이를 통해 개별 컨테이너의 리소스 설정과 네임스페이스 수준의 리소스 거버넌스가 어떻게 연결되는지 이해할 수 있습니다.


