NGINX Plus

클러스터 내 런타임 상태 공유

이 문서에서는 Sticky Learn 세션 지속성, 요청 제한 및 Key-Value Store 데이터를 포함하여 NGINX 클러스터 노드 간에 공유 메모리 Zone을 동기화하기 위해 NGINX Plus 를 사용하는 방법에 대해 설명합니다.

목차

1. 소개
2. 전제 조건
3. Zone Synchronization 구성
3-1. 동기화 세부 조정
4. 클러스터 노드 관리
4-1. 노드 시작
4-2. 노드 중지
4-3. 노드 제거하기
5. 클러스터에서 동기화 사용
5-1. Sticky Learn Zone 동기화
5-2. 요청 제한 Zone 동기화
5-3. Key-Value Storage Zone 동기화
6. 클러스터 상태 모니터링
7. API 구성
8. API로 Sync 상태 Polling

1. 소개

여러 NGINX Plus 인스턴스가 클러스터로 구성된 경우, 인스턴스 간에 다음과 같은 일부 상태 데이터를 공유할 수 있습니다.

  • Sticky Learn 세션 지속성
  • 요청 제한
  • Key-Value Storage

공유 메모리 Zone이 모든 클러스터 멤버에서 동일한 이름을 갖는다면 모든 NGINX Plus 인스턴스는 클러스터의 다른 모든 멤버와 상태 데이터를 교환할 수 있습니다.

2. 전제 조건

  • 클러스터 전체에 걸쳐 요청 처리 및 Key-Value 데이터의 제한을 공유하기 위한 NGINX Plus R16
  • 클러스터 전체에서 Sticky Learn 데이터의 제한을 공유하기 위한 NGINX Plus R15

클러스터 전반의 상태 공유는 결국 본질적으로 일관성을 유지합니다. 지연 시간, 낮은 대역폭, 패킷 손실은 상태 일관성에 상당한 부정적인 영향을 미치므로 트래픽 클러스터링에는 데이터센터급 네트워크를 사용하는 것이 좋습니다. 인터넷, 지역 또는 가용성 영역에 걸쳐 클러스터를 확장하는 것은 권장하지 않습니다.

3. Zone Synchronization 구성

클러스터의 각 NGINX Plus 인스턴스에 대해 NGINX 구성 파일을 열고 다음 단계를 수행합니다.

1. 클러스터 노드 간 동기화 사용: 최상위 stream 블록에서 zone_sync 지시문을 사용하여 server를 생성합니다.

 stream {
    #...

     server {
         zone_sync;
         #...
     }
 }

2. zone_sync_server 지시문을 사용하여 클러스터의 다른 모든 NGINX Plus 인스턴스를 지정합니다. resolver를 사용하는 경우 DNS 서비스를 사용하여 클러스터 노드를 동적으로 추가할 수 있습니다.

 stream {

     resolver 10.0.0.53 valid=20s;

     server {
         zone_sync;
         zone_sync_server nginx-cluster.example.com:9000 resolve;
     }
 }

그렇지 않으면 각 클러스터 노드를 zone_sync_server 지시문의 별도 줄로 정적으로 추가할 수 있습니다.

 stream {

     server {
         zone_sync;
         zone_sync_server nginx-node1.example.com:9000;
         zone_sync_server nginx-node2.example.com:9000;
         zone_sync_server nginx-node3.example.com:9000;
     }
 }

3. TCP 서버에 대한 listen 지시문의 ssl 매개변수를 지정하여 SSL을 활성화합니다.

stream {

    resolver 10.0.0.53 valid=20s;

    server {
        listen 10.0.0.1:9000 ssl;
        #...

        zone_sync;
        zone_sync_server nginx-cluster.example.com:9000 resolve;
        #...
    }
}

4. ssl_certificate 지시문을 사용하여 인증서 경로를 지정하고, ssl_certificate_key 지시문을 사용하여 Private Key 경로를 지정합니다. 인증서와 Key는 모두 PEM 형식이어야 합니다:

stream {

    resolver 10.0.0.53 valid=20s;

    server {
        listen 10.0.0.1:9000 ssl;

        ssl_certificate     /etc/ssl/nginx-1.example.com.server_cert.pem;
        ssl_certificate_key /etc/ssl/nginx-1.example.com.key.pem;

        zone_sync;
        zone_sync_server    nginx-cluster.example.com:9000 resolve;
        #...

    }
}

5. zone_sync_ssl 지시문으로 클러스터 서버 간의 SSL 연결을 사용하도록 설정하고, zone_sync_ssl_verifyzone_sync_ssl_trusted_certificate 지시문으로 다른 클러스터 서버 인증서의 확인을 사용하도록 설정합니다.

 stream {

     resolver 10.0.0.53 valid=20s;

     server {
         listen 10.0.0.1:9000 ssl;

         ssl_certificate        /etc/ssl/nginx-1.example.com.server_cert.pem;
         ssl_certificate_key    /etc/ssl/nginx-1.example.com.key.pem;

         zone_sync;
         zone_sync_server    nginx-cluster.example.com:9000 resolve;

         zone_sync_ssl;

         zone_sync_ssl_verify              on;
         zone_sync_ssl_trusted_certificate /etc/ssl/server_ca.pem;
         #...
     }
 }

6. 클러스터 노드에서 인증서 기반 인증을 설정합니다.

zone_sync_ssl_certificatezone_sync_ssl_certificate_key 지시문을 추가하여 나가는 연결에 대한 클라이언트 인s증서를 보냅니다.

그런 다음 ssl_verify_client 지시문을 on으로 설정하고 ssl_trusted_certificate 지시문으로 클라이언트 인증서 CA의 위치를 지정하여 클라이언트 인증서를 요구하도록 NGINX Plus 를 구성합니다.

 stream {

     resolver 10.0.0.53 valid=20s;

     server {
         listen 10.0.0.1:9000 ssl;

         ssl_certificate        /etc/ssl/nginx-1.example.com.server_cert.pem;
         ssl_certificate_key    /etc/ssl/nginx-1.example.com.key.pem;

         zone_sync;
         zone_sync_server    nginx-cluster.example.com:9000 resolve;

         zone_sync_ssl;

         zone_sync_ssl_verify              on;
         zone_sync_ssl_trusted_certificate /etc/ssl/server_ca.pem;

         zone_sync_ssl_certificate     localhost.crt;
         zone_sync_ssl_certificate_key localhost.key;

         ssl_verify_client       on;
         ssl_trusted_certificate /etc/ssl/client_ca.pem;
         #...
    }
}

3-1. 동기화 세부 조정

일반적으로 동기화 옵션을 조정할 필요는 없지만 경우에 따라 이러한 값 중 일부를 조정하는 것이 유용할 수 있습니다.

#...
zone_sync;
zone_sync_server nginx-cluster.example.com:9000 resolve;

zone_sync_buffers                256 4k;
zone_sync_connect_retry_interval 1s;
zone_sync_connect_timeout        5s;
zone_sync_interval               1s;
zone_sync_timeout                5s;
#...

zone_sync_buffers – 버퍼의 수와 크기를 제어합니다. 버퍼 수를 늘리면 버퍼에 저장되는 정보 수가 증가합니다.

zone_sync_connect_retry_interval – 클러스터 노드에 대한 연결 시도 사이의 시간 제한을 설정합니다.

zone_sync_connect_timeout – 클러스터 노드에 연결하는 데 소요되는 시간을 설정합니다.

zone_sync_interval – 공유 메모리 Zone에서 업데이트를 Polling하는 간격을 설정합니다. 이 값을 늘리면 클러스터 노드 간에 데이터 불일치가 발생할 수 있으며, 값을 줄이면 CPU 및 메모리 리소스가 많이 소모될 수 있습니다.

zone_sync_timeout – 클러스터 노드 간 TCP stream의 수명을 설정합니다. TCP stream이 이 값보다 오래 유휴 상태이면 연결이 닫힙니다.

4. 클러스터 노드 관리

4-1. 노드 시작

새 노드를 시작하려면 다음과 같이 하세요.

  • DNS의 경우, 클러스터 호스트 이름의 DNS 레코드를 새 노드의 IP 주소로 업데이트하고 인스턴스를 시작합니다.
  • 정적으로 추가된 노드의 경우, 노드의 주소를 nginx 설정 파일에 추가하고 다른 모든 노드를 Reload합니다.

노드가 시작되면 DNS 또는 정적 구성에서 다른 노드를 검색하고 업데이트 전송을 시작합니다. 다른 노드는 결국 DNS를 사용하여 새 노드를 발견하고 해당 노드로 업데이트를 Push하기 시작합니다.

4-2. 노드 중지

노드를 중지하려면 ‘QUIT’ 신호를 보내세요.

nginx -s quit

노드는 신호를 수신하는 즉시 영역 동기화를 완료하고 열려 있는 연결을 정상적으로 닫습니다.

4-3. 노드 제거하기

노드를 제거하려면 다음과 같이 하세요.

  • DNS의 경우, 클러스터 호스트 이름의 DNS 레코드를 업데이트하고 노드의 IP 주소를 제거합니다.
  • 정적으로 추가된 노드의 경우 각 노드의 nginx 구성 파일에서 노드 주소를 제거하고 각 노드를 Reload합니다.

노드가 제거되면 다른 노드는 제거된 노드에 대한 연결을 닫고 더 이상 연결을 시도하지 않습니다. 노드가 제거된 후에는 노드를 중지할 수 있습니다.

5. 클러스터에서 동기화 사용

5-1. Sticky Learn Zone 동기화

기존 구성에서 이미 Sticky Learn 기능을 사용하는 경우, 클러스터 내 각 NGINX Plus 인스턴스의 구성 파일에 있는 기존 sticky 지시문에 sync 매개변수를 추가하여 기존 상태를 클러스터 전체에서 간단히 공유할 수 있습니다. 클러스터의 다른 모든 NGINX 노드에서 Zone 이름이 동일해야 한다는 점에 유의하세요.

upstream my_backend {
    zone my_backend 64k;

		server backends.example.com resolve;
			sticky learn zone=sessions:1m
			create=$upstream_cookie_session
			lookup=$cookie_session
			sync;
}

server {
    listen 80;
		location / {
		    proxy_pass http://my_backend;
		}
}

5-2. 요청 제한 Zone 동기화

기존 구성에서 이미 전송률 제한을 사용하는 경우, 클러스터 내 각 NGINX Plus 인스턴스의 구성 파일에 있는 limit_req_zone 지시문에 sync 매개변수를 추가하기만 하면 클러스터 전체에 이러한 제한을 적용할 수 있습니다.

limit_req_zone $remote_addr zone=req:1M rate=100r/s sync;

server {
    listen 80;
    location / {
        limit_req zone=req;

        proxy_pass http://my_backend;
    }
}

Zone 이름은 클러스터의 다른 모든 NGINX 노드에서도 동일해야 합니다.

5-3. Key-Value Storage Zone 동기화

속도 제한 및 Sticky Learn과 마찬가지로 Key-Value 공유 메모리 Zone의 콘텐츠는 keyval_zone 지시문의 sync 매개변수를 사용하여 클러스터의 NGINX 디바이스 간에 공유할 수 있습니다.

keyval_zone zone=one:32k state=/var/lib/nginx/state/one.keyval sync;
keyval $arg_text $text zone=one;
#...
server {
    #...
    location / {
        return 200 $text;
    }

    location /api {
        api write=on;
    }
}

6. 클러스터 상태 모니터링

클러스터 상태 데이터는 NGINX Plus API 지표로 모니터링할 수 있습니다.

  • 공유 메모리 Zone의 이름
  • 노드의 총 레코드 수
  • 전송해야 하는 레코드 수
  • 클러스터의 각 노드별 sync 상태

7. API 구성

API 지표에 액세스하려면 API를 구성해야 합니다.

1. api 지시문을 사용하여 read-write 모드에서 NGINX Plus API를 활성화합니다.

# ...
 server {
     listen 80;
     server_name www.example.com;

     location /api {
         api write=on;
     }
 }

2. 예를 들어 localhost(127.0.0.1)에서만 액세스를 허용하고 HTTP 기본 인증을 사용하는 일부 사용자에게만 PATCH, POST, DELETE 메서드에 대한 액세스를 제한하는 등 이 위치에 대한 액세스를 제한할 것을 적극 권장합니다.

# ...
 server {
     listen 80;
     server_name www.example.com;

     location /api {
         limit_except GET {
             auth_basic "NGINX Plus API";
             auth_basic_user_file /path/to/passwd/file;
         }

         api   write=on;

         allow 127.0.0.1;
         deny  all;
     }
 }

8. API로 Sync 상태 Polling

공유 메모리 Zone의 동기화 상태를 가져오려면 curl과 같은 API 명령을 보내세요.

$ curl -s '127.0.0.1/api/8/stream/zone_sync' | jq

출력은 다음과 같습니다.

{
  "zones" : {
    "zone1" : {
      "records_pending" : 2061,
      "records_total" : 260575
    },
    "zone2" : {
      "records_pending" : 0,
      "records_total" : 14749
    }
  },
  "status" : {
    "bytes_in" : 1364923761,
    "msgs_in" : 337236,
    "msgs_out" : 346717,
    "bytes_out" : 1402765472,
    "nodes_online" : 15
  }
}

모든 노드의 레코드 수(records_total)가 거의 같고 나가는 Queue(records_pending)이 거의 비어 있으면 클러스터가 정상으로 간주될 수 있습니다.