Cloudturing blog

고가용성을 단순화했다: Valkey Sentinel을 제거한 이유

Cloudturing Team 발행: 2026. 08. 26 16:00 수정: 2026. 08. 25 10:04

Valkey Sentinel HA를 단일 Standard Valkey로 단순화한 의사결정

3줄 요약

  • Spot 기반 Valkey 데이터 노드와 Sentinel을 여러 개 운영했지만, 선점 후 서로 다른 primary를 인식하고 replication이 끊기는 장애가 발생했다.
  • 실제 메모리 사용량과 복구 요구를 다시 평가해 Sentinel과 replica를 제거하고 단일 Standard Valkey로 단순화했다.
  • HA의 구성요소 수가 아니라 독립 장애 도메인, 정기 failover 검증 능력, RTO·RPO와 운영 복잡성을 함께 비교해야 한다.

배경: 왜 처음에는 Sentinel을 선택했나

Valkey는 세션, 짧은 수명의 대화 상태, 캐시와 만료 이벤트처럼 사용자 요청 경로 가까이에 있었다. 한 인스턴스가 내려가면 여러 서비스가 동시에 영향을 받을 수 있으므로 처음에는 primary와 replica, Sentinel을 조합한 고가용성 구성이 자연스러운 선택처럼 보였다.

Valkey Sentinel은 primary와 replica를 모니터링하고, 여러 Sentinel의 합의로 장애를 판단하며, replica를 새 primary로 승격하고, 클라이언트에 현재 primary 주소를 알려준다. 제대로 배치하고 반복 검증한다면 유효한 HA 방식이다.

비용을 낮추기 위해 데이터 노드와 Sentinel 상당수를 GKE Autopilot Spot 위에 두고, Sentinel에는 anti-affinity와 stable/spot 혼용을 적용했다. 구성도상으로는 replica와 감시자가 여러 개였고, 한 Pod가 사라져도 나머지가 복구할 것으로 기대했다.

실제로 발생한 증상

Spot 선점 후 Valkey와 Sentinel Pod가 다시 생성되는 과정에서 구성원들의 상태 인식이 갈라졌다.

  • 한 데이터 노드는 자신을 primary로 인식했지만 연결된 replica가 없었다.
  • 다른 데이터 노드는 이미 사라진 이전 primary 주소를 계속 바라봤다.
  • 일부 Sentinel은 서로 다른 primary 주소를 보고 있었다.
  • 애플리케이션 클라이언트가 묻는 Sentinel에 따라 연결 대상이 달라질 여지가 생겼다.

겉으로는 Pod가 여러 개 Running이었지만, “하나의 쓰기 경로로 합의된 클러스터”라는 본래 목적은 달성하지 못했다. 고가용성 구성요소가 장애를 흡수하기보다 새로운 상태 조합과 복구 절차를 만들고 있었다.

원인 분석: Sentinel이 나빴던 것이 아니다

Sentinel 자체를 원인으로 결론 내리면 교훈을 놓친다. 공식 문서는 robust deployment를 위해 최소 세 Sentinel을 서로 독립적으로 실패한다고 믿을 수 있는 머신이나 가용 영역에 배치하고, 개발 또는 운영에서 failover를 주기적으로 시험하라고 권고한다. 또한 비동기 replication이므로 장애 중 확인된 쓰기의 완전 보존을 보장하지 않는다는 경계도 있다.

우리 구성의 문제는 다음 조건이 겹친 데 있었다.

  1. 데이터 노드와 감시자 다수가 같은 Spot 선점 특성에 노출됐다.
  2. 재생성된 Pod의 주소와 Sentinel이 저장한 상태를 안정적으로 수렴시키는 운영 검증이 부족했다.
  3. 실제 데이터 사용량은 각 Pod 수 MiB에서 수십 MiB 수준으로 작았지만, 구성과 클라이언트 접속 경로는 여러 서비스에 걸쳐 복잡했다.
  4. 자동 failover가 실제 RTO를 줄이는지 정기적으로 재현하지 못한 채 구성요소 수만 유지하고 있었다.

결국 논리적 replica 수는 많았지만 독립 장애 도메인과 검증된 복구 절차라는 HA의 핵심이 약했다.

검토한 선택지와 트레이드오프

1. 기존 Sentinel 구성을 더 단단하게 만든다

데이터 노드와 Sentinel을 서로 다른 가용 영역과 Standard 용량에 배치하고, 영속 상태와 announce 설정을 정비하며, failover 훈련을 자동화할 수 있다. 가장 높은 가용성을 목표로 한다면 올바른 방향이다. 대신 작은 캐시 워크로드에 비해 운영·비용 부담이 컸다.

2. 관리형 캐시로 전환한다

인프라 운영 책임을 줄일 수 있지만 제품 특성, 비용, 네트워크, 지원 기능과 마이그레이션 범위를 다시 검토해야 했다. 즉시 장애를 단순하게 해결하는 범위를 넘어섰다.

3. 단일 Standard Valkey로 단순화한다

자동 failover와 replica 읽기를 포기하는 대신, 선점되지 않는 한 인스턴스와 한 Service 주소로 접속 경로를 단순화한다. 장애 시 수동 또는 재배포 기반 복구가 필요하고 캐시·세션 일부를 잃을 수 있다. 당시 실제 사용량, 운영 인력, 복구 요구에서는 이 단점이 복잡한 미검증 HA보다 명확하고 관리 가능하다고 판단했다.

적용한 해결 방법

인프라에서는 Sentinel Service와 Deployment, 세 개의 HA 데이터 노드를 제거하고 단일 StatefulSet과 ClusterIP Service로 바꿨다. Spot selector를 제거하고 Standard provisioning을 명시했다. 메모리 상한과 eviction 정책은 유지해 캐시가 무제한으로 커지지 않도록 했다.

애플리케이션에서는 Sentinel 목록과 primary 이름을 이용한 클라이언트 설정을 제거하고 단일 Service에 직접 연결하도록 바꿨다. 읽기 전용 replica 역할을 기대하던 클라이언트도 direct 연결로 통일했다. 이 변화는 인프라만 먼저 바꾸면 모든 서비스가 연결에 실패하므로, 클라이언트 코드와 Valkey 배포를 같은 전환 절차로 다뤘다.

검증 방법과 운영 결과

전환 후에는 다음을 확인했다.

  • Valkey Pod가 Spot이 아닌 Standard 실행 위치에 스케줄되는가
  • 설정한 maxmemoryallkeys-lru 정책이 실제 런타임에 적용됐는가
  • 개발·운영의 논리 DB 분리가 유지되는가
  • 챗봇, Gateway, Engine, Console 계열 서비스가 모두 PING과 실제 읽기·쓰기에 성공하는가
  • key expiration을 소비하는 subscriber가 정상 동작하는가
  • 재배포 뒤 Pending, CrashLoopBackOff, probe failure가 없는가

전환의 직접적인 결과는 “자동 복구 능력 증가”가 아니라 상태 공간의 축소였다. 누가 primary인지 묻는 경로, Sentinel별 인식 차이, replica link 복구라는 장애 조합이 사라졌다. 대신 단일 인스턴스 장애라는 명확한 위험을 받아들였다.

포기한 것과 보완해야 할 것

단일 구성은 고가용성이 아니다. Pod 또는 실행 기반에 장애가 나면 재시작 동안 캐시와 세션 기능이 영향을 받는다. persistence를 사용하지 않는 데이터는 유실될 수 있다. 따라서 다음 보완이 필요하다.

  • Valkey를 정본 저장소로 사용하지 않는다.
  • 캐시 miss 시 Cloud SQL 등 정본에서 복구 가능한 경로를 둔다.
  • 세션 유실이 사용자에게 어떤 경험을 만드는지 명시한다.
  • 메모리와 연결 수, 재시작 이벤트를 관측한다.
  • 실제 요구 RTO·RPO가 높아지면 Sentinel, Cluster 또는 관리형 서비스를 다시 평가한다.

지금 다시 한다면

처음부터 “HA가 필요하다”가 아니라 데이터별 손실 허용 시간을 표로 만든다. 캐시, 로그인 세션, 활성 대화, 이벤트 신호는 같은 Valkey에 있어도 RPO와 복구 방법이 다르다. 그중 가장 엄격한 데이터 때문에 전체 구성을 복잡하게 할지, 엄격한 데이터만 다른 저장소로 옮길지를 비교할 것이다.

Sentinel을 선택한다면 세 대를 띄운 시점이 완료가 아니다. 서로 독립적인 장애 도메인에 있는지, 상태 파일과 네트워크 주소가 재시작 후에도 일관되는지, 클라이언트가 Sentinel을 올바르게 지원하는지, 정기 failover 테스트가 자동화됐는지를 완료 조건으로 삼을 것이다.

참고 자료