분산 작업 스케줄러를 etcd로 구축하는 가이드
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
DevOps
대상자
- Go 언어 기초 지식 보유자(코루틴, 채널 경험자)
- 분산 시스템에 관심 있는 개발자
- etcd 사용법이 생소한 초보자 포함
- 난이도: 중급 (Go 기초 + 분산 시스템 개념 필요)
핵심 요약
- etcd는 분산 시스템에서의 작업 스케줄링을 위한 최적의 도구
- Raft 컨센서 프로토콜 기반의 고가용성 키-벨류 저장소
- Watch, Lease, 분산 락 등 핵심 기능 제공
- Go 기반 구현 예시
clientv3
라이브러리 사용json.Marshal
과etcd.Put
을 통한 작업 정보 저장Txn
을 활용한 중복 작업 방지 로직- 분산 시스템의 주요 문제 해결
- 단일 고장 지점 방지, 작업 중복 방지, 상태 동기화 보장
섹션별 세부 요약
1. 분산 작업 스케줄러의 필요성
- 기존 방식의 한계
- cron
은 단일 노드 기반으로 스케일링 불가
- 다중 노드 환경에서 상태 불일치 발생 가능성
- 분산 스케줄러의 핵심 요구사항
- 고가용성, 작업 중복 방지, 실시간 상태 동기화
- 레더스(Leader Election) 기반의 작업 분배
- etcd의 역할
- 분산 락을 통한 작업 할당
- Watch 기능으로 작업 상태 실시간 감지
2. etcd의 핵심 기능과 장점
- Raft 기반의 고가용성
- 3개 이상의 노드 구성 가능
- 자원 소모 최소화 (ZooKeeper 대비)
- 주요 기능
- Key-Value 저장소: 작업 ID, 스케줄 시간, 상태 등 저장
- Watch: 작업 상태 변경 시 실시간 알림
- Lease: 노드 활성 상태 감지 (10초 간격으로 lease 갱신)
- 분산 락: 작업 중복 방지 (txn + lease 활용)
- 대체 솔루션 비교
- Redis: 최종일관성(eventual consistency)
- ZooKeeper: 복잡한 설정 필요
3. etcd 기반 스케줄러 구현 예시
- 데이터 구조 설계
```go
type Task struct {
ID string json:"id"
Name string json:"name"
ScheduleAt time.Time json:"schedule_at"
Status string json:"status"
}
```
- 작업 저장 로직
```go
func storeTask(cli *clientv3.Client, task Task) error {
data, _ := json.Marshal(task)
key := "/tasks/" + task.ID
_, err := cli.Put(context.Background(), key, string(data))
return err
}
```
- 작업 할당 로직
```go
func grabTask(cli *clientv3.Client, taskID string) bool {
lease, _ := cli.Grant(context.Background(), 10) // 10초 lease
lockKey := "/locks/" + taskID
txn := cli.Txn(context.Background()).
If(clientv3.Compare(clientv3.CreateRevision(lockKey), "=", 0)).
Then(clientv3.OpPut(lockKey, "locked", clientv3.WithLease(lease.ID)))
resp, _ := txn.Commit()
return resp.Succeeded
}
```
- 작업 상태 모니터링
```go
func watchTask(cli *clientv3.Client, taskID string) {
key := "/tasks/" + taskID
for resp := range cli.Watch(context.Background(), key) {
for _, ev := range resp.Events {
log.Printf("작업 상태 변경: %s", ev.Type)
}
}
}
```
4. 실무 적용 시 주의사항
- lease 갱신 주기 설정
- 10초 이상의 lease는 노드 장애 감지 지연 발생 가능
- Txn 조건 설정
- CreateRevision(lockKey) == 0
조건으로 중복 락 방지
- Go 코루틴 활용
- goroutine
으로 watchTask
실행하여 비동기 상태 감지
결론
- etcd는 분산 작업 스케줄러 구축에 최적화된 도구
- Raft 기반의 고가용성과 강한 일관성 제공
- clientv3
라이브러리 활용으로 Go 기반 구현 용이
- 핵심 팁
- lease 갱신 주기와 작업 실행 시간 간격을 동기화 시키기
- Txn
조건을 작업 ID 기반으로 설정하여 중복 방지
- Watch 기능을 Go 코루틴으로 비동기 처리하여 실시간 감지
- 실무 적용 예시
- 데이터베이스 백업, 주문 처리, 웹 크롤러 등 분산 작업 시스템 구축에 활용 가능