내 잡다한 노트
Service Discovery란? 본문
**Service Discovery(서비스 디스커버리)**는 동적으로 변화하는 분산 환경(특히 마이크로서비스 아키텍처)에서, 애플리케이션들이 서로 위치를 파악하고 통신하기 위해 사용하는 기법/시스템을 말합니다. 예컨대, 각각의 마이크로서비스가 실행 중인 IP/포트 또는 엔드포인트 URL을 자동으로 등록하고, 찾아 쓸 수 있게 하는 과정 전반이 서비스 디스커버리입니다.
아래에서는 개념, 필요성, 대표 패턴과 구현 방식, 그리고 실제 사례 등을 단계적으로 설명하겠습니다.
1. 왜 서비스 디스커버리가 필요한가?
- 동적 스케일링
- 컨테이너 기반이나 클라우드 환경에서 서비스는 자동으로 스케일 업/다운 됩니다.
- 이때 서비스 인스턴스(IP, 포트)가 실시간으로 바뀌기 때문에, 클라이언트가 서비스의 위치를 하드코딩하면 곤란합니다.
- 고가용성(HA) & 장애 복구
- 일부 인스턴스가 죽거나 재시작되더라도, 정상 인스턴스를 찾아야 합니다.
- 수동으로 위치 정보(엔드포인트)를 수정하지 않도록, 자동화된 ‘발견 기제(Discovery Mechanism)’가 필요합니다.
- 마이크로서비스 아키텍처의 필수 요소
- 여러 작은 서비스들(MSA)로 구성된 환경에서는, 서로 다른 수십~수백 개 서비스가 유연하게 상호 통신해야 함.
- DNS나 로드 밸런서만으로 해결하기엔 한계가 있어, 서비스 레지스트리 등을 통한 세분화된 컨트롤이 필요합니다.
2. Service Discovery의 동작 방식
2-1. 서비스 등록(Registration)
- 서비스가 기동(또는 스케일아웃)될 때
- “나는 A 서비스이며, IP는 10.1.2.3, 포트는 8080이야” 같은 정보를 **레지스트리(Registry)**에 등록
- 서비스 등록은 수동(개발자가 스크립트를 통해) 혹은 자동(서비스가 시작 시 스스로 레지스트리에 API 호출 등)으로 이뤄짐
- 헬스 체크(Health Check)
- 등록된 서비스가 실제로 동작 중인지 정기적으로 확인(Heart-beat, HTTP health-check 등)
- 죽거나 장애가 나면 자동으로 레지스트리에서 제거하여 트래픽 유입을 차단
2-2. 서비스 찾기(Discovery)
- 클라이언트(소비자)가 “A 서비스가 어디서 동작 중이냐?”라고 레지스트리에게 물으면, 레지스트리는 “10.1.2.3:8080, 10.1.2.4:8080, ...” 등 가용 인스턴스 리스트를 반환
- 이후 클라이언트는 그중 하나를 골라 요청하거나, 로드 밸런싱 알고리즘(Round Robin, Least Connection 등)에 따라 선택
3. 대표적인 서비스 디스커버리 패턴
3-1. 클라이언트 사이드 디스커버리 (Client-Side Discovery)
- 개념
- 클라이언트가 직접 서비스 레지스트리에 문의해, 사용 가능한 서비스 인스턴스를 조회한 뒤, 로드 밸런싱을 수행하여 요청
- 예시
- Netflix OSS의 Eureka(레지스트리) + Ribbon(클라이언트 로드 밸런서) 조합
- 클라이언트 애플리케이션이 Eureka에서 service-a 인스턴스 목록을 받아온 뒤, Ribbon 등이 라운드 로빈으로 요청 분배
- 장점
- 로드 밸런싱 로직을 클라이언트가 커스터마이징 가능
- 클라이언트가 직접 상태를 캐싱하고 관리해, 네트워크 오버헤드가 낮을 수 있음
- 단점
- 클라이언트마다 서비스 디스커버리 & 로드 밸런싱 로직이 필요해, 구현 복잡도 증가
- 언어나 프레임워크별로 라이브러리를 추가해야 할 수 있음
3-2. 서버 사이드 디스커버리 (Server-Side Discovery)
- 개념
- 클라이언트는 단순히 **로드 밸런서(또는 API Gateway)**에 요청하고, 로드 밸런서가 레지스트리에서 서비스 위치를 조회한 뒤 적절한 인스턴스로 트래픽을 라우팅
- 예시
- AWS의 Elastic Load Balancer(ELB), Kubernetes의 Service(ClusterIP)
- 클라이언트는 “service-a”라는 DNS로 호출하면, 내부적으로 로드 밸런서가 인스턴스 상태를 확인 & 분배
- 장점
- 클라이언트는 서비스 디스커버리에 대한 구현이 필요 없음(‘어디로 보내야 하나?’ 고민 없이 LB URL만 안다).
- 디스커버리 로직이 중앙(로드 밸런서/Gateway)에서 일원화되어 관리 쉬움
- 단점
- 로드 밸런서/게이트웨이 단일 장애 지점(SPoF)이 될 수 있으므로 고가용성 구성이 필요
- 특정 클라우드/솔루션에 종속될 가능성
4. Service Discovery 구현 도구 및 방식
- DNS 기반
- 가장 전통적인 방식. 각 서비스가 DNS 레코드를 등록하고, 클라이언트가 “serviceA.mycompany.local” 같은 도메인으로 접근
- 클라우드나 Kubernetes에서는 DNS를 자동으로 업데이트해주기도 함
- 장점: 인프라 표준 기술(DNS) 활용 / 단점: 캐싱, TTL 문제로 동적 스케일링 시 반응 속도가 느릴 수 있음
- 전용 레지스트리(Discovery Server) 사용
- Consul, Etcd, Zookeeper, Eureka 등이 대표적
- 서비스가 시작/중지될 때 레지스트리에 등록/제거 → 상태 정보를 관리
- API나 라이브러리를 통해 클라이언트가 해당 레지스트리에 쿼리
- 클라우드 네이티브 구현
- AWS ECS, EKS, Azure Container Apps, GCP Cloud Run 등에서 각각의 서비스 디스커버리 기능을 매니지드 형태로 제공
- 예: AWS Cloud Map, Azure Private DNS Zone, Google Cloud DNS
- 장점: 클라우드에서 자동 연동 / 단점: 클라우드 종속성
- 오케스트레이션 플랫폼 자체 기능
- Docker Swarm, Kubernetes는 내부적으로 서비스를 정의할 때 이미 Service / Ingress / DNS 같은 디스커버리 메커니즘을 제공
- 예: Kubernetes에서 Service 객체를 만들면, 내부 DNS(serviceName.namespace.svc.cluster.local)가 자동 생성, Pod의 IP 변화도 K8s가 추적해서 라우팅
- 대규모 MSA에선 사실상 Kubernetes Service가 디스커버리 역할을 겸하고 있음
5. 실제 사례 & 시나리오
- Netflix OSS 스택
- Eureka(Service Registry) + Ribbon(Client LB) + Zuul(API Gateway)
- 각 마이크로서비스가 Eureka에 자기 IP/Port를 등록 → 클라이언트가 Ribbon을 통해 Eureka 조회 → 적절한 인스턴스에 요청
- Spring Cloud Netflix가 이 구조를 쉽게 구현
- HashiCorp Consul
- 고가용성 K/V 스토어 + Service Registry + Health Check 기능 통합
- 서버/에이전트 구조로 동작하며, “Consul DNS” 기능으로 DNS 기반 디스커버리도 가능
- 동적으로 서비스가 추가/제거되면 Consul이 DNS 레코드를 업데이트
- Kubernetes Service
- Pod들은 언제든 IP가 바뀔 수 있으나, K8s Service 객체가 “가상 IP”를 부여하고 자동으로 Pod들로 트래픽을 라우팅
- CoreDNS가 “serviceName.namespace.svc.cluster.local” DNS를 제공
- 클라이언트는 오직 Service DNS 이름만 안다면, 그 뒤 Pod이 몇 개든, IP가 어떻게 바뀌든 상관없이 호출 가능
6. 고려해야 할 요소
- 헬스 체크
- 서비스 디스커버리가 올바르게 동작하려면, 각 인스턴스가 건강 상태(Health) 정보를 정확히 보고해야 함
- 헬스 체크 실패 시 레지스트리에서 제거해 요청이 가지 않도록 보장
- 로드 밸런싱 전략
- 단순 Round Robin 외에도, CPU 사용률이나 네트워크 부하 등 다양한 지표 기반 동적 로드 밸런싱을 사용할 수도 있음
- 일부 솔루션은 지리적 위치(Region) 기반으로 가장 가까운 인스턴스에 연결하기도 함
- 캐싱 & TTL
- 레지스트리에 조회한 서비스 목록을 일정 시간 캐싱할 때, TTL이 너무 길면 장애 감지가 늦어지고, 너무 짧으면 쿼리 오버헤드 증가
- 적절한 균형과 실시간성을 유지해야 함
- 보안 & 권한 관리
- 레지스트리에 무조건 모든 서비스 목록을 공개하면, 악의적인 내부/외부 사용자에게 공격 표면이 늘어날 수 있음
- 인증, 접근 제어, 네트워크 정책을 함께 고려해야 함
7. 결론
- Service Discovery는 마이크로서비스나 동적 스케일링 환경에서 핵심 요소입니다.
- 각 서비스가 자기 위치를 자동 등록하고, 다른 서비스나 클라이언트는 레지스트리나 로드 밸런서를 통해 쉽게 찾아서 연결함으로써, IP/포트 변동과 장애 등에 유연하게 대응할 수 있습니다.
- 클라이언트 사이드와 서버 사이드 디스커버리라는 두 가지 큰 패턴이 있고, 구현 방안은 전용 레지스트리(Consul, Eureka 등), DNS 기반, 오케스트레이션 플랫폼(K8s) 등이 다양하게 존재합니다.
- 서비스 디스커버리를 제대로 설계·구현하면, 애플리케이션이 확장, 축소, 장애 복구, 배포 자동화 등 복잡한 운영 시나리오를 안정적으로 처리할 수 있게 됩니다.
'분산시스템' 카테고리의 다른 글
Service Registry (0) | 2025.01.16 |
---|---|
application advertising (0) | 2025.01.15 |
Split Brain이란? (0) | 2025.01.09 |
분산 코디네이터 (1) | 2024.12.14 |
Communication (0) | 2024.12.07 |