정책을 코드로 · mutate 와 generate · 실습
테넌트 온보딩을 자동화하는 생성 정책
목표
새 테넌트 네임스페이스가 만들어지는 순간 기본 보안·자원 리소스가 함께 생기도록 하는 생성 정책을 쓰고, 그 정책이 실제 클러스터에서 동작하려면 무엇이 더 필요한지까지 갖춥니다.
왜 중요한가
새 팀에게 네임스페이스를 하나 내주는 일은 보통 체크리스트로 굴러갑니다. NetworkPolicy 를 걸고, ResourceQuota 를 씌우고, LimitRange 를 넣고, 레지스트리 시크릿을 복사한다. 사람이 하면 언젠가 한 단계를 빠뜨리고, 빠뜨린 것이 하필 기본 차단 정책이면 그 네임스페이스만 몇 달 동안 열려 있게 됩니다. 생성 규칙은 이 체크리스트를 네임스페이스 생성 이벤트에 묶어 버립니다. 여기서 세 가지를 배웁니다. 첫째, 트리거 범위를 라벨로 좁히지 않으면 시스템 네임스페이스까지 대상이 됩니다. 둘째, 시크릿처럼 내용을 정책 파일에 적으면 안 되는 것은 clone 으로 원본만 가리킵니다 — 정책은 git 에 들어가니까요. 셋째, 백그라운드 컨트롤러는 최소 권한으로 설치되므로 만들 리소스 종류의 권한을 따로 붙여야 하고, 권한이 없으면 요청은 성공하고 리소스만 조용히 안 생깁니다. 이 환경에서는 컨트롤러가 돌지 않아 실제 리소스가 생기지는 않고, kyverno CLI 로 로컬 평가한 결과와 정책 YAML 구조로 채점합니다.
단계
1. /root/policy/generate/add-networkpolicy.yaml 에 kind: ClusterPolicy 를 만드세요. spec.rules[0].generate 에 apiVersion: networking.k8s.io/v1, kind: NetworkPolicy, name: default-deny 를 적고, generate.data.spec 에 podSelector: {} 와 policyTypes 를 두되 Ingress 를 반드시 포함하세요.
2. 같은 규칙의 match.any[0].resources.kinds 를 Namespace 로 하고, selector.matchLabels 에 labhub.io/tenant: "true" 를 적어 테넌트 네임스페이스에만 반응하게 하세요.
3. generate.synchronize 를 true 로 두세요. 그리고 /root/policy/generate/out/sync-note.txt 에 켰을 때의 동작(누가 손으로 고치면 되돌린다)과 껐을 때의 차이(만들 때 한 번만 관여한다)를 둘 다 적으세요.
4. /root/policy/generate/clone-registry-secret.yaml 을 만드세요. generate.kind 는 Secret, generate.clone.namespace 는 pol-lab, generate.clone.name 은 registry-creds 입니다. generate.data 는 쓰면 안 되고, 정책 파일 안에 시크릿 내용이 들어가서도 안 됩니다.
5. add-networkpolicy.yaml 의 generate.namespace 를 "{{ request.object.metadata.name }}" 로, generate.name 을 명시하세요. 그리고 /root/policy/generate/out/vars-note.txt 에 정책에서 쓸 수 있는 변수를 정리하되 request.object 와 요청자 정보를 담은 변수(request.operation 또는 request.userInfo)를 반드시 포함하세요.
6. /root/policy/generate/background-rbac.yaml 에 kind: ClusterRole 을 만드세요. rules 에 networkpolicies 를 포함하고 verbs 에 create 와 update 를 넣으세요(동기화를 켰으니 갱신도 필요합니다). metadata.labels 에 rbac.kyverno.io/aggregate-to-background-controller: "true" 같은 집계 라벨을 다세요.
7. kyverno apply /root/policy/generate/add-networkpolicy.yaml --resource /opt/lab/fixtures/policy/resources/target-ns.yaml 을 실행하고, 생성된 NetworkPolicy 매니페스트만 /root/policy/generate/out/generated.txt 로 저장하세요. 실행 요약 줄(pass: ..., error: 0 ...)은 넣지 마세요.
8. /root/policy/generate/tenant-onboarding.yaml 에 규칙 3개짜리 정책을 만드세요. 각 규칙이 각각 NetworkPolicy·ResourceQuota·LimitRange 를 생성하고, 규칙 이름은 서로 달라야 하며, 세 규칙 모두 generate.synchronize: true 여야 합니다. 그리고 /root/policy/generate/out/onboarding-report.json 에 trigger_namespace 를 tenant-alpha 로, generated 배열에 생성될 리소스 3건 이상을 kind 키를 포함해 담으세요(ResourceQuota 가 반드시 들어가야 합니다).
참고
- 트리거 픽스처는
/opt/lab/fixtures/policy/resources/target-ns.yaml이고, 이름은tenant-alpha, 라벨은labhub.io/tenant: "true"입니다. - 7번 결과 파일에
error라는 글자가 들어가면 채점이 실패합니다. 요약 줄에는error: 0이 포함되니 생성 매니페스트만 남기세요. generate.clone과generate.data는 둘 중 하나만 쓸 수 있습니다.- 흔한 실수 1: 4번 정책 파일에 시크릿 값을 흉내 내어 적는 것.
password·token같은 문자열이 파일에 있으면 clone 을 쓰는 이유가 사라집니다. - 흔한 실수 2: 8번에서 규칙 이름을 복사해 그대로 두는 것. 이름이 겹치면 정책이 거절됩니다.
단계 8개
- 기본 NetworkPolicy 를 만드는 규칙 쓰기
- 트리거와 대상 셀렉터 좁히기
- 동기화 켜고 그 의미 정리하기
- 원본을 복사하는 clone 규칙 쓰기
- 요청 컨텍스트 변수로 대상 정하기
- 생성 권한을 위한 ClusterRole 쓰기
- 트리거 리소스로 돌려 생성 결과 저장하기
- 온보딩 정책 묶음과 결과 보고서 만들기