CNPA — 클라우드 네이티브 플랫폼 엔지니어링 어소시에이트 · 플랫폼 기준선과 준수 · 실습
플랫폼 기준선 세우고 올리기
목표
플랫폼이 요구하는 최소 기준선을 네임스페이스에 못박고, 그것이 실제로 거절하는지 확인한 다음, 한 단계 올리는 과정을 영향 조사부터 예외 처리까지 한 바퀴 돌립니다.
왜 중요한가
기준선을 문서로만 두면 아무것도 거절하지 못하고, 거절하지 못하는 규칙은 반년 뒤에 절반이 깨져 있습니다. 반대로 처음부터 전부 막으면 어제 되던 배포가 오늘 막혀 플랫폼이 장애의 원인으로 기억됩니다. 그래서 실무는 "지금 지킬 등급을 강제하고, 다음 등급은 경고로 미리 알리고, 올리기 전에 영향을 조사하고, 못 지키는 쪽에는 만료일이 붙은 예외를 준다" 는 순서로 움직입니다. 이 실습은 그 순서를 그대로 손으로 밟습니다. 준수(conformance)를 함께 다루는 이유도 같습니다. 폐기된 API 를 남겨 두면 어느 날 클러스터를 올리는 순간 배포가 통째로 멈추는데, 그 신호를 미리 읽는 눈이 플랫폼 팀의 기본기입니다.
단계
1. 네임스페이스 platform-baseline 을 만들고 라벨을 붙이세요. pod-security.kubernetes.io/enforce=baseline, pod-security.kubernetes.io/enforce-version=v1.30, pod-security.kubernetes.io/warn=restricted, pod-security.kubernetes.io/warn-version=v1.30, platform.labhub.io/owner=platform-team 입니다.
2. /root/cnpa-base/bad-probe.yaml 에 platform-baseline 네임스페이스의 파드 bad-probe 를 작성하세요. spec.hostPID: true 이고 컨테이너는 이름 probe, 이미지 ghcr.io/labhub/probe:1.0.0 입니다. 적용해 보고 그 실패 출력을 표준 에러까지 함께 /root/cnpa-base/reject.txt 에 저장하세요. 파드 bad-probe 는 클러스터에 남아 있으면 안 됩니다.
3. /root/cnpa-base/legacy.yaml 에 apiVersion: extensions/v1beta1 인 Ingress orders-legacy(네임스페이스 platform-baseline)를 작성하세요. 적용해 보고 그 실패 출력을 /root/cnpa-base/legacy-reject.txt 에 저장하세요.
4. /root/cnpa-base/app.yaml 에 apps/v1 Deployment orders 를 작성해 적용하세요. spec.replicas: 2, 메타데이터 라벨 app.kubernetes.io/name: orders 와 app.kubernetes.io/part-of: cnpa-platform, 컨테이너 이름 app, 이미지 ghcr.io/labhub/orders:1.4.0, 컨테이너 포트는 이름 http(8080)와 metrics(9102) 두 개입니다. /root/cnpa-base/edge.yaml 에는 Service orders(셀렉터 app.kubernetes.io/name: orders, 포트 이름 http 는 80 에서 8080 으로, 포트 이름 metrics 는 9102 에서 9102 로)와 networking.k8s.io/v1 Ingress orders(호스트 orders.labhub.internal, 경로 /, pathType: Prefix, 백엔드는 서비스 orders 의 포트 이름 http)를 작성해 적용하세요.
5. /root/cnpa-base/servicemonitor.yaml 에 ServiceMonitor orders(네임스페이스 platform-baseline)를 작성해 적용하세요. spec.selector.matchLabels 는 app.kubernetes.io/name: orders, spec.endpoints[0].port 는 metrics, interval 은 30s 입니다.
6. /root/cnpa-base/exception.yaml 에 네임스페이스 platform-legacy 를 작성해 적용하세요. 라벨은 pod-security.kubernetes.io/enforce: baseline 과 pod-security.kubernetes.io/enforce-version: v1.30, 어노테이션은 platform.labhub.io/exception-expires(YYYY-MM-DD 형식의 만료일)와 platform.labhub.io/exception-reason(사유)입니다. 같은 파일에 Deployment legacy-batch(replicas 1, 이미지 ghcr.io/labhub/legacy-batch:0.9.0, 보안 설정 없음)도 넣으세요. 그다음 이 네임스페이스를 restricted 로 올리는 라벨 변경을 서버 dry-run 으로 보내고, 그 출력을 표준 에러까지 /root/cnpa-base/upgrade-check.txt 에 저장하세요. legacy-batch 는 고치지 말고 그대로 둡니다.
7. orders 의 파드 템플릿을 restricted 기준에 맞추세요. 파드 수준에 runAsNonRoot: true, runAsUser: 10001, seccompProfile.type: RuntimeDefault 를, 컨테이너 수준에 allowPrivilegeEscalation: false 와 capabilities.drop: [ALL] 을 넣습니다. 다시 적용해 파드가 새로 뜬 뒤에 platform-baseline 의 enforce 라벨을 restricted 로 올리세요. enforce-version 은 v1.30 그대로 둡니다.
8. /root/cnpa-base/baseline.json 에 현황을 남기세요. 키는 namespace, enforce, enforce_version, deployments(그 네임스페이스의 Deployment 개수), servicemonitor(이름), exception_namespace, exception_expires 입니다.
참고
- 거절 메시지는 표준 출력이 아니라 표준 에러로 나옵니다.
> 파일 2>&1로 함께 담으세요. - 셀렉터가 무엇을 골랐는지는
kubectl get svc -n platform-baseline -l <라벨>로 되물을 수 있습니다. - 6단계에서
legacy-batch에 보안 설정을 넣어 버리면 상향 경고가 사라져 채점이 떨어집니다. 실수로 넣었다면kubectl delete deploy legacy-batch -n platform-legacy로 지우고 다시 적용하세요. - 7단계는 순서가 중요합니다. 등급을 먼저 올리면 새 파드가 거절되어 롤아웃이 멈춥니다.
단계 8개
- 기준선 네임스페이스
- 정말 거절하는지 확인
- 폐기된 API 는 왜 거절되는가
- 상위 API 로 옮겨 적용
- 스크레이프 계약 맺기
- 예외와 상향 영향 조사
- 워크로드를 맞추고 등급 올리기
- 기준선 현황을 값으로 남기기