You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`postgres-prod-shard-0-rw` Service(ownerRef=PostgresCluster postgres-prod)의 selector 가 `postgres.keiailab.io/role: primary` 를 요구하지만, STS pod 3개 모두 해당 라벨이 없어 endpoints 가 6일+ `` — 이 svc 를 DATABASE_URL 로 쓰는 world-real-debt 앱이 "No route to host" 로 전면 실패.
그동안 PostgresCluster CR 은 PHASE=Ready / "all subsystems ready" 로 정상 보고 (rw endpoint 공동을 감지하는 조건 없음).
PG 자체는 건강: pod-0 = primary(pg_is_in_recovery=f), pod-1/2 replica. 임시 복구로 pod-0 에 수동 라벨 부여 → endpoints 즉시 복구, 앱 정상화.
근본원인 (코드 조사)
현행 코드(main, v0.4.0-beta.5-reseed 배포 기준)에는 `postgres.keiailab.io/role` 라벨을 pod 에 스탬프하는 로직이 존재하지 않음 (grep 전수: tls.go 의 server-tls 용도뿐). `SelectorLabels()`(internal/controller/names.go:135)는 role 인자를 `app.kubernetes.io/component` 로만 매핑.
현행 빌더는 headless svc(builders.go:623) + router 용 client svc(builders.go:646)만 생성 — `-rw` svc 생성/유지 코드 없음. 잔존 `-rw` svc 는 구버전 산출물이 ownerRef 로 남은 고아.
`postgres.keiailab.io/instance-role` 라벨도 fence runbook(failover/pvc_fence_runbook.go:78)이 읽기만 하고 쓰는 쪽이 없음.
정식 primary 공표는 CR `status.shards[].primary.endpoint`(headless pod DNS)뿐 — 앱(k8s Service 소비자)이 failover 를 추적할 안정 write endpoint 가 없음 (shardingMode=none + router off + Pooler 미사용 구성에서 진입점 공백).
failover 시 라벨이 새 primary 로 이동하지 않음 → rw svc 가 강등된 replica 를 가리켜 쓰기 실패/정합성 위험 (수동 라벨의 더 나쁜 실패 모드).
제안 fix 방향 (택1 또는 병행)
reconcile 루프에서 `status.shards[].primary.pod` 기준으로 pod 라벨(`postgres.keiailab.io/role=primary`, 나머지 멤버는 제거)을 지속 보장 + `-rw` svc 를 정식 관리 대상으로 복귀 (CNPG `-rw` 패턴 정합).
또는 selector-less `-rw` Service + operator 가 EndpointSlice 를 직접 primary 로 유지 (라벨 경합 제거).
최소한: 잔존 `-rw` svc 를 GC 하고 문서에 공식 진입점(예: Pooler 의무) 명시 + rw endpoint 공동을 Ready 조건에 반영.
참고
임시조치 롤백: `kubectl label pod -n data postgres-prod-shard-0-0 postgres.keiailab.io/role-`
증상 (라이브 실측, 2026-07-06, keiailab k3s data ns)
근본원인 (코드 조사)
재발 조건
제안 fix 방향 (택1 또는 병행)
참고