정책을 코드로 · validate 정책 · 실습
필수 라벨과 레지스트리 제한 정책 쓰기
목표
필수 라벨을 요구하는 검증 정책과 레지스트리를 제한하는 거부 규칙을 직접 쓰고, 통과·실패 판정과 정책 리포트를 로컬에서 확인합니다. 마지막에는 정당한 예외를 좁은 범위로 표현합니다.
왜 중요한가
검증 정책에서 사고를 내는 것은 조건식이 아니라 매치 범위입니다. 조건이 틀리면 테스트에서 걸리지만, 매치가 틀리면 정책이 조용히 아무것도 하지 않기 때문에 아무도 눈치채지 못합니다. 그래서 통과해야 할 리소스와 막혀야 할 리소스를 둘 다 넣어 보는 것이 정책 작성의 기본기입니다. 또 하나, 거부 메시지는 정책의 절반입니다. 배포가 막힌 사람이 볼 수 있는 것은 kubectl apply 가 뱉은 한 줄뿐이고, 그 한 줄이 불친절하면 정책 운영 비용이 전부 문의로 돌아옵니다. 마지막으로 이 환경에는 정책 엔진 컨트롤러가 떠 있지 않아 클러스터가 잘못된 파드를 실제로 막지는 않습니다. 판정은 kyverno apply 로 로컬에서 확인하며, 채점도 정책 YAML 의 구조와 그 실행 결과를 봅니다.
단계
1. /root/policy/validate/require-labels.yaml 을 만드세요. apiVersion: kyverno.io/v1, kind: ClusterPolicy, metadata.name 은 require-labels 입니다. spec.validationFailureAction 을 Enforce 로(또는 규칙의 validate.failureAction 을 Enforce 로), spec.background 를 true 로 두고, spec.rules[0].name 을 check-required-labels 로 지으세요.
2. 같은 규칙에 match.any[0].resources.kinds 로 Pod 를, namespaces 로 pol-lab 을 지정하세요. 그리고 규칙에 exclude.any[0].resources.namespaces 로 kube-system 을 빼세요.
3. validate.pattern.metadata.labels 아래에 app.kubernetes.io/name 과 team 두 라벨을 각각 "?*" 로 요구하세요. 같은 validate 에 message 를 넣되 15자 이상으로, 무엇을 고쳐야 하는지 알 수 있게 쓰세요.
4. kyverno apply /root/policy/validate/require-labels.yaml --resource /opt/lab/fixtures/policy/resources/good-pod.yaml 을 실행해 결과를 /root/policy/validate/out/pass.txt 로 저장하세요. 결과에 require-labels 라는 정책 이름과 통과 표시가 보여야 하고, 실패 건수는 0 이어야 합니다.
5. 같은 정책을 /opt/lab/fixtures/policy/resources/bad-pod.yaml 로 돌려 /root/policy/validate/out/fail.txt 로 저장하세요(실패 건수 1 이상, 정책 이름 포함). 그리고 /root/policy/validate/out/fail-note.txt 에 어떤 라벨이 없어서 걸렸는지 한국어로 적으세요.
6. /root/policy/validate/restrict-registry.yaml 에 두 번째 ClusterPolicy 를 만드세요. 규칙에 validate.deny.conditions.all(또는 any)을 쓰고, 허용 레지스트리로 registry.labhub.io 를 넣어 그 밖의 이미지를 거부하게 하세요. 그다음 /opt/lab/fixtures/policy/resources/bad-registry.yaml 로 돌린 결과를 /root/policy/validate/out/registry.txt 로 저장하세요(거부/실패가 보여야 합니다).
7. restrict-registry.yaml 의 규칙에 preconditions 를 추가하세요. {{ request.operation }} 같은 요청 컨텍스트 변수를 써서 CREATE·UPDATE 일 때만 규칙이 돌게 합니다. 그리고 /root/policy/validate/out/precondition-note.txt 에 preconditions 와 deny 의 차이를 적으세요 — preconditions 가 거짓이면 규칙이 건너뛰어진다는 점과, deny 는 규칙이 실행된 결과로 거부한다는 점이 둘 다 들어가야 합니다.
8. require-labels.yaml 을 good-pod 와 bad-pod 둘 다 --resource 로 넣고 --policy-report 로 실행해 /root/policy/validate/out/policy-report.yaml 로 저장하세요(summary.pass 1 이상, summary.fail 1 이상). 그리고 /root/policy/validate/exception.yaml 에 kind: PolicyException 을 만들어 spec.exceptions[0].policyName 을 require-labels, ruleNames 를 check-required-labels, spec.match.any[0].resources.names 를 legacy-batch-* 처럼 이름 단위로 좁히세요.
참고
- 기본 실행 형태는
kyverno apply <정책> --resource <매니페스트>입니다.-t는 표,--detailed-results는 상세,--policy-report는 리포트 형태로 출력합니다. - 결과 파일에 정책 이름이 안 보이면
-t나--detailed-results를 붙이세요. 요약 줄만 저장하면 정책 이름이 빠집니다. - 실패가 하나라도 있으면
kyverno apply의 종료 코드가 1 입니다. 파이프라인이 아니라면 그대로 두어도 됩니다. --policy-report출력 앞에 진행 메시지가 섞이면yq가 읽지 못합니다.apiVersion:줄부터 잘라 저장하세요 (sed -n '/^apiVersion:/,$p').- 흔한 실수 1:
exclude를 빼먹는 것. 시스템 네임스페이스까지 대상이 되면 클러스터가 위험해집니다. - 흔한 실수 2: 예외를 정책 전체에 거는 것.
ruleNames와 리소스names로 좁히지 않은 예외는 정책을 끄는 것과 같습니다.
단계 8개
- 정책 뼈대와 강제 모드 정하기
- 적용 대상과 제외 대상 좁히기
- 필수 라벨 패턴과 거부 메시지 쓰기
- 통과해야 할 파드로 돌려 보기
- 위반 파드로 돌려 원인 적기
- 레지스트리를 제한하는 deny 규칙 쓰기
- preconditions 로 규칙 적용 범위 좁히기
- 정책 리포트와 좁은 예외 만들기