KCA — Kyverno Certified Associate
Comparing validate Rules Against the Built-in Policies
한국어 원문으로 표시합니다.
목표
Kyverno ClusterPolicy 로 라벨 필수와 태그 금지 규칙을 작성하고, 같은 검사를 쿠버네티스 내장 ValidatingAdmissionPolicy 로도 실제 클러스터에 올려 두 접근의 차이를 확인합니다.
왜 중요한가
정책 엔진을 도입할지 판단하려면 내장 기능의 사정거리를 알아야 합니다. 필드 하나를 CEL 로 검사하는 것이 전부라면 ValidatingAdmissionPolicy 로 충분하고, 그러면 운영할 컴포넌트가 하나 줄고 웹훅 인증서 갱신을 신경 쓸 일도 하나 줍니다. Kyverno 를 정당화하는 것은 generate 와 mutate, 이미지 검증처럼 내장 정책이 못 하는 일들입니다. 이 실습에서 두 매니페스트를 나란히 만들어 보면 그 경계가 어디인지 손에 남습니다. 또 하나, 규칙마다 강제 수준을 다르게 주는 연습은 실제 도입 절차의 핵심입니다.
단계
/root/kca-validate/디렉터리를 만들고policy.yaml에 apiVersionkyverno.io/v1, kindClusterPolicy,metadata.namekca-require-app-label을 쓰고spec.rules[0].name을check-app-label로 하세요.spec.rules[0].match.any[0].resources.kinds에Pod와Deployment를 넣고, 같은 곳의namespaces에kca-app을 넣으세요.spec.rules[0].validate.message를 채우고,validate.pattern으로metadata.labels의app.kubernetes.io/name이 비어 있지 않은 값이어야 한다고 요구하세요.spec.rules[0].validate.failureAction을Enforce로 두세요. 정책 수준spec.validationFailureAction은 쓰지 마세요.- 두 번째 규칙
deny-latest-tag를 추가하세요.validate.message를 채우고validate.deny.conditions.all[0]에 컨테이너 이미지를 가리키는 key, operator, value 를 넣은 뒤, 이 규칙의validate.failureAction은Audit으로 두세요. spec.rules[0].exclude.any[0].resources.namespaces에kube-system과kyverno를 넣으세요.- 클러스터에 ValidatingAdmissionPolicy
kca-require-app-label을 실제로 만드세요.spec.failurePolicy는Fail,spec.matchConstraints는apps그룹의deployments를 CREATE·UPDATE 로 잡고,spec.validations[0].expression은app.kubernetes.io/name라벨의 존재를 검사하는 CEL 이어야 합니다. - 클러스터에 네임스페이스
kca-app을 라벨kca=enforced와 함께 만들고, ValidatingAdmissionPolicyBindingkca-require-app-label-binding을 실제로 만드세요.spec.policyName은kca-require-app-label,spec.validationActions에는Deny를,spec.matchResources.namespaceSelector.matchLabels에는kca: enforced를 넣으세요.
참고
- CEL 예시로는
has(object.metadata.labels)와 인덱싱을 조합하는 형태가 흔합니다.kubectl explain validatingadmissionpolicy.spec.validations가 도움이 됩니다. - 파일 확인은
yq '.spec.rules[1].validate' /root/kca-validate/policy.yaml처럼 부분만 뽑아 보세요. - 흔한 실수 1:
spec.validationFailureAction을 남겨 둔 채 규칙 단위 필드를 추가하는 것. 이 실습에서는 정책 수준 필드를 지워야 통과합니다. - 흔한 실수 2: 바인딩 없이 ValidatingAdmissionPolicy 만 올리는 것. 정책은 존재해도 아무 요청도 타지 않습니다.
ClusterPolicy 골격
/root/kca-validate/ 디렉터리를 만들고 policy.yaml 에 apiVersion kyverno.io/v1, kind ClusterPolicy, metadata.name kca-require-app-label 을 쓰고 spec.rules[0].name 을 check-app-label 로 하세요.
ClusterPolicy 는 kyverno.io 그룹의 클러스터 스코프 리소스입니다. rules 는 배열이고 각 규칙에는 반드시 이름이 있어야 합니다.
무엇을 고를 것인가
spec.rules[0].match.any[0].resources.kinds 에 Pod 와 Deployment 를 넣고, 같은 곳의 namespaces 에 kca-app 을 넣으세요.
match.any 는 배열이고 각 원소 안의 resources 에 kinds·namespaces·names·selector 를 넣습니다. 대상 종류와 네임스페이스를 함께 좁히면 웹훅을 타는 요청 수가 줄어듭니다.
패턴 매칭으로 필수 라벨 요구
spec.rules[0].validate.message 를 채우고, validate.pattern 으로 metadata.labels 의 app.kubernetes.io/name 이 비어 있지 않은 값이어야 한다고 요구하세요.
pattern 은 검사할 오브젝트 모양을 그대로 그린 뒤 값 자리에 연산자를 넣습니다. 비어 있지 않은 값을 요구하는 연산자가 무엇인지 떠올리세요.
규칙 단위로 강제 수준 정하기
spec.rules[0].validate.failureAction 을 Enforce 로 두세요. 정책 수준 spec.validationFailureAction 은 쓰지 마세요.
정책 수준 필드는 deprecated 이므로 남겨 두면 안 됩니다. 강제 수준은 validate 블록 안으로 내려왔고, 지정하지 않으면 기본이 관찰 모드입니다.
deny.conditions 로 두 번째 규칙 추가
두 번째 규칙 deny-latest-tag 를 추가하세요. validate.message 를 채우고 validate.deny.conditions.all[0] 에 컨테이너 이미지를 가리키는 key, operator, value 를 넣은 뒤, 이 규칙의 validate.failureAction 은 Audit 으로 두세요.
조건은 key, operator, value 세 칸입니다. all 과 any 중 어느 쪽으로 묶을지는 조건이 여러 개일 때 의미가 갈립니다. 이 규칙만 관찰 모드로 두세요.
시스템 네임스페이스 제외
spec.rules[0].exclude.any[0].resources.namespaces 에 kube-system 과 kyverno 를 넣으세요.
exclude 의 구조는 match 와 같습니다. 정책이 Kyverno 자신이나 컨트롤 플레인 구성요소를 막으면 복구가 어려워집니다.
같은 규칙을 내장 정책으로
클러스터에 ValidatingAdmissionPolicy kca-require-app-label 을 실제로 만드세요. spec.failurePolicy 는 Fail, spec.matchConstraints 는 apps 그룹의 deployments 를 CREATE·UPDATE 로 잡고, spec.validations[0].expression 은 app.kubernetes.io/name 라벨의 존재를 검사하는 CEL 이어야 합니다.
ValidatingAdmissionPolicy 는 CRD 가 아니라 쿠버네티스 내장 리소스라 그냥 apply 하면 됩니다. 표현식은 CEL 이고 object 로 검사 대상에 접근합니다.
바인딩과 대상 네임스페이스
클러스터에 네임스페이스 kca-app 을 라벨 kca=enforced 와 함께 만들고, ValidatingAdmissionPolicyBinding kca-require-app-label-binding 을 실제로 만드세요. spec.policyName 은 kca-require-app-label, spec.validationActions 에는 Deny 를, spec.matchResources.namespaceSelector.matchLabels 에는 kca: enforced 를 넣으세요.
내장 정책은 정책과 바인딩 두 오브젝트가 한 쌍입니다. 바인딩이 없으면 정책은 존재만 하고 아무 요청도 타지 않으며, 어떤 동작을 할지도 바인딩이 정합니다.