DNS SRV 레코드 사용하여 NGINX IP 및 Port 자동 등록
마이크로서비스 아키텍처의 가장 큰 장점 중 하나는 서비스 인스턴스를 얼마나 빠르고 쉽게 확장할 수 있는지입니다. 서비스 인스턴스가 여러 개인 경우 로드 밸런서와 사용 가능한 서비스 인스턴스 집합에 대한 변경 사항을 신속하게 알리는 방법이 필요합니다. 이를 Service Discovery이라고 합니다. NGINX Plus는 서비스 검색(Service Discovery) 시스템과 통합하기 위한 두 가지 옵션인 NGINX Plus API 및 DNS(Domain Name System) 재확인을 제공합니다. 이 블로그 포스트는 후자에 중점을 둡니다.
가상 머신(VM) 또는 컨테이너를 추가하거나 제거하여 서비스 인스턴스(이 블로그 포스트에서는 백엔드라고 함)를 확장할 때 백엔드 세트에 대한 모든 변경 사항을 반영하도록 로드 밸런서의 구성을 변경해야 합니다. 확장은 애플리케이션에 따라 하루, 시간당 또는 심지어 분당 여러 번 발생할 수 있습니다. 구성 변경 빈도가 높기 때문에 자동화가 필요하며 이를 수행하는 방법 중 하나는 DNS를 통한 서비스 검색(Service Discovery)입니다.
Kubernetes와 같이 오늘날 애플리케이션을 실행하는 많은 플랫폼은 DNS를 사용하여 서비스 검색(Service Discovery)을 지원합니다. 이 블로그 포스트의 끝부분에 DNS를 사용하는 인기 있는 플랫폼 및 서비스 검색 도구와 NGINX Plus를 통합하는 방법을 설명하는 포스트에 대한 링크가 제공됩니다.
[참고 – 이 포스트는 이전에는 별도의 동적 구성 모듈을 언급했지만, 이제는 사용이 중지되었고 대신 NGINX Plus API를 사용합니다.]
목차
1. DNS 주요 기능
1-1. TTL(Time-to-Live)
1-2. TCP를 통한 DNS
1-3. SRV 레코드
2. NGINX 및 NGINX Plus용 DNS를 사용한 서비스 검색 방법
2-1. NGINX와 함께 서비스 검색에 DNS 사용
2-1-1. proxy_pass 지시문에서 도메인 이름 사용
2-1-2. Upstream 서버 그룹에서 도메인 이름 사용
2-1-3. 변수에 도메인 이름 설정
2-2. NGINX Plus와 함께 서비스 검색에 DNS 사용
2-2-1. NGINX Plus에서 A 레코드 사용
2-2-2. NGINX Plus에서 SRV 레코드 사용
3. 주의 사항
4. 결론
1. DNS 주요 기능
DNS를 통해 서비스 검색(Service Discovery)을 구성하는 방법을 설명하기 전에 특히 관련이 있거나 편리한 DNS 프로토콜의 일부 기능을 간단히 살펴보겠습니다.
1-1. TTL(Time-to-Live)
DNS 클라이언트가 오래된 정보를 사용하지 못하도록 DNS 레코드에는 클라이언트가 레코드를 유효하다고 간주할 수 있는 기간을 정의하는 TTL(Time-to-Live) 필드가 포함됩니다. DNS 표준을 준수하기 위해 클라이언트는 레코드가 TTL을 초과할 때 DNS 서버에 업데이트를 쿼리해야 합니다. NGINX Plus는 기본적으로 TTL을 따르지만 레코드의 “수명”에 대한 보다 세부적인 제어도 제공합니다. TTL을 무시하고 대신 지정된 빈도로 레코드를 업데이트하도록 NGINX Plus를 구성할 수 있습니다. (NGINX Open Source가 TTL을 처리하는 방법은 포스트 뒷부분에서 설명하겠습니다.)
1-2. TCP를 통한 DNS
기본적으로 DNS 클라이언트와 서버는 UDP를 통해 통신하지만 도메인 이름이 많은 수의 백엔드 IP 주소로 확인되는 경우 전체 응답이 512바이트로 제한되는 단일 UDP 데이터그램에 맞지 않을 수 있습니다. UDP 대신 TCP를 사용하면 이 문제가 해결됩니다. 전체 레코드 집합이 하나의 데이터그램에 맞지 않으면 서버는 응답에 truncation 플래그를 설정하여 클라이언트가 모든 레코드를 가져오려면 TCP로 전환하도록 지시합니다. TCP를 통한 DNS는 NGINX 버전 1.9.11 이상과 NGINX Plus R9 이상에서 지원됩니다. 자세한 내용은 블로그에서 DNS 트래픽 NGINX로 로드 밸런싱을 참조하십시오.
1-3. SRV 레코드
DNS는 호스트 이름을 IP 주소로 확인하지만 포트 번호는 어떻습니까? 예를 들어 Docker 컨테이너를 로드 밸런싱하는 경우 포트 번호가 대신 동적으로 할당되기 때문에 잘 알려진 포트 번호를 사용할 수 없는 경우가 있습니다. DNS에는 포트 번호와 몇 가지 다른 매개변수를 포함하는 특별한 유형의 레코드인 서비스(SRV) 레코드가 있습니다. R9 이상에서 NGINX Plus는 SRV 레코드를 지원하므로 여기에서 포트 정보를 추출할 수 있습니다.
2. NGINX 및 NGINX Plus용 DNS를 사용한 서비스 검색 방법
이제 NGINX 및 NGINX Plus에서 서비스 검색을 위해 DNS를 사용하여 정교함을 높이는 다섯 가지 방법을 보여드리겠습니다. 처음 3개는 NGINX와 NGINX Plus 모두에서 사용할 수 있고 마지막 2개는 NGINX Plus에서만 사용할 수 있습니다.
서비스 검색 방법에 대한 이 조사에서는 IP 주소가 10.0.0.2인 example.com 영역에 대한 권한 있는 이름 서버가 있다고 가정합니다. nslookup 유틸리티의 다음 출력에 표시된 것처럼 도메인 이름 backends.example.com에 해당하는 세 개의 백엔드 서버가 있습니다. NGINX 및 NGINX Plus는 DNS에서 표준 A 레코드를 요청합니다. 마지막 방법으로 NGINX Plus는 대신 SRV 레코드를 요청합니다.
$ nslookup backends.example.com 10.0.0.2
Server: 10.0.0.2
Address: 10.0.0.2#53
Name: backends.example.com
Address: 10.0.0.11
Name: backends.example.com
Address: 10.0.0.10
Name: backends.example.com
Address: 10.0.0.12
2-1. NGINX와 함께 서비스 검색에 DNS 사용
NGINX Open Source에서 DNS를 사용하는 세 가지 방법을 보여주는 것으로 시작하겠습니다(위에서 언급한 대로 NGINX Plus에서도 사용할 수 있음).
2-1-1. proxy_pass 지시문에서 도메인 이름 사용
Upstream 서버(백엔드) 그룹을 정의하는 가장 간단한 방법은 proxy_pass 지시문에 대한 매개변수로 도메인 이름을 지정하는 것입니다.
server {
location / {
proxy_pass http://backends.example.com:8080;
}
}
NGINX는 구성을 시작하거나 다시 로드할 때 DNS 서버를 쿼리하여 backends.example.com을 확인합니다. DNS 서버는 위에서 설명한 3개의 백엔드 목록을 반환하고 NGINX는 기본 라운드 로빈 알고리즘을 사용하여 요청 부하를 분산합니다. NGINX는 OS 구성 파일 /etc/resolv.conf에서 DNS 서버를 선택합니다.
이 방법은 서비스 검색을 수행하는 가장 유연한 방법이며 다음과 같은 추가 단점이 있습니다.
- 도메인 이름을 확인할 수 없는 경우 NGINX는 구성을 시작하거나 다시 로드하지 못합니다.
- NGINX는 레코드의 TTL 값을 무시하고 다음에 다시 시작하거나 구성을 다시 로드할 때까지 DNS 레코드를 캐시합니다.
- 다른 로드 밸런싱 알고리즘을 지정할 수 없으며 다음 섹션에서 설명할 server 지시문에 대한 매개 변수로 정의된 수동 상태 검사 또는 기타 기능을 구성할 수도 없습니다.
2-1-2. Upstream 서버 그룹에서 도메인 이름 사용
NGINX가 제공하는 로드 밸런싱 옵션을 활용하기 위해 upstream 구성 블록에서 upstream 서버 그룹을 정의할 수 있습니다. 그러나 IP 주소로 개별 서버를 식별하는 대신 server 지시문에 대한 매개변수로 도메인 이름을 사용하십시오.
첫 번째 방법과 마찬가지로 backends.example.com은 NGINX가 구성을 시작하거나 다시 로드할 때 3개의 백엔드 서버로 확인됩니다. 그러나 이제는 보다 정교한 로드 밸런싱 알고리즘인 Least Connections를 정의하고 max_fails 매개변수를 사용하여 패시브 상태 확인을 활성화하여 NGINX가 세 번의 연속 요청이 실패할 때 서버를 다운된 것으로 표시하도록 지정할 수 있습니다.
upstream backends {
least_conn;
server backends.example.com:8080 max_fails=3;
}
server {
location / {
proxy_pass http://backends;
}
}
이 방법을 사용하면 로드 밸런싱 알고리즘을 선택하고 상태 확인을 구성할 수 있지만 시작, 다시 로드 및 TTL과 관련하여 이전 방법과 동일한 단점이 있습니다.
2-1-3. 변수에 도메인 이름 설정
이 방법은 첫 번째 방법의 변형이지만 NGINX가 도메인 이름을 다시 확인하는 빈도를 제어할 수 있습니다.
resolver 10.0.0.2 valid=10s;
server {
location / {
set $backend_servers backends.example.com;
proxy_pass http://$backend_servers:8080;
}
}
변수를 사용하여 proxy_pass 지시문에서 도메인 이름을 지정하면 NGINX는 TTL이 만료되면 도메인 이름을 다시 확인합니다. 이름 서버를 명시적으로 지정하려면 resolver 지시문을 포함해야 합니다(NGINX는 처음 두 방법에서와 같이 /etc/resolv.conf를 참조하지 않음). resolver 지시문에 유효한 매개변수를 포함하면 NGINX가 TTL을 무시하고 대신 지정된 빈도로 이름을 다시 확인하도록 지시할 수 있습니다. 여기서 우리는 NGINX에 10초마다 이름을 다시 확인하도록 지시합니다.
참고: TCP/UDP 로드 밸런싱의 경우 proxy_pass 지시문에서 변수를 사용하는 이 방법은 NGINX 1.11.3 이상 및 NGINX Plus R10 이상에서 지원됩니다.
이 방법은 도메인 이름을 확인할 수 없을 때 NGINX 시작 또는 다시 로드 작업이 실패하지 않고 NGINX가 이름을 다시 확인하는 빈도를 제어할 수 있다는 점에서 첫 번째 방법의 두 가지 단점을 제거합니다. 그러나 upstream 그룹을 사용하지 않기 때문에 로드 밸런싱 알고리즘이나 다른 매개 변수를 서버 지시문에 지정할 수 없습니다(두 번째 방법에서 수행한 것처럼).
2-2. NGINX Plus와 함께 서비스 검색에 DNS 사용
이제 NGINX Plus 전용 DNS로 서비스를 검색하는 두 가지 방법을 살펴보겠습니다.
2-2-1. NGINX Plus에서 A 레코드 사용
NGINX Plus를 사용하면 처음 세 가지 방법에 대해 위에서 설명한 단점 없이 원하는 만큼 자주 DNS 이름을 다시 확인할 수 있습니다. 이 기능을 사용하려면 다음이 필요합니다.
- 이전 방법과 마찬가지로 이름 서버를 지정하는 resolver 지시문을 포함합니다.
- Upstream 구성 블록에 zone 지시문을 포함하여 공유 메모리 영역을 할당합니다.
- 도메인 이름을 사용하는 서버 지시문에 resolve 매개변수를 추가합니다.
다음 예를 살펴보겠습니다.
resolver 10.0.0.2 valid=10s;
upstream backends {
zone backends 64k;
server backends.example.com:8080 resolve;
}
server {
location / {
proxy_pass http://backends;
}
}
기본적으로 NGINX Plus는 TTL을 준수하여 레코드가 만료되면 이름을 다시 확인합니다. 대신 NGINX Plus가 지정된 빈도로 이름을 다시 확인하도록 하려면 resolver 지시문에 유효한 매개변수를 포함합니다.
스니펫에서 NGINX Plus는 10초마다 10.0.0.2의 이름 서버를 쿼리하여 backends.example.com을 확인합니다. 이름을 확인할 수 없는 경우 시작 시, 구성을 다시 로드할 때 또는 런타임 중에 NGINX Plus가 실패하지 않습니다. 대신 클라이언트는 표준 502 오류 페이지를 보게 됩니다.
2-2-2. NGINX Plus에서 SRV 레코드 사용
NGINX Plus R9 이상은 DNS SRV 레코드를 지원합니다. 이를 통해 NGINX Plus는 이름 서버에서 IP 주소뿐만 아니라 포트 번호, 가중치 및 우선 순위도 가져올 수 있습니다. 이는 서비스의 포트 번호가 종종 동적으로 할당되는 마이크로서비스 환경에서 매우 중요합니다.
SRV 레코드는 서비스 이름, 서비스와의 통신을 위한 프로토콜 및 도메인 이름의 삼중항으로 정의됩니다. 이름 서버를 쿼리할 때 세 가지를 모두 제공해야 합니다. 10.0.0.2 이름 서버에는 nslookup 유틸리티의 다음 출력에 표시된 것처럼 서비스 이름 http, 프로토콜 tcp 및 도메인 이름 backends.example.com의 3개가 포함된 3개의 SRV 레코드가 있습니다.
$ nslookup -query=SRV _http._tcp.backends.example.com 10.0.0.2
Server: 10.0.0.2
Address: 10.0.0.2#53
_http._tcp.backends.example.com service = 0 2 8090 backend-0.example.com.
_http._tcp.backends.example.com service = 0 1 8091 backend-1.example.com.
_http._tcp.backends.example.com service = 10 1 8092 backend-2.example.com.
각 SRV 레코드에서 호스트명을 쿼리하면 해당 IP 주소를 얻습니다.
$ nslookup backend-0.example.com 10.0.0.2
...
Name: backend-0.example.com
Address: 10.0.0.10
$ nslookup backend-1.example.com 10.0.0.2
...
Name: backend-1.example.com
Address: 10.0.0.11
$ nslookup backend-2.example.com 10.0.0.2
...
Name: backend-2.example.com
Address: 10.0.0.12
첫 번째 nslookup 명령에서 반환된 첫 번째 SRV 레코드의 정보를 자세히 살펴보겠습니다.
_http._tcp.backends.example.com service = 0 2 8090 backend-0.example.com.
- _http._tcp. – SRV 레코드의 이름 및 프로토콜. 이를 NGINX Plus 구성 파일(아래 참조)의 서버 지시문에 대한 서비스 매개변수 값으로 지정합니다.
- 0 – 우선순위. 값이 낮을수록 우선 순위가 높습니다. NGINX Plus는 우선 순위가 가장 높은 서버를 기본 서버로 지정하고 나머지 서버를 백업 서버로 지정합니다. 이 레코드는 모든 레코드 중에서 가장 낮은 값(가장 높은 우선 순위)을 가지므로 NGINX Plus는 해당 백엔드를 주 서버로 지정합니다.
- 2 – 무게. NGINX Plus는 upstream 그룹에 백엔드를 추가할 때 백엔드의 가중치를 이 값으로 설정합니다(서버 지시문의 가중치 매개변수와 동일).
- 8090 – 포트 번호입니다. NGINX Plus는 백엔드를 upstream 그룹에 추가할 때 백엔드의 포트를 이 값으로 설정합니다.
- backend‑0.example.com – 백엔드 서버의 호스트 이름입니다. NGINX Plus는 이 이름을 확인하고 해당 백엔드를 upstream 그룹에 추가합니다. 이름이 여러 레코드로 확인되면 NGINX Plus는 여러 서버를 추가합니다.
이제 SRV 레코드를 사용하도록 NGINX Plus를 구성하는 방법을 살펴보겠습니다. 다음은 샘플 구성 파일입니다.
resolver 10.0.0.2 valid=10s;
upstream backends {
zone backends 64k;
server backends.example.com service=_http._tcp resolve;
}
server {
location / {
proxy_pass http://backends;
}
}
서버 지시문에 대한 service 매개변수를 사용하여 확인하려는 SRV 레코드의 이름과 프로토콜을 지정합니다. 우리의 경우에는 각각 _http와 _tcp입니다. 서비스 매개변수와 포트를 지정하지 않는다는 사실을 제외하고는 이전 섹션의 구성 예와 동일하게 보입니다.
이 섹션의 첫 번째 nslookup 명령에서 반환된 값을 기반으로 NGINX Plus는 3개의 백엔드 서버로 구성됩니다.
10.0.0.10 – Primary server with port 8090 and weight 2.
10.0.0.11 – Primary server with port 8091 and weight 1.
10.0.0.12 – Backup server with port 8092 and weight 1.
NGINX Plus에 대한 실시간 모니터링을 구성하면 내장 대시보드에서 해당 백엔드를 볼 수 있습니다.

지정된 가중치에 따라 요청이 어떻게 분배되는지 확인하십시오. 10.0.0.11:8091 서버(가중치 1)는 요청의 1/3을 받는 반면 10.0.0.10:8090 서버(가중치 2)는 2/3를 받습니다. 백업 서버로서 10.0.0.12:8092 서버는 다른 두 서버가 다운되지 않는 한 어떠한 요청도 받지 않습니다.
3. 주의 사항
NGINX Plus에서 서비스 검색(Service Discovery)을 위해 DNS를 사용할 때 유의해야 할 몇 가지 사항이 있습니다.
- DNS 서버는 가용성이 높거나 백업 서버가 있어야 합니다. DNS 서버를 사용할 수 없게 되면 NGINX Plus는 업데이트를 중지합니다. 해당 레코드의 TTL 값을 무시하고 구성에서 기존 백엔드를 유지합니다(다시 시작하거나 구성을 다시 로드하지 않는 한).
- resolver 지시문을 사용하여 여러 이름 서버를 지정할 수 있으므로 그 중 하나가 다운되면 NGINX Plus가 다른 서버를 시도합니다.
- 소개에서 언급했듯이 NGINX Plus를 사용한 서비스 검색을 위한 DNS의 대안은 NGINX Plus API입니다. 이 API를 사용하면 upstream 그룹에서 서버를 추가하거나 제거하기 위한 간단한 HTTP 요청을 만들 수 있습니다.
4. 결론
NGINX Plus에서 완전히 사용할 수 있는 DNS를 통한 서비스 검색(Service Discovery)은 마이크로서비스 환경에서 로드 밸런서의 구성을 업데이트하는 간단한 방법을 제공합니다. 릴리스 9 이상에서 SRV 레코드를 지원하면 NGINX Plus가 IP 주소뿐만 아니라 백엔드의 포트 번호도 얻을 수 있으므로 NGINX Plus가 더욱 강력해집니다.
다른 향상된 기능과 함께 NGINX Plus용 DNS로 서비스 검색을 시도할 준비가 되셨습니까? 지금 무료 30일 평가판을 시작하거나 NGINX STORE에 연락하여 사용 사례에 대해 문의하십시오.
사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.
댓글을 달려면 로그인해야 합니다.