네임스페이스 리소스 쿼터 (Resource Quota) 적용

KubernetesBeginner
지금 연습하기

소개

이전 실습에서는 개별 파드와 디플로이먼트 내부의 리소스 요청 (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 에 의해 거부되는 것을 관찰했습니다. 또한 네임스페이스의 파드 개수 제한에 도달할 때까지 규정을 준수하는 파드를 실행해 보았습니다. 이를 통해 개별 컨테이너의 리소스 설정과 네임스페이스 수준의 리소스 거버넌스가 어떻게 연결되는지 이해할 수 있습니다.