Goal
백엔드에서 VM 스냅샷을 효율적으로 관리하는 기능을 구현한다. 크게 두 가지 유형의 스냅샷을 지원한다: 롤백 스냅샷 (인스턴스 내부 상태 복원)과 외부 스냅샷 (오브젝트 스토리지 기반 이식성 있는 이미지).
Requirements
롤백 스냅샷
- 각 롤백 스냅샷은 현재 동작 중인 VM의 위치 정보를 포함해야 한다.
- 롤백 요청은
VM uuid + snapshot uuid 조합으로 특정 대상을 식별한다.
- 롤백 스냅샷 수는 최대 ~10개 수준으로 예상되므로
[]rollback.Snapshot 슬라이스로 충분하다. (map 불필요)
Cores -> []rollback.Snapshot 구조로 관리하며, 탐색 흐름은 아래와 같다:
seekRollbackSnapshot(vmUUID, snapshotUUID) 로 해당 코어 내 스냅샷 탐색
- 존재하면 코어에 전달할 쿼리 생성 후 전송 (탐색 함수는 VM 서비스 레이어에서 재사용)
- 존재하지 않으면
No such rollback snapshot 에러 반환
예상 자료구조:
package rollback
type Snapshot struct {
UUID string
ParentVMUUID string
Timestamp time.Time
// 추가 필드
}
// DB 저장 시 primary key: snapshot UUID, 인덱스: parentVMUUID, timestamp
외부 스냅샷
- 롤백 스냅샷 포함 여부와 관계없이 모든 VM을 외부 스냅샷으로 export할 수 있어야 한다.
- 외부 스냅샷은 오브젝트 스토리지에 저장한다.
- 오퍼레이션은 아래 단위로 분리한다:
| 오퍼레이션 |
방향 |
설명 |
| PullBaseImage(uuid | name) |
Object Storage → Core |
인스턴스 생성 전 base image 다운로드 |
| CreateVM(spec) |
Core 내부 |
이미지 준비 완료 후 VM 생성 |
| PushExternalSnapshot(vmUUID) |
Core → Object Storage |
생성된 VM 이미지를 외부 스냅샷으로 업로드 |
| ExportSnapshot(vmUUID) |
Core → Object Storage |
롤백 유무 무관하게 특정 VM을 외부 스냅샷으로 export |
Notes
- 자료구조 결정 근거: 롤백 스냅샷은 최대 ~10개이므로
[]rollback.Snapshot 슬라이스로 충분하다. 조회 패턴이 uuid 기반 순차 탐색이므로 map의 추가 복잡도를 도입할 이유가 없다.
- 오브젝트 스토리지 방향: 코어 → 오브젝트 스토리지 방향의 push/pull로 구현. 오브젝트 스토리지가 특정 IP로 직접 push하는 방식은 지원이 불확실하므로 코어 주도 방식으로 통일한다.
- 외부 스냅샷 선행 조건: 오브젝트 스토리지 구현 및 코어의
PullBaseImage 기능이 완료되어야 외부 스냅샷 작업을 시작할 수 있다.
- gRPC 전환 검토: 현재 구조에서 외부 스냅샷의 각 오퍼레이션(
PullBaseImage, PushExternalSnapshot 등)은 HTTP 단일 엔드포인트 안에 묶이기 쉬운데, 이를 명시적으로 분리하려면 설계상의 의지가 필요하다. gRPC를 도입하면 .proto 에 각 RPC를 선언하는 것 자체가 오퍼레이션 경계를 강제하므로 자연스럽게 분리된다. 또한 base image처럼 큰 파일을 전송할 때 server-side streaming으로 진행률을 실시간으로 내려줄 수 있어 UX와 에러 추적 모두 유리하다. 현 시점에서 바로 전환하기는 어렵지만, 외부 스냅샷 설계 시 오퍼레이션 단위를 gRPC로 이전하기 쉬운 형태로 잡아두는 것이 좋을 것 같다.
Goal
백엔드에서 VM 스냅샷을 효율적으로 관리하는 기능을 구현한다. 크게 두 가지 유형의 스냅샷을 지원한다: 롤백 스냅샷 (인스턴스 내부 상태 복원)과 외부 스냅샷 (오브젝트 스토리지 기반 이식성 있는 이미지).
Requirements
롤백 스냅샷
VM uuid + snapshot uuid조합으로 특정 대상을 식별한다.[]rollback.Snapshot슬라이스로 충분하다. (map 불필요)Cores -> []rollback.Snapshot구조로 관리하며, 탐색 흐름은 아래와 같다:seekRollbackSnapshot(vmUUID, snapshotUUID)로 해당 코어 내 스냅샷 탐색No such rollback snapshot에러 반환예상 자료구조:
외부 스냅샷
Notes
[]rollback.Snapshot슬라이스로 충분하다. 조회 패턴이 uuid 기반 순차 탐색이므로 map의 추가 복잡도를 도입할 이유가 없다.PullBaseImage기능이 완료되어야 외부 스냅샷 작업을 시작할 수 있다.PullBaseImage,PushExternalSnapshot등)은 HTTP 단일 엔드포인트 안에 묶이기 쉬운데, 이를 명시적으로 분리하려면 설계상의 의지가 필요하다. gRPC를 도입하면.proto에 각 RPC를 선언하는 것 자체가 오퍼레이션 경계를 강제하므로 자연스럽게 분리된다. 또한 base image처럼 큰 파일을 전송할 때 server-side streaming으로 진행률을 실시간으로 내려줄 수 있어 UX와 에러 추적 모두 유리하다. 현 시점에서 바로 전환하기는 어렵지만, 외부 스냅샷 설계 시 오퍼레이션 단위를 gRPC로 이전하기 쉬운 형태로 잡아두는 것이 좋을 것 같다.