A Generation Policy That Automates Tenant Onboarding
한국어 원문으로 표시합니다.
목표
새 테넌트 네임스페이스가 만들어지는 순간 기본 보안·자원 리소스가 함께 생기도록 하는 생성 정책을 쓰고, 그 정책이 실제 클러스터에서 동작하려면 무엇이 더 필요한지까지 갖춥니다.
왜 중요한가
새 팀에게 네임스페이스를 하나 내주는 일은 보통 체크리스트로 굴러갑니다. NetworkPolicy 를 걸고, ResourceQuota 를 씌우고, LimitRange 를 넣고, 레지스트리 시크릿을 복사한다. 사람이 하면 언젠가 한 단계를 빠뜨리고, 빠뜨린 것이 하필 기본 차단 정책이면 그 네임스페이스만 몇 달 동안 열려 있게 됩니다. 생성 규칙은 이 체크리스트를 네임스페이스 생성 이벤트에 묶어 버립니다. 여기서 세 가지를 배웁니다. 첫째, 트리거 범위를 라벨로 좁히지 않으면 시스템 네임스페이스까지 대상이 됩니다. 둘째, 시크릿처럼 내용을 정책 파일에 적으면 안 되는 것은 clone 으로 원본만 가리킵니다 — 정책은 git 에 들어가니까요. 셋째, 백그라운드 컨트롤러는 최소 권한으로 설치되므로 만들 리소스 종류의 권한을 따로 붙여야 하고, 권한이 없으면 요청은 성공하고 리소스만 조용히 안 생깁니다. 이 환경에서는 컨트롤러가 돌지 않아 실제 리소스가 생기지는 않고, kyverno CLI 로 로컬 평가한 결과와 정책 YAML 구조로 채점합니다.
단계
/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를 반드시 포함하세요.- 같은 규칙의
match.any[0].resources.kinds를Namespace로 하고,selector.matchLabels에labhub.io/tenant: "true"를 적어 테넌트 네임스페이스에만 반응하게 하세요. generate.synchronize를true로 두세요. 그리고/root/policy/generate/out/sync-note.txt에 켰을 때의 동작(누가 손으로 고치면 되돌린다)과 껐을 때의 차이(만들 때 한 번만 관여한다)를 둘 다 적으세요./root/policy/generate/clone-registry-secret.yaml을 만드세요.generate.kind는Secret,generate.clone.namespace는pol-lab,generate.clone.name은registry-creds입니다.generate.data는 쓰면 안 되고, 정책 파일 안에 시크릿 내용이 들어가서도 안 됩니다.add-networkpolicy.yaml의generate.namespace를"{{ request.object.metadata.name }}"로,generate.name을 명시하세요. 그리고/root/policy/generate/out/vars-note.txt에 정책에서 쓸 수 있는 변수를 정리하되request.object와 요청자 정보를 담은 변수(request.operation또는request.userInfo)를 반드시 포함하세요./root/policy/generate/background-rbac.yaml에kind: ClusterRole을 만드세요.rules에networkpolicies를 포함하고verbs에create와update를 넣으세요(동기화를 켰으니 갱신도 필요합니다).metadata.labels에rbac.kyverno.io/aggregate-to-background-controller: "true"같은 집계 라벨을 다세요.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 ...)은 넣지 마세요./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번에서 규칙 이름을 복사해 그대로 두는 것. 이름이 겹치면 정책이 거절됩니다.
기본 NetworkPolicy 를 만드는 규칙 쓰기
/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 를 반드시 포함하세요.
생성 규칙은 만들 리소스의 apiVersion·kind·name·namespace 를 먼저 적습니다. 내용을 정책에 직접 쓰는 키가 따로 있습니다.
트리거와 대상 셀렉터 좁히기
같은 규칙의 match.any[0].resources.kinds 를 Namespace 로 하고, selector.matchLabels 에 labhub.io/tenant: "true" 를 적어 테넌트 네임스페이스에만 반응하게 하세요.
무엇이 만들어질 때 반응할지를 match 에 적습니다. 모든 네임스페이스에 만들면 시스템 네임스페이스까지 대상이 되니 라벨로 좁히세요.
동기화 켜고 그 의미 정리하기
generate.synchronize 를 true 로 두세요. 그리고 /root/policy/generate/out/sync-note.txt 에 켰을 때의 동작(누가 손으로 고치면 되돌린다)과 껐을 때의 차이(만들 때 한 번만 관여한다)를 둘 다 적으세요.
켜면 만든 뒤에도 계속 지켜봅니다. 껐을 때와 무엇이 달라지는지를 파일로 적어야 통과합니다.
원본을 복사하는 clone 규칙 쓰기
/root/policy/generate/clone-registry-secret.yaml 을 만드세요. generate.kind 는 Secret, generate.clone.namespace 는 pol-lab, generate.clone.name 은 registry-creds 입니다. generate.data 는 쓰면 안 되고, 정책 파일 안에 시크릿 내용이 들어가서도 안 됩니다.
시크릿 내용을 정책 파일에 적으면 정책이 곧 유출 경로가 됩니다. 원본이 어디에 있는지만 알려 주는 방식이 있고, 내용을 직접 적는 키와는 함께 쓸 수 없습니다.
요청 컨텍스트 변수로 대상 정하기
add-networkpolicy.yaml 의 generate.namespace 를 "{{ request.object.metadata.name }}" 로, generate.name 을 명시하세요. 그리고 /root/policy/generate/out/vars-note.txt 에 정책에서 쓸 수 있는 변수를 정리하되 request.object 와 요청자 정보를 담은 변수(request.operation 또는 request.userInfo)를 반드시 포함하세요.
만들어진 네임스페이스 이름은 요청 오브젝트에서 꺼냅니다. 정책에서 쓸 수 있는 변수 세 가지를 정리해야 통과합니다.
생성 권한을 위한 ClusterRole 쓰기
/root/policy/generate/background-rbac.yaml 에 kind: ClusterRole 을 만드세요. rules 에 networkpolicies 를 포함하고 verbs 에 create 와 update 를 넣으세요(동기화를 켰으니 갱신도 필요합니다). metadata.labels 에 rbac.kyverno.io/aggregate-to-background-controller: "true" 같은 집계 라벨을 다세요.
백그라운드 컨트롤러는 스스로 아무 권한이 없습니다. 동기화를 켰다면 만드는 것 말고 갱신도 필요합니다. 권한을 모아 가는 집계 라벨도 잊지 마세요.
트리거 리소스로 돌려 생성 결과 저장하기
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 ...)은 넣지 마세요.
저장할 것은 생성된 리소스 매니페스트입니다. 실행 요약 줄은 넣지 마세요 — 채점이 오류 문자열을 찾습니다.
온보딩 정책 묶음과 결과 보고서 만들기
/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 가 반드시 들어가야 합니다).
네트워크·할당량·기본 리소스 세 가지를 한 정책 안 서로 다른 규칙으로 만듭니다. 규칙 이름이 겹치면 안 되고 전부 동기화가 켜져 있어야 합니다.