Skip to content

[Store] Give LOCAL_DISK segments an unmount half, and let the offload RPC honour connect timeouts - #1

Merged
Juhyun-Kim-Memphis merged 1 commit into
our_mainfrom
inf291-localdisk-unmount
Aug 10, 2026
Merged

Juhyun-Kim-Memphis merged 1 commit into
our_mainfrom
inf291-localdisk-unmount

Conversation

@Juhyun-Kim-Memphis

Copy link
Copy Markdown
Collaborator

무엇

LOCAL_DISK 세그먼트에 unmount 반쪽을 주고, offload RPC가 connect 타임아웃을 지키게 한다.

LOCAL_DISK 세그먼트는 클라이언트 만료로만 master를 떠난다. 다른 세그먼트 종류는 클라이언트가 부를 수 있는 unmount RPC가 다 있는데(UnmountSegment·GracefulUnmountSegment·UnmountNoFSegment) UnmountLocalDiskSegment만 ClientMonitorFunc 만료 분기에서 불리는 내부 함수로 존재한다. mount 반쪽은 전 계층에 깔려 있으니 설계 제약이 아니라 빠뜨린 절반이다.

결과: 종료 중인 store가 ping을 멈춘 뒤 최대 client_ttl 동안 자기가 offload한 키의 소유자로 계속 광고된다. 그 창에 들어온 읽기는 더는 서빙할 수 없는 peer에 닿는다.

어떻게

  • MasterService::UnmountLocalDiskSegment(client_id)를 mount 반쪽이 이미 지나간 계층(rpc_service → master_client → client_service)에 노출
  • FileStorage::DrainLocalDiskSegment(grace_period_ms) 추가
  • Python 바인딩 unmount_local_disk_segment(grace_period_seconds) + REST POST /api/unmount_local_disk → preStop에서 호출 가능
  • offload RPC가 MC_RPC_CONNECT_TIMEOUT_MS를 지키도록 수정

실측 (2노드 rig, INF-291)

항목 결과
계획된 scale-in(신규 preStop drain 경유) 8 동시 reader blocked read 0건, 최악 40ms
master의 disk replica 해제 요청 후 1.7s (기존: TTL 만료 30s 대기)
타임아웃 override 없이 crash worker당 read 1건이 33-62s 파킹
MC_RPC_CONNECT_TIMEOUT_MS=1000 적용 후 최악 4.2s
정확성 654,123 reads 바이트 대조, 오답 0

관리 정보

INF-302 fork 관리 체계에 따라 편입한 PR. 이 PR의 머지 = 우리가 이 패치를 채택해 shipping한다는 뜻이며, upstream #3316의 상태와 무관하게 우리 쪽 기록·리뷰는 여기서 관리한다.

… RPC honour connect timeouts

LOCAL_DISK segments can only leave the master by client expiry: every other
segment kind has a client-callable unmount RPC, but UnmountLocalDiskSegment
exists only as an internal function called from the ClientMonitorFunc expiry
branch. A store shutting down therefore keeps advertising itself as the owner
of the keys it offloaded for up to client_ttl, and reads that land in that
window reach a peer that can no longer serve them.

Exposes MasterService::UnmountLocalDiskSegment(client_id) through the layers
the mount half already crosses (rpc_service -> master_client ->
client_service), adds FileStorage::DrainLocalDiskSegment(grace_period_ms),
and surfaces it as the Python binding unmount_local_disk_segment() and
REST POST /api/unmount_local_disk so a preStop hook can call it. Also lets
the offload RPC honour MC_RPC_CONNECT_TIMEOUT_MS.

Measured on a two-node rig: on a planned scale-in through the new preStop
drain, 8 concurrent readers saw zero blocked reads and a 40 ms worst case,
with the master dropping the disk replicas 1.7 s after the request rather
than at TTL expiry 30 s later. The same crash without the timeout override
parked one read per worker for 33-62 s; with MC_RPC_CONNECT_TIMEOUT_MS=1000
the worst case is 4.2 s. 654,123 reads byte-checked across all arms, zero
wrong answers.

Upstream PR: kvcache-ai#3316
Linear: INF-291
@Juhyun-Kim-Memphis Juhyun-Kim-Memphis added the upstream:open upstream PR 제출됨 (열림) label Aug 10, 2026
@Juhyun-Kim-Memphis Juhyun-Kim-Memphis self-assigned this Aug 10, 2026
@Juhyun-Kim-Memphis

Copy link
Copy Markdown
Collaborator Author

라이브 대조 검증 (2026-08-10) — merge 보류, open 유지

ganymede 두 프로덕션 셀의 mooncake tier를 확인한 결과 이 패치는 라이브에 들어가 있지 않다. 따라서 "라이브 반영분"으로 merge하지 않고, upstream 추적 및 향후 채택 대상으로 open(ready for review) 상태로 둔다.

라이브 mooncake는 stock이다

셀 mooncake 이미지 기동 시각
magma-glm-prod lmsysorg/sglang:v0.5.15-cu130 (master 1 + store 5) 2026-08-06
minimax-m3-prod vllm/vllm-openai:v0.25.0 (master 1 + store 6) 2026-08-06

둘 다 stock 이미지 안의 mooncake wheel을 그대로 쓰고, 패치된 wheel/.so를 주입하는 initContainer나 볼륨도 없다.

파드 안에서 직접 확인한 부재 증거

magma-glm-prod-mooncake-store-fkkrk에서:

  • store.so에 unmount_local_disk_segment / DrainLocalDiskSegment 0건 → store_py.cpp의 Python 바인딩 부재
  • mooncake_store_service.py 파일 자체가 없음 → REST POST /api/unmount_local_disk 부재

⚠️ 판정 함정 하나: mooncake_master 바이너리에서 unmount_local_disk_segment 문자열이 1건 걸린다. 이것은 우리 패치의 흔적이 아니다 — stock v0.3.12.post1의 mooncake-store/src/segment.cpp가 이미 그 문자열을 갖고 있다(소스 대조 확인). 우리 패치는 그 위에 store_py.cpp·master_service.cpp·rpc_service.cpp·mooncake_store_service.py 4개 파일에 추가로 넣는데, 라이브에는 그 4곳이 전부 없다.

오늘(2026-08-10) 배포는 mooncake가 아니었다

오늘 재기동된 것은 magma-glm-prod-router 2 pod(02:50·02:53)뿐이고, 그 이미지도 기존 router-sdrelist-20260728-v4 그대로다. mooncake tier는 2026-08-06 이후 손대지 않았다.

그래서 왜 close하지 않는가

  1. upstream PR kvcache-ai/Mooncake#3316이 OPEN이다(2026-08-06 제출). 이 PR이 우리 쪽 추적 포인트다 — upstream이 방치하더라도 리뷰·근거·상태를 여기서 관리한다.
  2. magma engines/README.md가 graceful scale-in 절차의 전제로 이 빌드를 요구한다("mooncake ≥ v0.3.12.post1, rebuilt with the INF-291 patch"). 즉 라이브에 아직 없다는 것은 그 무중단 절차가 아직 쓸 수 없다는 뜻이고, 패치가 불필요하다는 뜻이 아니다.

⇒ 채택(=merge)은 이 빌드를 실제로 배포하는 시점에 한다. 그때까지 open.

참고: 측정 근거는 rig 기준

이 PR 본문의 실측(blocked read 0·40ms·master 1.7s·654,123 reads 바이트 대조)은 2노드 rig에서 얻은 것이고 프로덕션 실측이 아니다. INF-291 기록 참조.

@Juhyun-Kim-Memphis
Juhyun-Kim-Memphis marked this pull request as ready for review August 10, 2026 09:53
@Juhyun-Kim-Memphis

Copy link
Copy Markdown
Collaborator Author

결정 정정 — merge 한다 (직전 코멘트의 "merge 보류" 철회)

직전 코멘트는 "라이브에 없으므로 merge 보류"로 결론지었으나, 그 판단은 브랜치 모델을 잘못 적용한 것이다. 정정한다.

our_main은 트렁크이고 배포는 그 위의 커밋에서 release tag를 따는 것이다(INF-302 확정 규칙 3). 따라서 어떤 패치가 채택되어 our_main에 들어가는 것과, 그 커밋이 이미 배포되었는지는 별개 조건이다. 라이브가 반드시 our_main HEAD여야 할 이유가 없고, 배포 지점보다 HEAD가 앞서 있는 것이 정상 상태다.

이 패치는 리뷰를 통과했고 채택 대상이므로 our_main을 전진시킨다. 배포는 이후 이 트렁크에서 태그를 따서 나간다.

배포 태그는 지금 따지 않는다 — 라이브가 우리 fork 산출물이 아니기 때문

"현재 라이브 상태를 our_main에서 태그로 박제"하는 것도 검토했으나, 사실관계가 그것을 허용하지 않는다:

셀 라이브 mooncake wheel 출처
magma-glm-prod mooncake-transfer-engine-cuda13 0.3.11.post1 lmsysorg/sglang:v0.5.15-cu130 내장
minimax-m3-prod mooncake-transfer-engine 0.3.10.post2 (0da9dfea3) vllm/vllm-openai:v0.25.0 내장

세 가지 이유로 태그를 보류한다:

  1. 라이브는 우리 fork에서 빌드된 것이 아니다. sglang/vllm 이미지에 내장된 stock wheel을 그대로 쓴다 — 우리가 mooncake를 빌드해 올린 적이 없다.
  2. 단일 버전이 아니다. 두 셀이 서로 다른 mooncake 버전을 쓰므로, 태그 하나가 "현재 라이브"를 대표할 수 없다.
  3. 둘 다 our_main base(v0.3.12.post1)도 아니다. 라이브 버전은 그보다 이전이다. base 커밋에 태그를 달면 어느 셀의 라이브와도 일치하지 않는 태그가 된다.

⇒ 진짜 배포 태그는 우리가 mooncake를 실제로 빌드해 배포하는 시점에 our_main에서 딴다. magma engines/README.md가 graceful scale-in 절차의 전제로 이 빌드를 요구하고 있으므로, 그 절차를 켜는 작업이 곧 그 시점이 될 것이다.

유지되는 사실 (직전 코멘트에서 그대로 유효)

  • 이 패치는 현재 라이브에 없다 — 파드 내부 확인: store.so에 우리 심볼 0건, mooncake_store_service.py 파일 부재
  • mooncake_master의 unmount_local_disk_segment 문자열은 stock segment.cpp의 것이지 우리 흔적이 아니다
  • 본문 실측치는 2노드 rig 기준이며 프로덕션 실측이 아니다
  • upstream kvcache-ai/Mooncake#3316 OPEN — 이후 이 PR이 아니라 그쪽에서 upstream 상태를 추적한다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

upstream:merged upstream에 머지됨 (다음 sync 때 탈락 대상)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants