destroyed 상태 endpoint에 대해 manager가 route를 무한 재생성하여 routings 테이블이 무한 증식함
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
## 요약
`lifecycle_stage='destroyed'` 상태인 endpoint에 대해 매니저가 계속 route(routing)를 생성하며, 생성된 route는 전부 `failed_to_start`로 끝난다. 매니저가 떠 있는 동안 무한히 누적되어 `routings` 테이블이 계속 증가한다.
## 재현 환경
- 환경: 로컬 개발 서버 (10.82.130.172)
- 버전: 26.8.0rc1 / main `feccbe55d` / alembic head `c1a7d3f05e28`
- DB: PostgreSQL 16.3-alpine (halfstack)
- 계정: admin@lablup.com (superadmin)
- 데이터: 다른 호스트(10.122.10.215)의 운영 데이터를 백업 복원한 상태
## 재현 방법
1. `lifecycle_stage='destroyed'` 이면서 `replicas > 0` 인 endpoint가 존재하는 DB 상태를 준비한다 (본 건에서는 백업 복원 결과 해당 endpoint가 453개 존재했다).
1. 매니저를 기동한다 (`./dev start all`).
1. 수 분간 대기 후 `routings` 테이블의 행 수 변화를 관찰한다.
```sql
-- 최근 10분간 생성된 route를 endpoint의 lifecycle_stage 별로 집계
SELECT e.lifecycle_stage, count(DISTINCT r.endpoint) AS endpoints, count(*) AS new_routings
FROM routings r JOIN endpoints e ON e.id = r.endpoint
WHERE r.created_at > now() - interval '10 min'
GROUP BY 1 ORDER BY 3 DESC;
```
## 기대 동작
`destroyed` 상태의 endpoint는 종료된 상태이므로 replica 재조정 대상에서 제외되어야 하며, 새로운 route가 생성되지 않아야 한다.
## 실제 동작
`destroyed` endpoint에 대해 route가 계속 생성되고 전부 `failed_to_start`로 종료된다.
관측값 (매니저 기동 후 약 10분 시점):
| 항목 | 값 |
|---|---|
|—|—|
|---|---|
| 최근 10분간 신규 route | 351건 — **전부** `status='failed_to_start'` |
|---|---|
| 신규 route를 만든 endpoint | 35개 — **전부** `lifecycle_stage='destroyed'` |
|---|---|
| 해당 endpoint들의 `replicas` | 전부 `1` |
|---|---|
| DB 전체에서 `destroyed` + `replicas > 0` endpoint | 453개 |
|---|---|
| `destroyed` endpoint 총계 | 454개 (`ready`는 2개뿐) |
|---|---|
| 증가 속도 | 약 117행/분 |
|---|---|
| `routings` 테이블 증가량 | 약 1.9 MB/시간 |
|---|---|
`ready` 상태 endpoint는 2개뿐인데도(`replicas` 각각 0, 1) route 생성은 오직 `destroyed` endpoint에서만 발생했다.
시간 경과에 따른 실측:
```
15:31:22 routings=107667 failed_to_start=312
15:31:42 routings=107667 failed_to_start=351
15:32:02 routings=107706 failed_to_start=351
```
### 장기 운영 환경에서의 누적 규모
동일 데이터의 원본 호스트(10.122.10.215)에서는 DB가 \*6GB\*까지 증가했고, 그 대부분이 `failed_to_start` route \*239만 건\*과 그에 연동된 히스토리 테이블(`route_history`, `replica_group_history`, `deployment_history`)이었다. 백업 시 이 데이터를 제외하자 22MB(압축)로 줄었다.
## 원인 추정
미파악 — 본 리포트는 관측 사실 기록 목적이며 원인 분석은 수행하지 않았다. `lifecycle_stage='destroyed'` endpoint가 manager / sokovan deployment reconcile 로직에서 replica 재조정(scale-up) 대상에서 제외되지 않고 있는 것으로 추정된다.
## 영향
- `routings` 및 연동 히스토리 테이블이 무한 증가 → DB 용량 고갈
- 장기 운영 환경에서 DB 6GB 도달 (실측)
- route 생성/실패 사이클이 계속 돌면서 스케줄러 부하 발생
## 관련 컴포넌트
- 테이블: `routings`, `endpoints`, `route_history`, `replica_group_history`, `deployment_history`
- 컴포넌트: manager / sokovan deployment reconcile
JIRA Issue: BA-7175
Contributor guide
Research direction
Start by tracing the manager and sokovan deployment reconcile logic for endpoints with lifecycle_stage='destroyed' and replicas > 0. Reproduce with ./dev start all and the provided SQL query, then verify that destroyed endpoints no longer create routes or failed_to_start records and that routings and related history tables stop growing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, python
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100