CNPA — 클라우드 네이티브 플랫폼 엔지니어링 어소시에이트 · 플랫폼 기준선과 준수 · 실습
정책을 켜자 긴급 패치가 막혔다
목표
진짜 k3s 와 Kyverno 에서 플랫폼 규칙 하나(소유자 라벨과 리소스 요청)를 세 팀에 들입니다. 감사로 먼저 세고, 보고서로 위반을 찾고,
차단으로 바꿨을 때 무엇이 막히는지 겪어 본 뒤, 고칠 수 없는 대상에 기한부 예외를 주고 준수율을 계산합니다.
왜 중요한가
정책 엔진은 플랫폼의 가드레일을 코드로 강제하는 도구입니다. 그런데 규칙을 처음부터 차단으로 켜면 이미 규칙을 어긴 워크로드의 긴급 패치까지 막혀
장애 대응이 멈춥니다. 그래서 거버넌스는 보통 감사 → 보고서로 현황 파악 → 팀별 수정 → 차단 → 좁고 기한 있는 예외의 순서로 굴러갑니다.
이 실습은 그 순서의 각 단계에서 클러스터가 실제로 어떻게 반응하는지, 그리고 예외가 조용한 영구 허용으로 변하지 않게 하는 장치가 무엇인지를 확인합니다.
단계
1. /root/cnpa-pol/tenants.yaml 에 세 네임스페이스와 Deployment 네 개를 작성해 적용하세요. 네임스페이스 team-pay·team-legacy·team-vendor 에는 각각 라벨 platform.labhub.io/tenant 를 pay·legacy·vendor 로 붙입니다. Deployment 는 모두 replicas 1, 컨테이너 이름 app, 이미지 registry.k8s.io/pause:3.10, 메타데이터와 셀렉터 라벨 app.kubernetes.io/name: <이름> 입니다. team-pay/checkout 은 메타데이터 라벨 app.kubernetes.io/owner: pay 와 requests(cpu 10m, memory 16Mi)를 둘 다 가지고, team-legacy/report-gen 은 requests 만, team-legacy/batch-sync 는 owner 라벨(legacy)만, team-vendor/vendor-agent 는 둘 다 없습니다.
2. /root/cnpa-pol/policy.yaml 에 ValidatingPolicy(policies.kyverno.io/v1) tenant-deploy-baseline 을 작성해 적용하세요. validationActions: [Audit], evaluation.background.enabled: true, matchConstraints 는 apps/v1 deployments 의 CREATE·UPDATE 이고 namespaceSelector 로 라벨 platform.labhub.io/tenant 가 있는(Exists) 네임스페이스만 고릅니다. 검증 두 개를 이 순서로 둡니다. ① 메타데이터 라벨에 app.kubernetes.io/owner 가 있음, 메시지 Deployment 에 app.kubernetes.io/owner 라벨이 필요합니다 ② 모든 컨테이너에 requests 의 cpu 와 memory 가 있음, 메시지 모든 컨테이너에 cpu·memory requests 가 필요합니다.
3. Kyverno 가 남긴 PolicyReport 를 읽어, tenant-deploy-baseline 결과가 fail 인 Deployment 를 /root/cnpa-pol/violations.json 에 배열로 적으세요. 원소마다 namespace, name, uid(보고서의 scope.uid), message(그 결과의 메시지)를 둡니다.
4. 정책의 validationActions 를 [Deny] 로 바꾸세요. 그다음 legacy 팀의 긴급 패치를 흉내 내어 kubectl -n team-legacy set image deploy/batch-sync app=registry.k8s.io/pause:3.9 를 실행하고 그 출력(표준 에러 포함)을 /root/cnpa-pol/blocked.txt 에 저장하세요. 이어서 kubectl -n team-legacy scale deploy/batch-sync --replicas=2 를 실행하고, /root/cnpa-pol/deny-effects.json 에 image_update_denied, scale_allowed(불리언), batch_sync_image(지금 batch-sync 의 이미지)를 적으세요.
5. legacy 팀의 두 Deployment 를 규칙에 맞추세요. report-gen 에 메타데이터 라벨 app.kubernetes.io/owner: legacy 를, batch-sync 의 컨테이너 app 에 requests(cpu 50m, memory 64Mi)를 넣습니다. 그다음 4단계에서 막혔던 set image ... app=registry.k8s.io/pause:3.9 를 다시 실행해 통과시키고, 두 Deployment 의 PolicyReport 결과가 pass 로 바뀔 때까지 기다리세요.
6. vendor-agent 는 업체가 주는 매니페스트라 당장 고칠 수 없습니다. 먼저 kyverno-admission-controller Deployment 의 인자 --enablePolicyException=false 를 --enablePolicyException=true 로 바꾸고 롤아웃이 끝나기를 기다리세요. 그다음 /root/cnpa-pol/exception.yaml 에 PolicyException(policies.kyverno.io/v1) vendor-agent-requests 를 team-vendor 네임스페이스에 만듭니다. policyRefs 는 ValidatingPolicy tenant-deploy-baseline, matchConditions 는 이름이 vendor-agent 인 오브젝트만, expiresAt 은 지금부터 30일 뒤(RFC3339, UTC)입니다. 적용 뒤 vendor-agent 에 어노테이션 platform.labhub.io/reviewed=true 를 붙이세요.
7. /root/cnpa-pol/expired.yaml 에 PolicyException old-cron-requests 를 team-legacy 에 만드세요. 대상은 이름이 old-cron 인 오브젝트, 정책은 tenant-deploy-baseline, expiresAt 은 지금보다 하루 전입니다. 그다음 owner 라벨도 requests 도 없는 Deployment old-cron(이미지 registry.k8s.io/pause:3.10)을 team-legacy 에 서버 dry-run 으로 만들어 보고, 그 출력(표준 에러 포함)을 /root/cnpa-pol/expired.txt 에 저장하세요.
8. 세 테넌트 네임스페이스의 PolicyReport 에서 tenant-deploy-baseline 결과를 세어 /root/cnpa-pol/compliance.json 에 적으세요. 키는 pass, fail, skip(개수), rate_pct(pass / (pass + fail) × 100, 소수 첫째 자리, 분모가 0 이면 100.0), exceptions(지금 만료되지 않은 PolicyException 을 네임스페이스/이름 문자열로, 정렬한 배열)입니다.
참고
- VM 안에 k3s 와 Kyverno 1.19 가 설치되어 있습니다. 워크로드 이미지는
registry.k8s.io/pause만 씁니다. - 정책 준비 확인:
kubectl get validatingpolicy tenant-deploy-baseline -o jsonpath='{.status.conditionStatus.ready}'. - 보고서:
kubectl get policyreport -A와-o json. 보고서 이름은 대상 리소스의 uid 입니다. - 흔한 실수: 예외 기능이 꺼진 채 PolicyException 을 만드는 것.
kubectl apply는 성공하고 경고 한 줄만 나오며, 어드미션은 계속 거절합니다. - 예외의 만료 필드 설명:
kubectl explain policyexception.spec.expiresAt --api-version=policies.kyverno.io/v1. - 흔한 실수:
matchConditions없이 예외를 만드는 것. 그 네임스페이스의 모든 Deployment 가 규칙을 벗어납니다. - [Kyverno ValidatingPolicy](https://kyverno.io/docs/policy-types/validating-policy/) · [Kyverno Policy Exceptions](https://kyverno.io/docs/guides/exceptions/) · [Kyverno Reporting](https://kyverno.io/docs/guides/reports/) · [Kubernetes CEL](https://kubernetes.io/docs/reference/using-api/cel/) · [CNCF Platforms White Paper](https://tag-app-delivery.cncf.io/whitepapers/platforms/)
단계 8개
- 정책 전의 세 팀
- 막지 않고 먼저 센다
- 몰랐던 위반이 보고서에 드러났다
- 정책을 켜자 긴급 패치가 막혔다
- 규칙을 맞추자 같은 패치가 통과했다
- 고칠 수 없는 외부 매니페스트에 기한부 예외
- 기한이 지난 예외는 아무것도 지켜 주지 않는다
- 준수율을 보고서에서 계산한다