KCA — Kyverno 인증 어소시에이트 · mutate 와 generate · 실습
정책이 거절됐는데 원인은 권한이었다
목표
설치된 Kyverno 의 구성요소를 읽고, generate·cleanup 이 거절될 때 컨트롤러 권한을 집계 ClusterRole 로 더해 고치며,
kyverno ConfigMap 의 resourceFilters 와 webhooks 설정이 요청을 어디서 걸러 내는지 실제 요청으로 구분합니다.
왜 중요한가
Kyverno 는 하나의 프로그램이 아니라 어드미션·백그라운드·정리·보고서 네 컨트롤러가 각자의 ServiceAccount 로 도는 시스템입니다.
generate 규칙이 만드는 객체와 정리 정책이 지우는 객체는 요청한 사람이 아니라 그 컨트롤러의 권한으로 처리되므로, 권한이 없으면
정책을 쓰는 순간 어드미션에서 거절됩니다. 설치 매니페스트는 기본 권한을 최소로 두고 라벨로 집계되는 ClusterRole 을 더하게 설계되어 있어,
와일드카드 권한을 주는 대신 필요한 종류와 동사만 더하는 것이 운영의 기본입니다. 반대로 검사를 빼고 싶을 때는 두 자리가 있습니다.
resourceFilters 는 API 서버가 요청을 보낸 뒤 Kyverno 가 무시하는 것이고, 웹훅 namespaceSelector 는 API 서버가 아예 보내지 않는 것입니다.
어느 쪽이든 기본 제외 항목을 지우면 Kyverno 가 자기 자신이나 시스템 네임스페이스를 막는 사고가 납니다.
단계
1. /root/kca-install/inventory.json 에 version(kyverno-admission-controller 이미지의 태그), controllers(kyverno 네임스페이스 Deployment 이름 → spec.replicas 숫자), crd_count(API 그룹이 kyverno.io 로 끝나는 CRD 개수), webhook_configs(이름에 kyverno 가 든 ValidatingWebhookConfiguration·MutatingWebhookConfiguration 이름을 정렬한 배열)를 적으세요.
2. /root/kca-install/02-gen-pdb.yaml 에 ClusterPolicy gen-pdb 를 작성해 적용해 보세요. 규칙 default-pdb 는 라벨 kca.io/pdb=true 인 Namespace 가 생기면 그 안에 PodDisruptionBudget default-pdb(minAvailable 1, selector app=web)를 synchronize true 로 생성합니다. 적용 명령의 출력 전체를 /root/kca-install/gen-denied.txt 에 저장하세요.
3. /root/kca-install/03-role-bg.yaml 에 ClusterRole kca-bg-pdb 를 만들어 라벨 rbac.kyverno.io/aggregate-to-background-controller: "true" 를 붙이고 policy 그룹 poddisruptionbudgets 에 get·list·watch·create·update·delete 만 허용하세요(와일드카드 금지). 그다음 gen-pdb 를 다시 적용하고, 네임스페이스 kca-pdb-a 를 라벨 kca.io/pdb=true 로 만들어 PDB 가 생기는 것을 확인합니다. 생긴 PDB 의 UID 를 적어 두고 PDB 를 지운 뒤 다시 생긴 PDB 의 UID 와 함께 /root/kca-install/pdb.json 에 first_uid, second_uid 로 적으세요.
4. /root/kca-install/04-clean-short.yaml 에 ClusterCleanupPolicy clean-short 를 작성해 적용해 보세요. 네임스페이스 kca-clean 에서 라벨 ttl=short 인 Pod 를 매분(*/1 * * * *) 지웁니다. 적용 명령의 출력 전체를 /root/kca-install/cleanup-denied.txt 에 저장하세요.
5. /root/kca-install/05-role-cleanup.yaml 에 ClusterRole kca-cleanup-pods(라벨 rbac.kyverno.io/aggregate-to-cleanup-controller: "true", core pods 에 get·list·watch·delete 만)를 적용하고 clean-short 를 다시 적용하세요. 네임스페이스 kca-clean 에 라벨 ttl=short 인 Pod short 와 ttl=long 인 Pod long 을 만들고, 다음 정각 분이 지나 short 만 사라진 것을 확인한 뒤 /root/kca-install/cleanup.json 에 long_uid(남은 long 의 UID)와 last_execution(clean-short 의 status.lastExecutionTime)을 적으세요.
6. 네임스페이스 kca-skip 과 kca-ctl 을 만들고 /root/kca-install/06-need-team.yaml 에 ClusterPolicy need-team(background false, 규칙 team, 두 네임스페이스의 Pod 에 team 라벨 요구, Enforce)을 적용하세요. 그다음 kyverno 네임스페이스 ConfigMap kyverno 의 resourceFilters 에 기존 항목을 모두 유지한 채 [Pod,kca-skip,*] 를 덧붙이세요. kca-skip 의 라벨 없는 파드는 받아들여지고 kca-ctl 의 라벨 없는 파드는 계속 거절되어야 합니다.
7. 네임스페이스 kca-sel 을 라벨 kca.io/webhook=skip 으로 만들고 need-team 의 대상 네임스페이스에 kca-sel 을 더해 다시 적용하세요. 그다음 ConfigMap kyverno 의 webhooks 값의 namespaceSelector 에 기존 kube-system·kyverno 제외 조건을 유지한 채 kca.io/webhook NotIn [skip] 조건을 더하세요. Kyverno 가 갱신한 kyverno-resource-validating-webhook-cfg 에 그 조건이 들어가고, kca-sel 의 라벨 없는 파드는 받아들여지며 kca-ctl 은 계속 거절되어야 합니다. resourceFilters 에는 kca-sel 을 넣지 않습니다.
8. /root/kca-install/report.json 에 background_role(generate 권한을 더한 ClusterRole 이름), cleanup_role(정리 권한을 더한 ClusterRole 이름), pdb_regenerated(3단계 두 UID 가 다른지, 불리언), skip_by(kca-skip 을 거른 설정 키: resourceFilters 또는 webhooks), sel_by(kca-sel 을 거른 설정 키), default_exclusions(웹훅 selector 에 남아 있는 기본 제외 네임스페이스 이름을 정렬한 배열)를 적으세요.
참고
- VM 안에 k3s 와 Kyverno v1.19.1(설치 매니페스트, 컨트롤러 각 1개)이 있습니다.
- 계정 권한 확인:
kubectl auth can-i create poddisruptionbudgets.policy --as system:serviceaccount:kyverno:kyverno-background-controller -n <ns> - 저장하지 않고 판정 보기:
kubectl -n <ns> run t --image=nginx:1.27-alpine --dry-run=server - 흔한 실수: resourceFilters 나 webhooks 값을 통째로 새 값으로 바꾸는 것. 기본 제외 항목이 사라집니다.
- 흔한 실수: 집계 ClusterRole 에
*동사를 주는 것. 채점기는 과제의 동사만 있는지 봅니다. - [Customizing Permissions](https://kyverno.io/docs/installation/customization/) · [Cleanup](https://kyverno.io/docs/policy-types/cleanup-policy/) · [Generate Rules](https://kyverno.io/docs/policy-types/cluster-policy/generate/) · [Kubernetes RBAC 집계](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles)
단계 8개
- 설치된 Kyverno 가 무엇으로 이루어져 있나
- 정책은 맞는데 어드미션이 거절했다
- 라벨 하나로 컨트롤러에 권한을 더한다
- 지울 권한이 없는 정리 정책
- 짧은 수명 파드만 정각에 사라졌다
- Kyverno 가 받고도 못 본 척한 요청
- API 서버가 아예 묻지 않게 한다
- 권한과 필터를 어디에 두었는지 보고