CNPA — Cloud Native Platform Engineering Associate
Building One Golden Path End to End
한국어 원문으로 표시합니다.
목표
새 서비스 하나가 태어날 때 항상 함께 붙어야 하는 것들 — 표준 라벨, 리소스 요청/제한, 오토스케일, 중단 예산, 네트워크 정책 — 을 한 세트로 묶고, 가드레일이 걸린 네임스페이스에 실제로 올립니다. 이어서 같은 서비스를 Helm 차트로 포장해 환경별 values 로 분기하고 렌더 결과를 배포합니다.
왜 중요한가
골든 패스의 가치는 '무엇을 넣었는가'보다 '개발자가 요청하지 않았는데 들어 있는가'에 있습니다. 스캐폴드가 리소스 제한과 네트워크 정책을 기본으로 달아 주면, 그 규칙을 지키는 데 드는 개발자의 노력이 0 이 됩니다. 반대로 위키에 '반드시 제한을 설정하세요'라고 적어 두면 절반은 잊습니다. 가드레일의 위치도 같은 맥락입니다 — ResourceQuota 와 LimitRange 는 생성 시점에 즉시 판정하므로, 사후 감사 리포트보다 훨씬 나은 개발자 경험을 만듭니다. 특히 이 둘의 조합은 시험에 자주 나옵니다. 쿼터가 CPU 를 제한하면 요청을 명시하지 않은 파드는 거절되는데, LimitRange 의 기본값이 그 구멍을 메워 줍니다. 뒤쪽 Helm 부분은 '같은 스캐폴드를 값으로 분기한다'는 골든 패스의 두 번째 얼굴입니다 — 템플릿 하나로 dev 와 prod 를 동시에 만족시키는 방법입니다.
단계
/root/cnpa-path/manifests/deployment.yaml에 Deploymentpayments를 작성하세요 —spec.replicas: 2, 셀렉터·파드 라벨에app.kubernetes.io/name: payments, 메타데이터 라벨에app.kubernetes.io/name: payments와app.kubernetes.io/part-of: cnpa-platform, 컨테이너 이름app, 이미지ghcr.io/labhub/payments:1.0.0, containerPort8080,resources.requests는 cpu100m/ memory128Mi,resources.limits는 cpu300m/ memory256Mi./root/cnpa-path/manifests/service.yaml에 Servicepayments를 작성하세요 — typeClusterIP, port80, targetPort8080, 셀렉터app.kubernetes.io/name: payments./root/cnpa-path/manifests/hpa.yaml에 HorizontalPodAutoscalerpayments(apiVersionautoscaling/v2, scaleTargetRef 는 apps/v1 Deploymentpayments,minReplicas: 2,maxReplicas: 6, cpu Utilization 목표70)를 작성하세요./root/cnpa-path/manifests/pdb.yaml에 PodDisruptionBudgetpayments(minAvailable: 1, 셀렉터app.kubernetes.io/name: payments)를,/root/cnpa-path/manifests/netpol.yaml에 NetworkPolicypayments(podSelector 는app.kubernetes.io/name: payments, policyTypes 첫 항목Ingress, ingress 는app.kubernetes.io/part-of: cnpa-platform라벨을 가진 파드에서 TCP8080만 허용)를 작성하세요.- 네임스페이스
cnpa-app을 만들고, 그 안에 ResourceQuotacnpa-app-quota(requests.cpu: "1",requests.memory: 1Gi,limits.cpu: "2",limits.memory: 2Gi,pods: "8")와 LimitRangecnpa-app-limits(typeContainer,defaultcpu200m/ memory256Mi,defaultRequestcpu100m/ memory128Mi)를 만드세요. /root/cnpa-path/manifests/의 다섯 매니페스트를 모두cnpa-app네임스페이스에 적용하세요.helm create /root/cnpa-path/payments로 차트를 만들고,values.yaml을 고치세요 —replicaCount: 2,image.repository: ghcr.io/labhub/payments,image.tag: "1.0.0"./root/cnpa-path/payments/values-dev.yaml(replicaCount: 1,image.tag: "1.0.0")와/root/cnpa-path/payments/values-prod.yaml(replicaCount: 3,image.tag: "1.2.0",fullnameOverride: payments-v2)를 만드세요. 그다음helm template payments-v2 /root/cnpa-path/payments -f /root/cnpa-path/payments/values-prod.yaml -n cnpa-app결과를/root/cnpa-path/render-prod.yaml에 저장하세요./root/cnpa-path/render-prod.yaml을cnpa-app네임스페이스에 적용하세요. 적용 후payments-v2Deployment 가 replicas3, 이미지ghcr.io/labhub/payments:1.2.0으로 떠 있어야 하고, 3 단계의 쿼터는 그대로 남아 있어야 합니다.
참고
- 디렉터리 전체 적용은
kubectl apply -n cnpa-app -f /root/cnpa-path/manifests/입니다. helm template은 클러스터에 아무것도 만들지 않습니다. 렌더 결과만 표준 출력으로 나옵니다.fullnameOverride를 주면 helm 이 만드는 리소스 이름이 그 값으로 고정됩니다. 4 단계에서 올린payments와 이름이 겹치지 않게 하는 장치입니다.- 흔한 실수 1: HPA 의
scaleTargetRef.apiVersion을 빼먹는 것. Deployment 는apps/v1입니다. - 흔한 실수 2: NetworkPolicy 의
policyTypes를 생략하는 것. 생략하면 규칙이 있는 방향만 적용되어 의도와 달라질 수 있습니다.
서비스 스캐폴드 — Deployment 와 Service
/root/cnpa-path/manifests/deployment.yaml 에 Deployment payments 를 작성하세요 — spec.replicas: 2, 셀렉터·파드 라벨에 app.kubernetes.io/name: payments, 메타데이터 라벨에 app.kubernetes.io/name: payments 와 app.kubernetes.io/part-of: cnpa-platform, 컨테이너 이름 app, 이미지 ghcr.io/labhub/payments:1.0.0, containerPort 8080, resources.requests 는 cpu 100m / memory 128Mi, resources.limits 는 cpu 300m / memory 256Mi. /root/cnpa-path/manifests/service.yaml 에 Service payments 를 작성하세요 — type ClusterIP, port 80, targetPort 8080, 셀렉터 app.kubernetes.io/name: payments.
골든 패스의 기본값이란 '아무도 요청하지 않았지만 항상 들어 있는 것'입니다. 표준 라벨과 리소스 요청/제한이 그 예입니다.
HPA · PDB · NetworkPolicy
/root/cnpa-path/manifests/hpa.yaml 에 HorizontalPodAutoscaler payments(apiVersion autoscaling/v2, scaleTargetRef 는 apps/v1 Deployment payments, minReplicas: 2, maxReplicas: 6, cpu Utilization 목표 70)를 작성하세요. /root/cnpa-path/manifests/pdb.yaml 에 PodDisruptionBudget payments(minAvailable: 1, 셀렉터 app.kubernetes.io/name: payments)를, /root/cnpa-path/manifests/netpol.yaml 에 NetworkPolicy payments(podSelector 는 app.kubernetes.io/name: payments, policyTypes 첫 항목 Ingress, ingress 는 app.kubernetes.io/part-of: cnpa-platform 라벨을 가진 파드에서 TCP 8080 만 허용)를 작성하세요.
세 리소스 모두 셀렉터로 대상 워크로드를 찾습니다. HPA 만 셀렉터가 아니라 대상 참조를 씁니다.
가드레일이 있는 네임스페이스
네임스페이스 cnpa-app 을 만들고, 그 안에 ResourceQuota cnpa-app-quota(requests.cpu: "1", requests.memory: 1Gi, limits.cpu: "2", limits.memory: 2Gi, pods: "8")와 LimitRange cnpa-app-limits(type Container, default cpu 200m / memory 256Mi, defaultRequest cpu 100m / memory 128Mi)를 만드세요.
쿼터가 자원을 제한하면 그 네임스페이스의 모든 컨테이너는 요청/제한을 선언해야 합니다. 선언하지 않은 것을 구제해 주는 오브젝트가 따로 있습니다.
스캐폴드를 클러스터에 적용
/root/cnpa-path/manifests/ 의 다섯 매니페스트를 모두 cnpa-app 네임스페이스에 적용하세요.
다섯 리소스를 모두 같은 네임스페이스에 올립니다. 디렉터리 전체를 한 번에 적용하는 옵션이 있습니다.
helm create 로 로컬 차트
helm create /root/cnpa-path/payments 로 차트를 만들고, values.yaml 을 고치세요 — replicaCount: 2, image.repository: ghcr.io/labhub/payments, image.tag: "1.0.0".
helm create 는 인터넷 없이 로컬에 차트 뼈대를 만듭니다. 생성된 values.yaml 을 이 서비스에 맞게 고치세요.
환경별 values 와 렌더 확인
/root/cnpa-path/payments/values-dev.yaml(replicaCount: 1, image.tag: "1.0.0")와 /root/cnpa-path/payments/values-prod.yaml(replicaCount: 3, image.tag: "1.2.0", fullnameOverride: payments-v2)를 만드세요. 그다음 helm template payments-v2 /root/cnpa-path/payments -f /root/cnpa-path/payments/values-prod.yaml -n cnpa-app 결과를 /root/cnpa-path/render-prod.yaml 에 저장하세요.
values 파일은 겹쳐 쌓입니다. 나중에 준 파일이 이깁니다. 렌더는 클러스터를 건드리지 않는 명령으로 하세요.
렌더 결과를 가드레일 안에 배포
/root/cnpa-path/render-prod.yaml 을 cnpa-app 네임스페이스에 적용하세요. 적용 후 payments-v2 Deployment 가 replicas 3, 이미지 ghcr.io/labhub/payments:1.2.0 으로 떠 있어야 하고, 3 단계의 쿼터는 그대로 남아 있어야 합니다.
이름 충돌이 나지 않도록 values 에서 이름을 고정했는지 확인하세요. 렌더한 파일을 그대로 적용하면 됩니다.