Repository navigation
feat: Cueue 프로젝트 권한·프로비저닝 라벨 추가 (AIP-3419) - #125
Merged
Merged
Conversation
Coaster 5.2 에서 SchedulingQueue 가 Cueue 로 대체되면서, Coaster 가 프로젝트별 Cueue 를 생성할 전제 조건을 project-controller 가 제공해야 한다. - Cueue DTO 6개. nodeSelector/conditions 는 V1LabelSelector/V1Condition 재사용. 이 컨트롤러는 Cueue 를 읽거나 리컨실하지 않으므로 인포머에 등록하지 않는다 - 프로젝트 역할별 cueues 규칙 — 매니저 get/patch/update, 멤버 get. list 는 Cluster scope 라 resourceNames 로 좁혀지지 않아 부여하지 않는다 (주면 전체 프로젝트 목록이 노출된다. 프론트는 UserAuthorityReview 로 집계한다) - 노드에 project-name.aipub.ten1010.io/<proj> 라벨. reconcileNodeAnnotations 와 같은 성격의 파생 상태라 isProjectManaged 게이트를 맞췄다 - 네임스페이스에 provisioning-enabled 라벨 + node-selector 어노테이션. NamespaceReconciler 에 annotation 리컨실 경로를 신설했다 - projectNamespaceFilter 에 annotation 비교 추가 — informer resync period 가 0 이라 빠지면 어노테이션이 훼손돼도 재기동 전까지 복구되지 않는다 auto-enqueue 라벨은 어드민이 직접 설정하므로 읽지도 쓰지도 않고, 외부가 붙인 값이 보존되는지만 테스트로 고정했다.
이 티켓의 요구사항은 프로비저닝 전제 조건(노드·네임스페이스 라벨/어노테이션) 리컨실과 프로젝트 역할별 Cueue RBAC 둘뿐이다. 두 가지 모두 Cueue 객체 모델을 쓰지 않는다 — RBAC 룰은 apiGroup·resource 를 문자열로 받고, 라벨·어노테이션 리컨실이 만지는 객체는 V1Node 와 V1Namespace 뿐이다. 초판에 추가한 V1alpha1Cueue 외 nested 5종은 src/main·src/test 통틀어 참조처가 0건이었다. 인포머·K8sApiProvider 에도 등록하지 않아 역직렬화될 경로 자체가 없으므로 컴파일만 되는 dead code 였다. 미사용 상수 CUEUE_RESOURCE_KIND 도 함께 제거한다(RBAC 이 쓰는 CUEUE_RESOURCE_PLURAL 은 유지). 필요해지는 시점은 Cueue validating webhook 을 넣기로 결정할 때다. CRD 스키마는 kubernetes/examples/crd.yaml 과 Confluence 에 남아 있어 복원 비용이 낮다. 테스트 275건 통과(DTO 에 테스트가 없어 수치 변동 없음).
juu-n-oo
force-pushed
the
feat/AIP-3419
branch
from
October 8, 2026 10:07
8173f5e to
2ec9535
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AIPub 5.2 코스터 신버전에서
SchedulingQueue가 삭제되고Cueue(cueues.coaster.ten1010.io, Cluster scope)가 그 자리를 대신한다. Cueue 는 프로젝트마다 하나씩 프로젝트와 같은 이름으로 Coaster 가 자동 생성하는데, 그 전제 조건(네임스페이스 라벨·어노테이션, 노드 라벨)을 project-controller 가 만들어 줘야 한다. 프로젝트 역할별 Cueue 접근 권한도 함께 부여한다.docs/aip-3419-cueue-provisioning/🔍 여기만은 꼭 봐주세요!!
1.
list를 부여하지 않았다 — 문서와 다른 선택이라 리뷰가 필요합니다.Confluence 문서 §9 는 매니저·멤버에게
get/list를 적어뒀지만list는 넣지 않았습니다.list는 컬렉션 요청이라resourceNames로 좁혀지지 않습니다. 규칙에 넣어도 매칭되지 않아 거부되고, 동작시키려면resourceNames를 떼야 하는데 Cueue 가 Cluster scope 라 전체 Cueue(= 전체 프로젝트 목록)가 모든 멤버에게 노출됩니다.UserAuthorityReview권한 분석으로 접근 가능한 리소스를 집계해 쓰므로 필요하지도 않습니다.gpuConfigs·nodeResources규칙이get만 주는 것과 같은 이유입니다.2. 노드 라벨에
isProjectManaged게이트를 뒀습니다.getAllBoundProjects(V1Node)가project-managed라벨을 보지 않아 비관리 노드도 바인딩으로 잡힙니다.reconcileNodeAnnotations가 바로 그 이유로 bound-projects 어노테이션을 게이트하고 있고, 새 라벨은 같은 성격의 프로젝트 파생 상태라 동작을 맞췄습니다. 접두 제거를 게이트 앞에 둬서 노드가 프로젝트 관리에서 빠질 때 기존 라벨이 회수됩니다.→
project-managed=false인데 프로젝트에 바인딩된 노드는 라벨을 받지 못합니다. 의도한 동작이 맞는지 봐주세요.3.
projectNamespaceFilter()에 annotation 비교를 추가했습니다.informer resync period 가
0이라 주기적 재리컨실이 없습니다. 이 비교가 빠지면 누가node-selector어노테이션을 지워도 Project ADD/DELETE 나 재기동 전까지 복구되지 않습니다 — 조용히 깨지는 경로라 테스트로 고정했습니다.4. Cueue DTO 를 만들지 않았습니다 — 초판에서 걷어냈습니다.
이 티켓의 요구사항은 프로비저닝 전제 조건(라벨·어노테이션) 리컨실과 프로젝트 역할별 RBAC 둘뿐이고, 두 가지 모두 Cueue 객체 모델을 쓰지 않습니다 — RBAC 룰은 apiGroup·resource 를 문자열로 받고(
CUEUE_RESOURCE_PLURAL하나면 끝), 라벨·어노테이션 리컨실이 만지는 객체는V1Node·V1Namespace뿐입니다.초판에
V1alpha1Cueue외 nested 5종을 추가했었는데src/main·src/test통틀어 참조처가 0건이었습니다. 인포머·K8sApiProvider에도 등록하지 않아 역직렬화될 경로 자체가 없어, 컴파일만 되는 dead code 였습니다. 미사용 상수CUEUE_RESOURCE_KIND와 함께 제거했습니다 (8173f5e).필요해지는 시점은 Cueue validating webhook 을 넣기로 결정할 때입니다(아래 후속 작업 참조 — 현 시점에는 불필요로 결론). CRD 스키마가
kubernetes/examples/crd.yaml과 Confluence §1 에 남아 있어 복원 비용은 낮습니다.Changes
RBAC (
ReconciliationService)ProjectApiConstants에CUEUE_RESOURCE_PLURALcueuesApiRule을gpuConfigsApiRule뒤에 추가. 매니저get/patch/update, 멤버get,resourceNames= 프로젝트 이름프로비저닝 전제 조건
project-name.aipub.ten1010.io/<proj>: ""—reconcileNodeLabels가boundProjects를 받도록 시그니처 변경cueue.coaster.ten1010.io/provisioning-enabled: "true"+ annotationcueue.coaster.ten1010.io/node-selector.reconcileNamespaceAnnotations신설 후NamespaceReconciler의 생성·갱신 양쪽 경로에 배선OnUpdateFilterFactory.projectNamespaceFilter()에 annotation 비교 추가기타
kubernetes/examples/crd.yaml에 Cueue CRD append범위 밖
cueue.coaster.ten1010.io/auto-enqueue라벨은 이 PR 범위가 아닙니다. 프로젝트별 on/off 운영 설정이라 Project 에서 파생할 수 있는 값이 아니고, AIPub 어드민이 직접 설정합니다(aipub-admin이cluster-admin바인딩이라 별도 권한 작업 불필요). 컨트롤러가 매 주기"true"를 심으면 끈 설정이 되살아나므로 읽지도 쓰지도 않으며, 외부가 붙인 값이 보존되는지만 테스트로 고정했습니다.Helm 차트 RBAC 와 어드민 ClusterRole 도 변경이 없습니다 — 컨트롤러 SA 는 이미
*/*/*, 어드민은cluster-admin바인딩입니다.하위 호환성 · 배포 영향
ClusterRoleReconciler가 룰 리스트를List.equals(순서 비교)로 판정하는데 규칙을 중간에 삽입했기 때문입니다. 의도된 1회성이며 이후 멱등입니다.aipub-web변경 불필요 — 프론트는UserAuthorityReview+ 이름별 GET 폴백 구조입니다.새로 생긴 제약
project-name.aipub.ten1010.io/접두로 시작하는 키를 NodeGroup 의spec.nodeSelector에 쓰면 안 됩니다.getBoundNodeGroupsByNodeSelector가 부분집합 판정이라, 프로젝트 A 의 키를 selector 로 가진 NodeGroup 을 프로젝트 B 에 바인딩하면 A 의 노드가 B 에도 전이 바인딩돼 테넌트 경계가 넓어집니다. 현재 이 키를 쓰는 NodeGroup 은 없고(워크스페이스 전체 grep 0건), 상수 Javadoc 에 금지를 명시했습니다.Test plan
자동 — 완료
./gradlew compileJava compileTestJava test→ 275 tests / 0 failuresproject-name.*라벨 제거isProjectManaged게이트 — 비관리 노드에 라벨이 붙지 않고, 관리에서 빠지면 회수된다auto-enqueue및 기타 모르는 라벨·어노테이션 보존get/patch/update, 멤버get, 양쪽 다list없음crd.yamlmulti-doc 파싱사람이 클러스터에서 — c10 실측 완료 (2026-10-08,
project-controller:1.10.0-31)kubectl auth can-i get cueues.coaster.ten1010.io/<proj> --as=oidc:<매니저>→ yespatch/update(매니저) → yes ·list/delete(매니저) → noget(멤버) → yes ·list/patch/update(멤버) → noresourceNames정상 동작)provisioning-enabled라벨 /node-selector어노테이션 부착project-name.aipub.ten1010.io/<proj>라벨 부착 (노드당 40~50개 프로젝트,project-managed=true게이트 정상)spec.nodeSelector변환 확인 — 맨 라벨 키가matchExpressions: [{key: …, operator: Exists}]로 들어옴status.nodes가 실제로 채워짐 —cueue.coaster.ten1010.io/managed=true인vnode1.pnode12에 바인딩된 큐(abc·hjw·say·vision-group·yshee·monitoring-test) 전부["vnode1.pnode12…"],observedGeneration == generation후속 작업 (이 PR 범위 밖 — 별도 티켓 필요)
spec.nodes쓰기 — 현 시점 조치 불필요로 결론 (2026-10-08). RBAC 은 서브필드로 좁힐 수 없어 매니저는 자기 Cueue 의spec.nodes에 임의 노드 이름을 넣을 수 있습니다(c10 server dry-run 으로 확인 — 남의 프로젝트 Cueue 접근은Forbidden). 그럼에도 조치하지 않는 근거:patch/update를 조건 없이 부여하고, §7 이 FE 가 사용자 권한으로spec.priority·spec.pods를 직접 패치하는 모델을 전제합니다. §3 필드표의spec.nodes"AIPub에서는 사용하지 않음"(쓰는 주체-)은 활용하지 않는다는 사실 서술이지 쓰기 금지 요구가 아닙니다.coaster/coaster-scheduler-installer가interQueuePolicy: FirstScheduling이고(77개 Cueue 전부BlockedByHigherCueue=False / reason=InterQueuePolicyFirstScheduling), 이 모드에서는 상위 큐가 하위 큐·미소속 Pod 을 막지 않습니다.managed=true노드도 현재vnode1.pnode12하나뿐입니다.status.nodes계산에는 프로젝트 소속 필터가 없습니다((spec.nodes ∪ selector) ∩ managed=true). 바로잡는다면 Coaster 의 계산 쪽이 자연스럽습니다 — project-controller 에 validating webhook 을 다는 건 남의 CR 계약을 대신 지키는 꼴입니다.interQueuePolicy를FirstAllocating으로 전환 ② Cueue Managed 노드 증가. 넣게 되면 그때 위에서 걷어낸 Cueue DTO 가 필요해집니다.cueue.coaster.ten1010.io/managed=true외에project.aipub.ten1010.io/project-managed=true도 필요합니다(후자가 없으면 project-controller 가project-name.*라벨을 아예 붙이지 않고, 컨트롤러가 기본값을false로 심으므로 기본 상태가 off). §4 는 "프로젝트에 속한 노드 중에서 Cueue Managed 로 지정된 노드" 라고만 해서 첫 조건이 드러나지 않습니다. 실제로example-project의status.nodes가[]인 원인입니다. (@김지헌)project-name.aipub.ten1010.io/<proj>를 "예시"라고 명시했고 키 형태는 project-controller 가 정하도록 돼 있어 그대로 썼습니다. c10 에서 Coaster 가 맨 라벨 키를matchExpressions: [{key: project-name.aipub.ten1010.io/<proj>, operator: Exists}]로 정상 변환했고, 그 결과로status.nodes까지 채워지는 것을 확인했습니다.list를 주지 않은 전제가 "프론트는UserAuthorityReview로 집계한다" 입니다. Prioritization 화면에서 매니저/멤버가 자기 프로젝트 큐를 실제로 보고 수정할 수 있는지 확인이 필요합니다.list미부여(현행getby name)로 확정했으므로(2026-10-08), 안 되면 설계를 다시 열어야 합니다. (@권현경)patch가 필요한데, 그대로 열면project.aipub.ten1010.io/project·allowlist 라벨까지 바꿀 수 있어 위험합니다. 연다면 경로(백엔드가 자기 SA 로 중계 등)를 따로 설계해야 합니다.schedulerName === 'coaster'인 Pending Pod 을 모으는 조건으로는 더 이상 아무것도 잡히지 않습니다. 대기 Pod 은 Cueue 의status.pods에서 가져와야 합니다. FE 작업이라 이 PR 밖입니다. (AIP-3242 에서 다뤄지는지 확인 필요)🚀 Release Version
v5.2.0