LabHub
배우기 러닝패스 코스

CNPA — Cloud Native Platform Engineering Associate

Setting a Platform Baseline and Raising It

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

플랫폼이 요구하는 최소 기준선을 네임스페이스에 못박고, 그것이 실제로 거절하는지 확인한 다음, 한 단계 올리는 과정을 영향 조사부터 예외 처리까지 한 바퀴 돌립니다.

왜 중요한가

기준선을 문서로만 두면 아무것도 거절하지 못하고, 거절하지 못하는 규칙은 반년 뒤에 절반이 깨져 있습니다. 반대로 처음부터 전부 막으면 어제 되던 배포가 오늘 막혀 플랫폼이 장애의 원인으로 기억됩니다. 그래서 실무는 "지금 지킬 등급을 강제하고, 다음 등급은 경고로 미리 알리고, 올리기 전에 영향을 조사하고, 못 지키는 쪽에는 만료일이 붙은 예외를 준다" 는 순서로 움직입니다. 이 실습은 그 순서를 그대로 손으로 밟습니다. 준수(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.yamlplatform-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.yamlapiVersion: 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: ordersapp.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.matchLabelsapp.kubernetes.io/name: orders, spec.endpoints[0].portmetrics, interval30s 입니다.
  6. /root/cnpa-base/exception.yaml 에 네임스페이스 platform-legacy 를 작성해 적용하세요. 라벨은 pod-security.kubernetes.io/enforce: baselinepod-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: falsecapabilities.drop: [ALL] 을 넣습니다. 다시 적용해 파드가 새로 뜬 뒤에 platform-baselineenforce 라벨을 restricted 로 올리세요. enforce-versionv1.30 그대로 둡니다.
  8. /root/cnpa-base/baseline.json 에 현황을 남기세요. 키는 namespace, enforce, enforce_version, deployments(그 네임스페이스의 Deployment 개수), servicemonitor(이름), exception_namespace, exception_expires 입니다.

참고

기준선 네임스페이스

네임스페이스 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 입니다.

Pod Security Admission 은 네임스페이스 라벨만으로 동작합니다. 지금 지킬 등급은 enforce 에, 다음에 올릴 등급은 warn 에 겁니다. 등급마다 버전 라벨을 함께 고정하세요.

정말 거절하는지 확인

/root/cnpa-base/bad-probe.yamlplatform-baseline 네임스페이스의 파드 bad-probe 를 작성하세요. spec.hostPID: true 이고 컨테이너는 이름 probe, 이미지 ghcr.io/labhub/probe:1.0.0 입니다. 적용해 보고 그 실패 출력을 표준 에러까지 함께 /root/cnpa-base/reject.txt 에 저장하세요. 파드 bad-probe 는 클러스터에 남아 있으면 안 됩니다.

라벨을 붙였다고 정책이 도는 것은 아닙니다. 호스트 네임스페이스를 요구하는 파드를 만들어 보고, 그때 나오는 거절 메시지를 표준 에러까지 함께 파일로 남기세요.

폐기된 API 는 왜 거절되는가

/root/cnpa-base/legacy.yamlapiVersion: extensions/v1beta1 인 Ingress orders-legacy(네임스페이스 platform-baseline)를 작성하세요. 적용해 보고 그 실패 출력을 /root/cnpa-base/legacy-reject.txt 에 저장하세요.

폐기된 그룹으로 쓰인 매니페스트는 문법 오류가 아니라 매핑 실패로 떨어집니다. 그 메시지를 그대로 남기고, 정말 그 그룹이 제공되지 않는지 클러스터에 확인해 보세요.

상위 API 로 옮겨 적용

/root/cnpa-base/app.yaml 에 apps/v1 Deployment orders 를 작성해 적용하세요. spec.replicas: 2, 메타데이터 라벨 app.kubernetes.io/name: ordersapp.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)를 작성해 적용하세요.

Deployment 는 apps/v1, Ingress 는 networking.k8s.io/v1 입니다. v1 Ingress 는 경로마다 pathType 을 요구하고, 백엔드는 서비스 이름과 포트를 따로 가리킵니다. 포트는 번호 대신 이름으로 가리키면 Service 와 어긋나지 않습니다.

스크레이프 계약 맺기

/root/cnpa-base/servicemonitor.yaml 에 ServiceMonitor orders(네임스페이스 platform-baseline)를 작성해 적용하세요. spec.selector.matchLabelsapp.kubernetes.io/name: orders, spec.endpoints[0].portmetrics, interval30s 입니다.

ServiceMonitor 는 Service 를 라벨로 고르고, 포트는 번호가 아니라 Service 의 포트 이름으로 가리킵니다. 만든 뒤에는 그 셀렉터가 정말 무엇을 골랐는지 kubectl 로 되물어 확인하세요.

예외와 상향 영향 조사

/root/cnpa-base/exception.yaml 에 네임스페이스 platform-legacy 를 작성해 적용하세요. 라벨은 pod-security.kubernetes.io/enforce: baselinepod-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 는 고치지 말고 그대로 둡니다.

라벨 변경을 서버 dry-run 으로 보내면 지금 떠 있는 파드를 새 등급으로 평가한 경고가 돌아옵니다. 경고는 표준 에러로 나오니 함께 저장하세요. 예외 네임스페이스의 워크로드는 일부러 고치지 않고 그대로 둡니다.

워크로드를 맞추고 등급 올리기

orders 의 파드 템플릿을 restricted 기준에 맞추세요. 파드 수준에 runAsNonRoot: true, runAsUser: 10001, seccompProfile.type: RuntimeDefault 를, 컨테이너 수준에 allowPrivilegeEscalation: falsecapabilities.drop: [ALL] 을 넣습니다. 다시 적용해 파드가 새로 뜬 뒤에 platform-baselineenforce 라벨을 restricted 로 올리세요. enforce-versionv1.30 그대로 둡니다.

restricted 는 네 가지를 요구합니다. 루트로 돌지 않기, seccomp 기본 프로파일, 권한 상승 금지, capability 전부 버리기입니다. 앞의 둘은 파드 수준에, 뒤의 둘은 컨테이너 수준에 씁니다. 워크로드를 먼저 고치고 등급은 나중에 올립니다.

기준선 현황을 값으로 남기기

/root/cnpa-base/baseline.json 에 현황을 남기세요. 키는 namespace, enforce, enforce_version, deployments(그 네임스페이스의 Deployment 개수), servicemonitor(이름), exception_namespace, exception_expires 입니다.

보고서의 숫자는 전부 클러스터에서 다시 셀 수 있는 것이어야 합니다. 네임스페이스 라벨, Deployment 개수, ServiceMonitor 이름, 예외 만료일을 각각 조회해 채우세요.