NGINX Plus R9는 역방향 프록시 및 UDP 트래픽 부하 분산 기능을 도입하여 NGINX Plus의 레이어 4 부하 분산 기능을 크게 향상시켰습니다.
이 블로그 게시물에서는 최신 애플리케이션 인프라에서 DNS 서버를 실행하는 데 따르는 과제를 살펴보고 NGINX 오픈 소스와 NGINX Plus가 어떻게 UDP와 TCP 트래픽의 부하를 효과적이고 효율적으로 분산할 수 있는지 설명합니다. (애플리케이션 [활성] 상태 검사는 NGINX Plus에만 해당하지만 이 블로그의 정보는 NGINX 오픈 소스에도 동일하게 적용됩니다. 간략하게 설명하기 위해 이 게시물의 나머지 부분에서는 NGINX Plus를 참조합니다.)
[편집자 - NGINX Plus R9의 모든 새로운 기능 개요는 블로그에서 NGINX Plus R9 발표를 참조하세요.]
TCP와 달리 UDP는 설계상 종단 간 데이터 전달을 보장하지 않습니다. 이는 전서구로 메시지를 보내는 것과 비슷합니다. 메시지가 전송되었다는 것은 확실히 알지만 도착했는지는 확신할 수 없습니다. 이 "연결 없는" 접근 방식에는 여러 가지 이점이 있습니다. 가장 주목할 만한 점은 UDP의 더 작은 개별 메시지는 대역폭을 덜 사용하고 연결을 설정하기 위한 핸드셰이크 프로세스가 없기 때문에 TCP보다 대기 시간이 짧다는 것입니다. UDP는 시간 초과 및 기타 네트워크 수준의 문제를 감지하는 문제를 애플리케이션 개발자에게 맡깁니다. 하지만 이것은 DNS에 어떤 의미를 갖을까요?
다른 여러 UDP 기반 프로토콜과 마찬가지로 DNS는 요청-응답 데이터 흐름을 사용합니다. 예를 들어, DNS 클라이언트는 호스트 이름에 해당하는 IP 주소를 요청하고 답변을 받습니다. 지정된 시간 초과 기간 내에 응답이 도착하지 않으면 DNS 클라이언트는 동일한 요청을 "백업" DNS 서버로 보냅니다. 그러나 요청을 다시 시도하기 전에 제한 시간을 기다려야 하기 때문에 보통은 매우 빠른 프로세스(밀리초 단위)가 매우 느린 프로세스(초 단위)로 바뀔 수 있습니다.
NGINX Plus를 사용하여 DNS 트래픽을 프록시 하고 부하를 분산하면 클라이언트에서 시간 초과가 발생하는 경우가 줄어듭니다. NGINX Plus 로드 밸런서 뒤에 여러 DNS 서버가 있는 경우, 클라이언트와 NGINX Plus 사이에 네트워크 파티션이 발생할 때만 클라이언트가 시간 초과를 경험하게 됩니다. NGINX Plus가 애플리케이션 상태 검사를 사용하면 클라이언트는 DNS 서버 자체의 문제를 경험하지 않습니다. NGINX Plus는 각 서버의 가용성과 응답 시간을 모니터링하여, 비정상적인 서버로 클라이언트 요청을 보내는 것을 방지합니다.
DNS 트래픽의 대부분은 UDP를 통해 이루어지지만, TCP를 사용하는 일반적인 DNS 작업도 있습니다. DNS는 작은 메시지(최대 512바이트)에는 UDP를 사용하지만, 더 큰 메시지가 필요하거나 필요할 가능성이 있는 작업에는 TCP를 사용합니다. 역사적으로, TCP는 권한 있는 기본 이름 서버에서 보조 이름 서버로 영역을 전송하는 데에만 DNS와 함께 사용되었습니다. 그러나 컨테이너와 변경 불가능한 인프라로의 전환으로 인해 SRV
레코드를 사용하여 DNS를 기본 서비스 검색 메커니즘으로 사용하는 경우가 점차 늘어나고 있습니다.
DNS SRV
레코드는 원래 SIP를 사용하여 서버를 검색하는 VoIP(Voice over IP) 핸드셋용으로 도입되었지만 모든 유형의 서비스에 사용할 수 있습니다. 그러나 SRV
레코드에는 대부분의 다른 DNS 레코드 유형보다 훨씬 많은 정보가 포함되어 있습니다. 결과적으로 약 30개의 A
레코드와 대조적으로 약 10개의 SRV
레코드만 표준 512바이트 UDP 응답에 들어맞습니다. DNS 응답이 512바이트 제한을 초과하면 처음 512바이트가 반환되지만 응답은 "잘림"으로 표시됩니다. 이 시점에서 DNS 클라이언트는 잘린 응답을 최선을 다해 처리하거나 TCP를 사용하여 동일한 요청을 다시 시도할 수 있습니다.
이는 최신 네트워크 인프라에서 DNS 서버의 부하를 분산할 때 NGINX Plus는 UDP와 TCP 트래픽을 혼합하여 수신할 수 있음을 의미합니다.
다음 그림은 두 개의 로드 밸런서가 있는 마이크로서비스 환경을 단순화하여 보여줍니다. 프런트엔드 로드 밸런서는 애플리케이션의 퍼블릭 클라이언트로부터 요청을 프록시하여 가장 적합한 마이크로서비스 인스턴스를 선택하고 여기서는 설명하지 않을 여러 다른 기능을 수행합니다. 우리는 마이크로서비스 환경과 마이크로서비스에 서비스 검색 정보를 제공하는 DNS 서버 사이에 위치한 DNS 로드 밸런서에 집중할 것입니다.
NGINX Plus는 스트림 모듈에서 계층 4 부하 분산을 구현하므로 다음 스니펫에 표시된 것처럼 스트림
블록에서 UDP 및 TCP 부하 분산이 구성됩니다.
경고: 이 구성 스니펫을 /etc/nginx/conf.d 디렉토리에 새 파일로 추가할 수는 없습니다. NGINX Plus nginx.conf 기본 구성 파일에 http
블록의 conf.d 디렉터리에 있는 파일의 내용이 포함되어 있으므로 유효성 검사 오류가 발생합니다("여기서는 stream 지시문이 허용되지 않습니다"). 가장 간단한 해결책은 전체 스트림
블록을 nginx.conf 에 직접 포함시키는 것입니다.
스트림 { 업스트림 dns_servers {
서버 192.168.136.130:53;
서버 192.168.136.131:53;
}
서버 {
listen 53 udp;
listen 53; #tcp
proxy_pass dns_servers;
error_log /var/log/nginx/dns.log info;
}
}
먼저 DNS 서버의 상류 그룹을 정의합니다. 서버
지침은 업스트림 서버가 수신하는 포트 번호인 53(DNS의 잘 알려진 포트)을 지정합니다.
server{}
블록은 NGINX Plus가 들어오는 DNS 트래픽을 처리하는 방법을 정의합니다. 두 개의 수신
지시어는 NGINX Plus에게 UDP와 TCP 트래픽을 모두 포트 53에서 수신하라고 지시합니다. TCP는 스트림 모듈의 기본 4계층 프로토콜이므로 UDP와 같이 매개변수로 명시적으로 지정하지 않습니다.
proxy_pass
지시어는 NGINX Plus가 수신하는 트래픽을 어떻게 처리할지 알려줍니다. 여기서는 이러한 트래픽을 dns_servers 업스트림 그룹으로 프록시합니다. NGINX Plus는 클라이언트 UDP 요청을 업스트림 서버로 전달할 때 자동으로 UDP를 사용하고(클라이언트 TCP 요청의 경우 TCP 사용) 업스트림 그룹에서 4계층 프로토콜을 명시적으로 지정할 필요가 없습니다.
NGINX Plus는 HTTP 패킷의 경우와 같이 TCP 세그먼트나 UDP 데이터그램의 페이로드를 검사하지 않기 때문에 Stream 모듈에는 access_log
지시문이 없습니다. 하지만 error_log
지시문에서 info
매개변수를 사용하면 연결 처리 및 프록시 이벤트를 기록할 수 있습니다.
[편집자 - 이 블로그가 게시된 후 NGINX Open Source 1.11.4 및 NGINX Plus R11 에서 스트림 모듈 에서 액세스 로깅이 활성화되었습니다.]
DNS 서버의 가용성을 개선하려면 몇 가지 지침을 추가하고 활성(애플리케이션) 상태 검사를 구성할 수 있습니다.
첫 번째 추가 지시문은 proxy_responses
로, NGINX Plus가 프록시된 UDP 요청 각각에 대해 얼마나 많은 응답을 기대하는지를 나타냅니다. 우리의 경우, NGINX Plus는 단일 응답을 받으면 즉시 추가 응답을 기다리지 않고, 그 세션에 사용된 메모리와 소켓을 확보합니다.
두 번째 추가 지시문인 proxy_timeout
은 NGINX Plus가 서버로부터 응답을 기다리는 시간을 결정합니다(여기서는 기본 10분을 1초로 줄였습니다). NGINX Plus가 이 기간 내에 응답을 받지 못하면 업스트림 그룹의 다음 서버에 응답을 시도하고 응답하지 않는 업스트림 서버를 정의된 기간(기본값 10초) 동안 사용할 수 없음으로 표시하여 다른 클라이언트가 해당 기간 동안 시간 초과로 인한 지연을 겪지 않도록 합니다.
서버 { 53 udp를 수신; 53을 수신; #tcp 프록시_패스 dns_서버; 오류_로그 /var/log/nginx/dns.log 정보; 프록시_응답 1 ; 프록시_시간 초과 1초 ; }
업스트림 그룹의 서버
지시문에 fail_timeout
옵션을 포함하면, 서버가 사용할 수 없음으로 표시되는 시간을 변경할 수도 있습니다. 다음 설정을 사용하면 NGINX Plus는 실패한 업스트림 서버를 60초 동안 사용할 수 없음으로 표시합니다.
업스트림 dns_servers { 서버 192.168.136.130:53 fail_timeout=60s ; 서버 192.168.136.131:53 fail_timeout=60s ; }
이를 통해 DNS 서버 중 하나에 장애가 발생할 경우 클라이언트가 얼마나 많은 지연을 겪을지 제어할 수 있습니다. 그러나 오류가 발생한 DNS 서버에 TCP 요청을 시도하면 TCP의 고유한 오류 검사를 통해 NGINX Plus가 자동으로 해당 서버를 사용할 수 없음으로 표시하여 이후 해당 서버에 대한 TCP 또는 UDP 요청이 방지됩니다.
NGINX Plus의 활성 상태 점검 기능은 DNS를 포함하여 모든 부하 분산 서비스의 고가용성을 위한 추가적이고 매우 귀중한 도구입니다. DNS 클라이언트의 실제 TCP 요청이 실패할 때까지 기다려서 DNS 서버를 다운으로 표시하는 대신, NGINX Plus는 주기적으로 포트 53에서 TCP 연결을 시도하여 DNS 서버가 작동하고 올바르게 작동하는지 확인합니다. 이를 위해 server{}
블록에 port=53
매개변수와 함께 health_check
지시문을 포함합니다. (NGINX Plus는 기본적으로 listen
지시문에서 지정한 포트, 우리의 경우 53으로 상태 검사를 보냅니다. 여기서는 매개변수를 사용하여 기본값을 명시적으로 구성하지만, DNS 서버가 트래픽에 응답하도록 수정한 경우 다른 포트를 지정할 수도 있습니다.)
UDP를 사용하면 한 단계 더 나아가 알려진 레코드에 대한 실제 DNS 조회를 수행하는 활성 상태 검사를 구성할 수 있습니다. 예를 들어, 마이크로서비스 환경 내에서 서비스 검색에 사용되는 것과 동일한 하위 도메인에 대한 영역 파일에 다음 CNAME
레코드를 삽입할 수 있습니다.
CNAME healthy.svcs.example.com에 healthcheck를 추가합니다.
UDP의 가벼운 특성을 감안하면 네트워크 트래픽을 관찰하고 DNS 조회를 나타내는 바이트 문자열을 쉽게 추출할 수 있습니다. 그런 다음 해당 문자열을 send
지시문에 대한 매개변수로 사용하는 일치
구성 블록을 만듭니다. expect
지시어는 서버가 정상으로 간주되기 위해 반환해야 하는 응답을 지정합니다.
match dns_lookup {
send x00x01x00x00x00x01x00x00x00x00x00x00x00x06x68x65x61 ...;
expect ~* "healthy.svcs.example.com.";
}
이러한 심층적인 애플리케이션 수준 상태 검사를 실시하는 이점은 이름 서버가 작동 중이더라도 프로덕션 도메인에 대한 실제 DNS 조회를 수행하면 다운스트림에서 문제를 일으킬 수 있는 구성 문제와 데이터 손상을 발견할 수 있다는 것입니다.
NGINX Plus 지원팀은 DNS 조회 및 기타 프로토콜에 대한 UDP 상태 검사를 준비하는 데 도움을 줄 수 있습니다.
다음 스니펫은 활성 상태 검사에 필요한 추가 지침을 강조합니다.
스트림 { 업스트림 dns_servers { 영역 dns_mem 64k ; 서버 192.168.136.130:53 fail_timeout=60s; 서버 192.168.136.131:53 fail_timeout=60s; } match dns_lookup { send x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...; expect ~* "healthy.svcs.example.com."; } server { listen 53 udp; listen 53; #tcp health_check match=dns_lookup interval=20 failed=2 passed=2 udp; health_check interval=20 failed=1 passed=2 port=53; #tcp proxy_pass dns_servers; 오류_로그 /var/log/nginx/dns.log 디버그; 프록시_응답 1; 프록시_시간 초과 1초; } }
zone
지시어는 dns_mem 이라는 공유 메모리 영역을 정의하는데, 이를 통해 모든 NGINX Plus 작업자 프로세스에서 상태 검사 결과(및 기타 상태 정보)를 사용할 수 있습니다.
매치
지시어는 바로 위에서 논의되었습니다.
health_check
지시문에는 사용자 환경에 맞게 조정할 수 있는 여러 매개변수가 있습니다. 여기서는 UDP와 TCP에 대해 각각 별도의 상태 검사를 정의합니다. UDP와 TCP의 차이로 인해 DNS 서버를 비정상으로 표시하기 전에 연속적인 UDP 상태 검사 실패가 두 번 필요하지만, TCP 실패는 한 번만 발생합니다. 두 프로토콜 모두 불안정하고 "플래핑"하는 서버에 요청을 보내는 것을 방지하기 위해 서버를 다시 정상으로 표시하기 전에 성공적인 응답이 두 번 필요합니다.
UDP와 TCP 트래픽 모두에 대해 단일 업스트림 DNS 서버 그룹을 정의하는 이점은 두 프로토콜 중 하나에 대한 상태 검사가 실패하면 서버가 비정상으로 표시되고 부하 분산 풀에서 제거된다는 것입니다.
백엔드 서버 두 개만 배포하는 것도 효과적인 고가용성 솔루션이 될 수 있지만 NGINX Plus의 부하 분산 기능을 사용하면 클라이언트의 지식 없이 백엔드 서버를 수평으로 확장할 수 있습니다.
위에 설명된 샘플 마이크로서비스 환경에서는 백엔드 DNS 서버를 확장할 필요가 없을 가능성이 높습니다. 그러나 모든 가입자에게 DNS 서비스를 제공하는 ISP는 지속적인 부하와 엄청난 급증 가능성을 겪기 때문에 많은 수의 DNS 서버와 프런트엔드 프록시가 필요하여 트래픽 부하를 분산해야 합니다.
모든 NGINX 및 NGINX Plus 부하 분산 알고리즘은 TCP 및 UDP뿐만 아니라 HTTP에도 사용할 수 있습니다.
(또한 모든 알고리즘에 가중치를 구성하여 효율성을 더욱 높일 수 있습니다. 토론을 위해 블로그의 Choosing an NGINX Plus Load‑Balancing Technique 에서 가중치에 대한 섹션을 참조하세요.)
HTTP 요청은 백엔드 서버에 가해지는 부하와 처리 요구 사항에 따라 엄청나게 다를 수 있는 반면, DNS 요청은 일반적으로 모두 동일한 부하를 생성합니다. 이러한 이유로 최소 연결 및 최소 시간 알고리즘은 라운드 로빈보다 이점을 제공할 가능성이 낮습니다. 특히, 최소 연결에는 NGINX Plus가 업스트림 서버로부터 응답을 기다리고 있는 모든 UDP 요청이 연결 수에 포함됩니다. proxy_responses
와 proxy_timeout
의 값이 충족되지 않는 한 NGINX Plus는 이미 작업을 완료했을 수 있는 업스트림 서버에 대한 연결을 계속 계산합니다.
클라이언트 수가 많고 클라이언트와 서버 간에 여러 메시지가 교환되는 RADIUS 챌린지-응답 흐름과 같이 많은 "대화"를 수행하는 프로토콜이 있는 경우 소스 IP 해시를 사용하면 단일 백엔드 서버에서 해당 대화를 수행할 수 있습니다. 즉, 세션 지속성을 확립합니다. 즉, NGINX Plus는 주어진 클라이언트의 모든 요청을 동일한 서버로 전달합니다. 다음 예제에서는 소스(클라이언트) IP 주소( $remote_addr
변수로 캡처)를 키로 사용하여 한 쌍의 RADIUS 인증 서버에 대한 해시 부하 분산 알고리즘을 구성합니다.
업스트림 반경 서버 { 해시 $remote_addr; # 소스 IP 해시
서버 192.168.136.201:1812;
서버 192.168.136.202:1812;
}
UDP 및 TCP 부하 분산에 대한 자세한 내용은 다음 리소스를 확인하세요.
업스트림
구성 컨텍스트NGINX Plus R9의 다른 뛰어난 기능에 대해 알아보려면 블로그에서 NGINX Plus R9 발표를 참조하고 주문형 웨비나 인 NGINX Plus R9의 새로운 기능을 시청하세요.
NGINX Plus를 사용해보려면 오늘 무료 30일 체험판을 시작하거나 저희에게 연락해 사용 사례에 대해 논의해 보세요.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."