etcd를 이용한 아시아 태평양 지역 비디오 트래픽 라우팅

8개 아시아 태평양 시장에 서비스를 제공하는 한 비디오 스트리밍 플랫폼이 지역별 설정을 etcd로 이동함으로써 반복되던 라우팅 오류를 해결했습니다. 라우팅 변경 사항의 전파 시간은 약 1초로 단축되었습니다. 편집자들은 이제 코드 수정 없이도 몇 시간 동안 뮤직 풀(music pool)을 강화할 수 있게 되었으며, 플랫폼은 한국 시청자에게 도쿄 피드를 보내는 문제를 중단했습니다.

기존 방식이 실패한 이유

각 라우터는 요청마다 세 가지 값, 즉 트렌딩 풀(trending pool), 언어별 토크나이저(tokenizer), 그리고 폴백 체인(fallback chain)을 읽었습니다. 새로운 아티스트 홍보, 지역적 장애 대응, 추천 알고리즘 테스트와 같은 비즈니스 결정은 코드 변경이 아닌 이러한 값들에 의해 이루어졌습니다.

초기에는 모든 배포 시 라우팅 테이블이 포함된 JSON 파일을 함께 묶었습니다. 장애 발생 시, 당직 엔지니어가 한 노드에서 파일을 수정하여 트래픽을 백업 풀로 돌렸지만, 나머지 7개 노드는 업데이트하지 않았습니다. 이로 인해 설정 드리프트(config drift)가 발생했습니다. 8개국이 서로 다른 테이블을 실행하게 되었고, "진실"을 검증할 단일 소스가 없었습니다. 서울 시청자를 도쿄로 보냈던 버그가 지속된 이유는 코드는 그대로였지만, 숨겨진 설정만 달랐기 때문입니다.

단일 진실 공급원(Single Source of Truth)으로 etcd를 선택한 이유

팀은 세 가지 옵션을 비교했습니다:

  • SQLite/MySQL – 각 라우터가 데이터베이스를 폴링(poll)해야 하므로 지연 시간이 추가되거나 쿼리가 폭증할 수 있습니다.
  • Consul – 견고한 서비스 디스커버리 도구이지만, 플랫폼에 그 모든 메시(mesh) 기능이 필요하지는 않았습니다.
  • etcd – 키가 변경되는 즉시 클라이언트에 알리는 watch 프리미티브(primitive)를 갖춘 강력한 일관성(strongly consistent)의 키-값 저장소입니다.

watch 기능이 결정적인 역할을 했습니다. 각 라우터가 반복적으로 "변경 사항이 있나요?"라고 묻는 대신, etcd가 업데이트를 푸시할 때까지 라우터는 대기 상태로 머물렀습니다. 불필요한 네트워크 트래픽이 사라졌고, 모든 인스턴스가 동시에 변경 사항을 알게 되었습니다.

시스템을 안전하게 유지하는 패턴

etcd만으로는 모든 리스크를 해결할 수 없었습니다. 엔지니어들은 세 가지 보완적인 패턴을 추가했습니다:

  1. Leases (임대) – 편집자는 임시 부스트를 설정할 수 있습니다(예: 6시간 동안 한국 팝 풀의 가중치 증가). 임대는 자동으로 만료되므로 수동 롤백 없이도 부스트가 사라집니다.
  2. Compare-and-swap (CAS) – 두 사람이 동시에 같은 설정을 편집할 때, CAS는 한 명에게 명확한 오류를 발생시켜 조용한 덮어쓰기를 방지합니다.
  3. Sidecar process (사이드카 프로세스) – PHP는 장기 연결(long-lived connections)을 처리하는 데 어려움이 있습니다. 각 서버의 작은 Go 사이드카가 etcd를 감시하고 라우팅 테이블의 스냅샷을 공유 메모리 파일(/dev/shm)에 작성합니다. PHP는 이 로컬 파일을 읽음으로써 요청 처리 중 네트워크 왕복(round-trip)을 피합니다.

아키텍처에 내장된 회복 탄력성

새로운 설계는 여러 안전망을 추가합니다:

  • Zero-latency reads (제로 지연 읽기) – PHP 핫 패스(hot path)가 로컬 메모리에서 읽으므로, 원격 저장소를 기다리느라 요청이 지연되는 일이 없습니다.
  • Graceful degradation (우아한 성능 저하) – etcd가 다운되더라도 라우터는 마지막으로 확인된 정상 설정을 계속 서비스하여 갑작스러운 장애를 방지합니다.
  • Reliable updates (신뢰할 수 있는 업데이트) – 사이드카가 재연결 로직을 처리하며, etcd 연결이 일시적으로 끊기더라도 변경 사항을 놓치지 않도록 보장합니다.

현장에서의 변화

마이그레이션 후 팀은 오래되었거나 일치하지 않는 라우팅 데이터로 인한 장애가 급격히 감소하는 것을 확인했습니다. 이제 단일 콘솔에서 현재 설정을 볼 수 있으며, 모든 수정 사항은 1초 이내에 8개 지역 모두로 전파됩니다. 임시 부스트는 임대가 만료되면 자동으로 정리되어, 이전에 인적 오류를 유발했던 수동 정리 단계를 제거했습니다.

반론: 사이드카의 비용

사이드카를 추가한다는 것은 서버당 두 번째 프로세스와 PHP 중심 스택에 Go 런타임이 추가됨을 의미합니다. 일부 운영자는 추가적인 메모리 사용과 또 다른 바이너리를 모니터링해야 하는 점을 우려합니다. 실제로 사이드카의 점유율은 미미하며, 특히 PHP가 네트워크 호출에서 차단(block)되지 않는다는 신뢰성 이득이 운영 오버헤드보다 큽니다.

향후 주의 깊게 살펴볼 사항

멀티 리전 서비스를 관리하는 팀은 다음을 모니터링해야 합니다:

  • etcd 상태 메트릭 – 라우팅 계층이 단일 저장소에 의존하므로 쿼럼(quorum) 상태와 지연 시간을 주시해야 합니다.
  • 임대 만료 처리 – 임대 시간을 비즈니스 윈도우에 맞추십시오. 임대 시간이 너무 길면 오래된 부스트가 그대로 유지될 수 있습니다.
  • watch 부하 확장 – 라우터가 늘어남에 따라 watch 연결도 증가하므로, 이에 맞춰 etcd 서버 용량을 계획하십시오.

시사점

여러 리전에 걸쳐 빠르고 조율된 구성 변경이 필요한 서비스의 경우, etcd의 watch, lease, transaction 프리미티브는 파일 기반 구성이나 무거운 메시(mesh) 구조를 대신할 수 있는 가볍고 강력한 일관성을 제공하는 대안이 됩니다. 구성을 푸시 기반의 자가 정화(self-cleaning) 저장소로 전환함으로써 특정 유형의 장애들을 완전히 제거할 수 있었고, 플랫폼이 라우팅 로직을 실시간으로 제어할 수 있게 되었습니다.