LabHub
배우기 러닝패스 코스

KCA — Kyverno 인증 어소시에이트 · 정책 작성 심화 — 조건·외부 데이터·자동 생성·정리 · 이론

규칙 하나가 일곱 컨트롤러를 덮는 이유, 그리고 정책이 지우는 것

LabHub 에서 이어서 보기

한 줄 요약

파드에 대해 쓴 규칙은 Kyverno 가 Deployment·StatefulSet·CronJob 등 파드 컨트롤러용 규칙으로 자동 생성(autogen) 해서 정책의 status.autogen 에 붙입니다. 반대로 리소스를 지우는 일은 validate·mutate 와 별개의 정책 종류인 CleanupPolicy 와 TTL 라벨이 맡습니다. 두 기능 모두 규칙 본문 밖에서 일어나기 때문에, 어떤 조건에서 켜지고 꺼지는지를 알아야 합니다.

왜 이게 필요했나

"이미지는 사내 레지스트리에서만" 같은 검증은 결국 파드에 대한 검증입니다. 그런데 파드를 직접 만드는 일은 거의 없고 Deployment·DaemonSet·StatefulSet·Job·CronJob 이 파드를 만듭니다. 컨트롤러마다 파드 템플릿의 위치가 다릅니다 — Deployment 는 spec.template.spec, CronJob 은 spec.jobTemplate.spec.template.spec. 같은 규칙을 컨트롤러 수만큼 복사해 두면 하나를 고칠 때 나머지를 빠뜨리게 됩니다. [autogen 문서](https://kyverno.io/docs/policy-types/cluster-policy/autogen/)는 그래서 "파드에 대해서만 쓴 규칙에서 상위 컨트롤러용 규칙을 자동 생성한다" 고 설명합니다.

정리는 다른 문제입니다. 실험용 네임스페이스에 남은 Deployment, 며칠 지난 Job 의 파드처럼 "만들 때는 필요했지만 언제 지울지 아무도 정하지 않은" 리소스가 쌓입니다. 어드미션 컨트롤러는 들어오는 요청만 보기 때문에 이미 있는 것을 지울 수 없습니다. 그래서 [cleanup 문서](https://kyverno.io/docs/policy-types/cleanup-policy/)가 설명하는 별도 컨트롤러와 스케줄이 필요합니다.

어떻게 동작하나

autogen 이 만드는 것

match.any[].resources.kindsPod 뿐인 validate 규칙을 만들면, Kyverno 는 정책의 status.autogen.rules 아래에 두 규칙을 더 넣습니다. 하나는 autogen-<규칙이름> 으로 DaemonSet·Deployment·Job·StatefulSet·ReplicaSet·ReplicationController 를 대상으로 하고 패턴을 spec.template.spec 아래로 옮긴 것, 다른 하나는 autogen-cronjob-<규칙이름> 으로 CronJob 을 대상으로 spec.jobTemplate.spec.template.spec 아래로 옮긴 것입니다. ReplicaSet 과 ReplicationController 도 포함되지만, 기본 리소스 필터가 이 둘을 제외하고 있어서 실제로 적용하려면 Kyverno ConfigMap 의 resourceFilters 를 손봐야 한다는 주의가 붙어 있습니다.

패턴만 옮기는 것이 아닙니다. preconditions 의 request.object.metadata.* 같은 변수도 컨트롤러에 맞게 request.object.spec.template.metadata.* 로 번역됩니다. 이것이 원하는 동작이 아니면 — 예를 들어 Deployment 자체의 애너테이션을 보고 싶다면 — request."object".metadata... 처럼 object 를 큰따옴표로 감싸 번역을 막습니다.

켜고 끄는 조건

동작은 정책 애너테이션 pod-policies.kyverno.io/autogen-controllers 로 조절합니다. 값에 Deployment,Job 처럼 컨트롤러를 나열하면 그것만 생성하고, none 이면 전혀 생성하지 않습니다. OpenKruise 의 CloneSet 처럼 파드 템플릿을 품은 커스텀 리소스도 이 애너테이션에 이름을 적으면 대상이 됩니다.

자동으로 꺼지는 경우도 있습니다. matchexcludenames·selector·annotations 가 있으면 건너뜁니다(컨트롤러에는 그 필터가 맞지 않을 수 있어서입니다). 종류가 Pod 를 넘어 다른 kind 를 같이 적어도 생성하지 않고, JSON patch 를 쓰는 mutate 규칙도 제외됩니다. 이때 주의할 점은, autogen 이 꺼져도 컨트롤러가 만든 파드는 여전히 파드 규칙에 걸린다는 것입니다. Job 이 만든 파드를 빼고 싶으면 preconditions 에서 request.object.metadata.ownerReferences[].kindAnyNotIn 으로 비교하라고 문서가 예를 듭니다.

CleanupPolicy 와 ClusterCleanupPolicy

정리 정책은 네임스페이스 범위의 CleanupPolicy 와 클러스터 범위의 ClusterCleanupPolicy 두 가지이며 API 는 kyverno.io/v2 입니다. 구조는 익숙합니다 — match/exclude 로 고르고, 선택적 conditions 로 좁히고(이때 대상 리소스의 값은 target.* 로 참조합니다), context 로 외부 데이터를 가져오고, schedule 에 cron 형식으로 실행 시각을 적습니다.

apiVersion: kyverno.io/v2kind: ClusterCleanupPolicymetadata:  name: cleandeployspec:  match:    any:    - resources:        kinds: [Deployment]        selector:          matchLabels:            canremove: "true"  conditions:    any:    - key: "{{ target.spec.replicas }}"      operator: LessThan      value: 2  schedule: "*/5 * * * *"  deletionPropagationPolicy: Foreground

정리 정책은 항상 이미 있는 리소스를 대상으로 하므로, 어드미션 때만 알 수 있는 subjects·Roles·ClusterRolesmatch/exclude 에 쓸 수 없고, operations[] 는 적을 수는 있지만 무시됩니다. 지우는 주체는 cleanup 컨트롤러이고, 최소 권한 원칙에 따라 지우려는 리소스마다 ClusterRole 을 더 주어야 할 수 있습니다. 문서는 delete 동사를 가진 ClusterRole 예시와 함께, 권한이 모자라면 정책을 설치할 때 Kyverno 가 검증해서 알려 준다고 적습니다.

deletionPropagationPolicy 는 종속 리소스를 어떻게 다룰지 정합니다. Foreground 는 종속 리소스를 먼저 지운 뒤 본체를 지우고, Background 는 본체를 먼저 지우고 종속은 비동기로, Orphan 은 종속을 남깁니다. 지정하지 않으면 API 서버의 기본 동작을 따릅니다.

TTL 라벨

정책을 쓰지 않고도 리소스 하나에 cleanup.kyverno.io/ttl 라벨을 붙이면 지워집니다. 값은 두 형식입니다 — ISO 8601 절대 시각(2023-10-04 또는 2023-10-04T003000Z) 또는 라벨을 관찰한 시점부터의 남은 시간(5m, 4h, 1d). 인식하지 못하는 형식은 경고를 냅니다. 라벨이 붙은 리소스를 Kyverno 가 감시하지만, 실제 삭제 해상도는 cleanup 컨트롤러의 ttlReconciliationInterval 플래그(기본 1m)가 정합니다. TTL 로 지울 때의 전파 정책은 애너테이션 cleanup.kyverno.io/propagation-policy 로 줍니다.

라벨이기 때문에 다른 기능과 이어집니다. mutate 규칙으로 특정 리소스에 TTL 라벨을 자동으로 붙이거나, validate 규칙으로 특정 그룹이 특정 네임스페이스에 이 라벨을 붙이지 못하게 막을 수 있습니다.

문서가 붙인 폐기 예고

시험 범위와 별개로 알아 둘 것이 있습니다. 2026-09 시점의 kyverno.io 문서는 CleanupPolicy·ClusterCleanupPolicy 를 v1.19 부터 deprecated 로 표시하고 v1.20 에서 제거하며, CEL 기반 DeletingPolicy 가 같은 기능을 제공한다고 적습니다. [업그레이드 문서](https://kyverno.io/docs/installation/upgrading/)는 ClusterPolicy·Policy(kyverno.io/v1) 자체도 같은 시점에 deprecated 라고 밝힙니다. 개념은 그대로이니 이 글의 내용은 유효하지만, 새로 쓰는 정책이라면 어느 종류로 쓸지 확인할 필요가 있습니다.

현장에서 만나는 모습

한 플랫폼 팀이 "파드에 requests/limits 필수" 정책을 넣고 나서 exclude 로 특정 애너테이션이 있는 파드를 빼려고 했습니다. 그 순간 autogen 이 조용히 꺼졌고, Deployment 로 만든 파드는 걸리는데 Deployment 자체를 만드는 요청은 통과하는 어긋남이 생겼습니다. 문서의 처방대로 exclude 대신 preconditions 에서 request."object".metadata.annotations 를 검사하도록 바꾸자 autogen 이 다시 붙었습니다.

정리 쪽에서는 ClusterCleanupPolicy 를 만들었는데 아무것도 지워지지 않는 일이 흔합니다. 대개 cleanup 컨트롤러에 그 리소스의 delete 권한이 없거나, conditionstarget.*request.object.* 로 잘못 적은 경우입니다.

다음 퀴즈에서 확인할 것

퀴즈에서는 autogen 이 생성하는 규칙 이름과 대상 종류, 애너테이션 값 none 의 뜻, names·selector·annotations 가 있을 때의 동작, 그리고 CleanupPolicy 의 schedule·target.*·TTL 라벨 형식·ttlReconciliationInterval 기본값을 묻습니다.