1. 라이브러리
  2. DNS
  3. DNS 설정

업데이트됨 1개월 전

라운드 로빈 DNS는 동전 던지기식 부하 분산입니다—결과가 분배되기는 하지만, 그 뒤에 아무런 지능도 없습니다.

작동 방식

같은 호스트명을 서로 다른 IP 주소에 연결하는 여러 DNS A 레코드를 생성합니다:

example.com.  300  IN  A  192.0.2.1
example.com.  300  IN  A  192.0.2.2
example.com.  300  IN  A  192.0.2.3

DNS 리졸버가 example.com을 쿼리하면, 권한 네임서버는 세 주소를 모두 반환하며 쿼리마다 순서를 바꿉니다. 첫 번째 쿼리: 192.0.2.1, 192.0.2.2, 192.0.2.3. 다음 쿼리: 192.0.2.2, 192.0.2.3, 192.0.2.1. 대부분의 클라이언트가 목록의 첫 번째 주소를 사용하기 때문에, 트래픽이 세 서버에 골고루 분산됩니다.

이론상으로는요.

캐싱 문제

DNS 캐싱은 라운드 로빈의 분산 논리를 무너뜨립니다. 재귀 리졸버가 DNS 레코드를 캐싱하면, 그 리졸버를 사용하는 모든 클라이언트는 TTL이 만료될 때까지 동일한 순서의 목록을 받습니다.

실제로 무슨 뜻인지 생각해 보세요. Comcast의 리졸버는 수백만 명의 사용자에게 서비스를 제공합니다. 192.0.2.1이 첫 번째로 캐싱되면, 수백만 명의 사용자가 모두 같은 서버에 연결합니다. 그동안 나머지 두 서버는 아무 일도 없이 놀고 있습니다. 세 서버 각각에 33%의 트래픽이 분산되도록 설정했는데, 결국 각 ISP 리졸버가 네임서버에 쿼리한 타이밍에 따라 서버 하나가 70%를 처리하게 됩니다.

문제는 여러 계층에서 중첩됩니다. 재귀 리졸버가 캐싱합니다. 운영체제가 캐싱합니다. 브라우저가 캐싱합니다. 일부 클라이언트는 TTL을 아예 무시합니다—악명 높은 Java 애플리케이션은 설정한 TTL에 상관없이 DNS를 무기한으로 캐싱할 수 있습니다. 권한 네임서버에서 이루어지는 순환은 결국 아무 의미가 없어집니다. 캐싱이 이미 트래픽이 어디로 갈지 결정해버린 것입니다.

TTL을 짧게 하면 트래픽이 더 자주 재분배되지만 DNS 쿼리 양이 늘어나고 지연 시간이 추가됩니다. TTL을 길게 하면 DNS 부하는 줄어들지만 사용자가 오랫동안 같은 서버에 묶이게 됩니다. 어느 쪽도 근본적인 문제를 해결하지 못합니다: 리졸버와 클라이언트가 레코드를 어떻게 캐싱하고 순서를 바꾸는지 제어할 수 없다는 점입니다.

상태 확인 없음

라운드 로빈 DNS는 서버가 살아 있는지 알 방법이 없습니다. 서버 하나가 다운되어도 DNS는 계속 그 IP 주소를 알립니다. 그 주소에 연결하려는 사용자는 연결 시간 초과를 경험합니다. 기다립니다. 실패합니다. 일부 클라이언트는 결국 목록의 다음 주소를 시도하지만, 그 재시도에 30초의 지연이 추가됩니다.

실패한 서버의 A 레코드를 수동으로 제거할 수 있지만, 그러면 캐시가 만료될 때까지 기다려야 합니다. TTL이 5분이면 사용자는 5분간 장애를 겪습니다. TTL이 길면 더 오래 지속됩니다. 자동 장애 복구도, 헬스 체크도, 지능도 없습니다.

이 때문에 라운드 로빈 DNS는 고가용성이 필요한 어떤 상황에도 적합하지 않습니다. 장애가 제대로 처리되지 않는 것이 아니라—아예 처리되지 않습니다.

분산이 결코 균등하지 않음

캐싱과 장애를 무시하더라도, 라운드 로빈 DNS는 연결을 분산할 뿐, 부하를 분산하지는 않습니다. 어떤 연결은 분당 1,000개의 API 호출을 만드는 모바일 앱일 수 있습니다. 또 어떤 연결은 웹 페이지 하나를 로드하고 떠나는 사람일 수 있습니다. 라운드 로빈은 이 둘을 동일하게 취급합니다.

세션 어피니티는 존재하지 않습니다. 사용자가 동일한 백엔드 서버와 세션을 유지해야 하는 애플리케이션이라면, 라운드 로빈 DNS는 아무것도 해주지 않습니다. 분산 세션 저장소를 구현하지 않은 경우, 사용자는 후속 요청에서 다른 서버에 연결되어 세션 상태가 깨집니다.

지리적 위치는 무시됩니다. 싱가포르의 사용자가 도쿄에 완벽한 서버가 있음에도 버지니아 서버에 연결됩니다. 라운드 로빈 DNS는 누가 어디에 있는지 알지도, 신경 쓰지도 않습니다.

유용한 경우

이 모든 문제에도 불구하고, 라운드 로빈 DNS에는 적합한 사용 사례가 있습니다:

정적 콘텐츠 미러. 모든 서버가 동일한 콘텐츠를 반환합니다. 가끔 발생하는 장애는 허용됩니다. 라운드 로빈은 별도의 인프라 없이 무료로 분산을 제공합니다.

개발 환경. 완벽한 분산은 중요하지 않습니다. 설정의 단순함이 우선입니다.

상태 없는 읽기 전용 서비스. 모든 서버가 모든 요청을 처리할 수 있습니다. 세션 상태 없음. 구현 비용 없이 불균등한 분산을 감수합니다.

트레이드오프는 명확합니다: 신뢰성을 단순함과 맞바꾸는 것입니다.

현대적인 대안

실제 부하 분산이 필요한 프로덕션 애플리케이션은 전용 솔루션을 사용합니다.

L4 로드 밸런서인 HAProxy나 NGINX는 헬스 체크를 수행하고, 실패한 서버를 자동으로 제거하며, 실제 연결 수나 서버 부하를 기반으로 분산합니다.

L7 로드 밸런서는 애플리케이션 인식 기능을 추가합니다—URL 경로, HTTP 헤더, 요청 내용을 기반으로 라우팅합니다. SSL을 종료하고, 세션을 관리하며, 지능적인 라우팅 결정을 내립니다.

클라우드 로드 밸런서(AWS ELB, Google Cloud Load Balancing, Azure Load Balancer)는 인프라를 직접 관리하지 않아도 헬스 체크, 자동 확장, 지리적 분산을 제공합니다.

GeoDNS와 Anycast는 사용자를 가까운 서버로 라우팅하여 지리적 한계를 해결합니다. CDN은 지리적 분산과 캐싱, 트래픽 관리를 결합합니다.

이러한 솔루션은 라운드 로빈 DNS보다 비용이 더 듭니다. 하지만 제대로 작동합니다.

라운드 로빈 DNS 자주 묻는 질문

일부 리졸버가 DNS 응답을 재정렬하는 이유는?

RFC 3484는 리졸버가 "수치적으로 가까운" 네트워크를 선호하도록 IP 주소를 재정렬할 수 있는 동작을 표준화했습니다. 신중하게 순환된 목록이 클라이언트에 도달하기 전에 재정렬될 수 있습니다. 캐싱과 결합되면, 네임서버에서 설정한 분산이 실제 트래픽 패턴과 거의 닮지 않게 됩니다.

라운드 로빈 DNS와 헬스 체크를 결합할 수 있나요?

AWS Route 53이나 NS1 같은 일부 관리형 DNS 서비스는 헬스 체크가 포함된 라운드 로빈을 제공하여 실패한 IP를 자동으로 순환에서 제거합니다. 이것은 가장 큰 약점을 해결하지만 비용과 복잡성이 추가됩니다. 그 시점에서는 단순한 라운드 로빈이 아니라 GSLB(Global Server Load Balancing)의 기본적인 형태를 사용하는 것입니다.

브라우저는 라운드 로빈 DNS 장애를 어떻게 처리하나요?

동작은 다양합니다. 일부 브라우저는 연결 시간 초과(일반적으로 30초) 후 다른 IP를 시도합니다. 다른 브라우저는 응답 여부에 상관없이 첫 번째 IP만 고집합니다. Chrome의 "Happy Eyeballs" 알고리즘은 더 빠른 폴백을 위해 여러 주소를 병렬로 시도하지만, 보편적이지는 않습니다. 가용성을 위해 클라이언트의 재시도 동작에 의존할 수 없습니다.

라운드 로빈 DNS가 로드 밸런서보다 나은 경우가 있나요?

단순함 측면에서는 그렇습니다. 로드 밸런서는 배포하고, 구성하고, 모니터링하고, 유지 관리해야 하는 인프라입니다. 라운드 로빈 DNS는 A 레코드 몇 개면 됩니다. 요구 사항이 소박하다면—상태 없는 서비스, 가끔 장애 허용, 세션 어피니티 불필요—라운드 로빈의 단순함이 그 한계를 능가할 수 있습니다.

출처

이 페이지가 도움이 되었나요?

😔
🤨
😃
라운드 로빈 DNS 이해하기 • 라이브러리 • Connected