Tenant Boundaries and an App Factory
한국어 원문으로 표시합니다.
목표
AppProject 로 테넌트 경계를 선언하고 ApplicationSet 두 종류로 Application 을 찍어내는 매니페스트를 작성한 뒤, 그 경계에 대응하는 실제 네임스페이스와 ResourceQuota 를 클러스터에 올립니다.
왜 중요한가
멀티테넌시는 두 층으로 이뤄집니다. 위층은 "누가 무엇을 선언할 수 있는가" 이고 아래층은 "그 선언이 자원을 얼마나 쓸 수 있는가" 입니다. AppProject 는 위층만 담당합니다. destinations 로 배포 대상을 좁혀도 그 네임스페이스가 노드를 다 먹는 것은 막지 못하고, 그것은 ResourceQuota 의 몫입니다. 반대로 ResourceQuota 만 있으면 테넌트가 남의 저장소를 소스로 걸거나 ClusterRoleBinding 을 만드는 것을 막지 못합니다. 두 층을 같이 세워 봐야 각 도구의 사정거리가 몸에 남습니다.
단계
/root/capa-project/디렉터리를 만들고appproject.yaml에 kindAppProject,metadata.namecapa-tenants,metadata.namespaceargocd를 쓰세요.spec.sourceRepos에https://gitea.homelab.internal/platform/*를,spec.destinations[0]에 serverhttps://kubernetes.default.svc와 namespacecapa-team-*를 넣으세요.- 같은 파일의
spec.clusterResourceWhitelist에 group"", kindNamespace를 넣고,spec.namespaceResourceBlacklist에는 group""의ResourceQuota와LimitRange두 종류를 넣으세요. spec.roles[0]에 namedeployer를 두고, policies 에p, proj:capa-tenants:deployer, applications, sync, capa-tenants/*, allow를 포함시키고, groups 에capa-platform을 넣으세요.spec.syncWindows에 kinddeny, schedule0 0 * * 0,6, duration24h, applications*인 항목을 하나 만드세요./root/capa-project/appset-list.yaml에 kindApplicationSet,metadata.namecapa-tenants-list를 쓰고spec.goTemplate를true로 켜세요.spec.generators[0].list.elements에tenant키 값이 각각alpha,bravo,charlie인 항목 3개를 넣고,spec.template.spec.project를capa-tenants로 지정하세요./root/capa-project/appset-matrix.yaml에 kindApplicationSet,metadata.namecapa-tenants-matrix를 쓰고spec.goTemplate를true로 켜세요.spec.generators[0].matrix.generators에 정확히 두 개를 넣되 하나는 repoURL 이https://gitea.homelab.internal/platform/tenants.git이고directories[0].path가apps/*인 git 제너레이터, 다른 하나는 원소가 하나 이상인 list 제너레이터로 하세요.- 클러스터에 네임스페이스
capa-team-alpha,capa-team-bravo,capa-team-charlie세 개를 실제로 만들고 각각 라벨capa.io/tenant값을alpha,bravo,charlie로 붙이세요. - 세 네임스페이스 각각에 이름이
tenant-quota인 ResourceQuota 를 실제로 만드세요.spec.hard.pods는10,spec.hard["requests.cpu"]는2입니다.
참고
kubectl create quota tenant-quota --hard=pods=10,requests.cpu=2 -n <네임스페이스>로 빠르게 만들 수 있습니다.- 매니페스트 검증은
yq '.spec.clusterResourceWhitelist' /root/capa-project/appproject.yaml처럼 필드만 뽑아 보세요. - 흔한 실수 1: 화이트리스트와 블랙리스트에 같은 종류를 넣는 것. 두 필드는 스코프가 다릅니다.
- 흔한 실수 2: matrix 아래에 제너레이터를 하나만 넣는 것. 곱집합은 두 개일 때만 성립합니다.
AppProject 의 허용 소스와 배포 대상
/root/capa-project/ 디렉터리를 만들고 appproject.yaml 에 kind AppProject, metadata.name capa-tenants, metadata.namespace argocd 를 쓰세요. spec.sourceRepos 에 https://gitea.homelab.internal/platform/* 를, spec.destinations[0] 에 server https://kubernetes.default.svc 와 namespace capa-team-* 를 넣으세요.
sourceRepos 와 destinations 는 둘 다 허용 목록입니다. destinations 의 namespace 필드에는 와일드카드를 쓸 수 있습니다.
화이트리스트와 블랙리스트
같은 파일의 spec.clusterResourceWhitelist 에 group "", kind Namespace 를 넣고, spec.namespaceResourceBlacklist 에는 group "" 의 ResourceQuota 와 LimitRange 두 종류를 넣으세요.
클러스터 스코프는 기본이 전면 금지라 열어야 할 것을 적고, 네임스페이스 스코프는 기본이 전면 허용이라 닫아야 할 것을 적습니다. 방향이 반대라는 점만 잡으면 됩니다.
프로젝트 역할과 그룹 매핑
spec.roles[0] 에 name deployer 를 두고, policies 에 p, proj:capa-tenants:deployer, applications, sync, capa-tenants/*, allow 를 포함시키고, groups 에 capa-platform 을 넣으세요.
정책 문자열은 p, SUBJECT, RESOURCE, ACTION, OBJECT, EFFECT 여섯 칸입니다. 프로젝트 역할의 주체는 proj:프로젝트명:역할명 형태를 씁니다.
주말에는 동기화를 막기
spec.syncWindows 에 kind deny, schedule 0 0 * * 0,6, duration 24h, applications * 인 항목을 하나 만드세요.
syncWindows 항목은 kind, schedule, duration, applications 로 이뤄집니다. schedule 은 창이 열리는 시각을 가리키는 크론이고 duration 이 창의 길이입니다.
list 제너레이터와 goTemplate
/root/capa-project/appset-list.yaml 에 kind ApplicationSet, metadata.name capa-tenants-list 를 쓰고 spec.goTemplate 를 true 로 켜세요. spec.generators[0].list.elements 에 tenant 키 값이 각각 alpha, bravo, charlie 인 항목 3개를 넣고, spec.template.spec.project 를 capa-tenants 로 지정하세요.
list 제너레이터의 elements 는 임의의 키를 가진 맵의 배열입니다. 조건이나 반복을 쓰려면 spec 바로 아래에 템플릿 엔진을 바꾸는 불리언 하나를 켜야 합니다.
matrix 제너레이터로 곱집합 만들기
/root/capa-project/appset-matrix.yaml 에 kind ApplicationSet, metadata.name capa-tenants-matrix 를 쓰고 spec.goTemplate 를 true 로 켜세요. spec.generators[0].matrix.generators 에 정확히 두 개를 넣되 하나는 repoURL 이 https://gitea.homelab.internal/platform/tenants.git 이고 directories[0].path 가 apps/* 인 git 제너레이터, 다른 하나는 원소가 하나 이상인 list 제너레이터로 하세요.
matrix 아래의 generators 는 정확히 두 개여야 곱집합이 됩니다. git 제너레이터는 directories 로 디렉터리를 스캔하고 각 디렉터리마다 파라미터를 하나씩 냅니다.
테넌트 네임스페이스 3개 만들기
클러스터에 네임스페이스 capa-team-alpha, capa-team-bravo, capa-team-charlie 세 개를 실제로 만들고 각각 라벨 capa.io/tenant 값을 alpha, bravo, charlie 로 붙이세요.
여기서부터는 실제 클러스터입니다. 이름과 라벨 값이 서로 대응되도록 만드세요. 반복 작업이니 셸 루프를 써도 좋습니다.
자원 경계를 세우는 ResourceQuota
세 네임스페이스 각각에 이름이 tenant-quota 인 ResourceQuota 를 실제로 만드세요. spec.hard.pods 는 10, spec.hard["requests.cpu"] 는 2 입니다.
ResourceQuota 의 spec.hard 는 맵이고 키에 점이 들어갑니다. AppProject 가 그린 것은 문법적 경계일 뿐이라는 점을 떠올리면 이 단계의 의미가 분명해집니다.