Cloud NAT 동적 포트 할당 사용

1. 개요

동적 포트 할당 (DPA)은 Cloud NAT의 새로운 기능입니다. DPA를 사용 설정하면 Cloud NAT가 필요에 따라 인스턴스의 포트 할당을 동적으로 확장/축소합니다. DPA는 포트를 최소값 미만으로 축소하거나 최대값을 초과하여 확장하지 않도록 최소 및 최대 포트 제한으로 구성되어 있습니다. 따라서 NAT 게이트웨이 뒤에 있는 일부 인스턴스에서 Cloud NAT 뒤의 모든 인스턴스에 포트를 할당할 필요 없이 연결 수를 동적으로 확장할 수 있습니다.

DPA를 사용하지 않으면 Cloud NAT 뒤의 모든 인스턴스에 minPortsPerVm 매개변수에서 정의한 대로 사용량에 관계없이 동일한 수의 포트가 할당됩니다 .

자세한 내용은 NAT DPA에 관한 문서 섹션 을 참고하세요.

학습할 내용

  • DPA에 대비하여 Cloud NAT 게이트웨이를 설정하는 방법입니다.
  • DPA 없이 포트 할당을 검사하는 방법
  • NAT 게이트웨이에 대해 DPA를 사용 설정하고 구성하는 방법
  • 병렬 이그레스 연결을 실행하여 DPA의 영향을 관찰하는 방법
  • DPA가 사용 설정된 NAT 게이트웨이에 NAT 규칙을 추가하는 방법
  • 여러 대상에 대한 이그레스 연결을 실행하여 규칙을 통해 DPA의 동작을 확인하는 방법

필요한 항목

  • Google Compute Engine의 기본 지식
  • 기본 네트워킹 및 TCP/IP 지식
  • 기본 Unix/Linux 명령줄 지식
  • Google Cloud의 네트워킹 실습과 같은 Google Cloud 네트워킹 둘러보기를 완료하면 도움이 됩니다.
  • '알파 액세스'가 포함된 Google Cloud 프로젝트 사용 설정되어 있습니다.
  • Cloud NAT 기본 사항에 대한 이해

2. Google Cloud 콘솔 및 Cloud Shell 사용

이 실습에서는 Google Cloud 콘솔과 Cloud Shell을 모두 사용하여 GCP와 상호작용하겠습니다.

Google Cloud Console

https://console.cloud.google.com에서 Cloud 콘솔에 액세스할 수 있습니다.

75eef5f6fd6d7e41.png

자습형 환경 설정

  1. Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
  • 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유해야 하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud Console은 고유한 문자열을 자동으로 생성합니다. 일반적으로 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID를 참조해야 하며(일반적으로 PROJECT_ID로 식별됨), 마음에 들지 않는 경우 임의로 다시 생성하거나 직접 지정해서 사용할 수 있는지 확인하세요. 프로젝트가 생성되면 프로젝트 ID가 '고정'됩니다.
  • 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참조하세요.
  1. 다음으로 Cloud 리소스/API를 사용하려면 Cloud Console에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼을 마친 후 비용이 결제되지 않도록 리소스를 종료하려면 Codelab의 끝에 있는 '삭제' 안내를 따르세요. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.

Cloud Shell 시작

Google Cloud를 노트북에서 원격으로 실행할 수 있지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.

GCP 콘솔에서 오른쪽 상단 툴바의 Cloud Shell 아이콘을 클릭합니다.

bce75f34b2c53987.png

환경을 프로비저닝하고 연결하는 데 몇 분 정도 소요됩니다. 완료되면 다음과 같이 표시됩니다.

f6ef2b5f13479f3a.png

가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉토리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 실습의 모든 작업은 브라우저만으로 수행할 수 있습니다.

3. 실습 설정

이 실습에서는 프로젝트 하나를 사용하여 각각 서브넷이 있는 두 개의 VPC를 만듭니다. 외부 IP 주소를 예약한 다음 Cloud Router를 사용한 Cloud NAT 게이트웨이 1개, 제작자 인스턴스 2개, 소비자 인스턴스 2개를 만들고 구성합니다. 기본 Cloud NAT 동작을 검증한 후 동적 포트 할당을 사용 설정하고 동작을 검증합니다. 마지막으로 NAT 규칙을 구성하고 DPA와 NAT 규칙 간의 상호작용을 관찰합니다.

네트워킹 아키텍처 개요:

a21caa6c333909d8.png

4. 외부 IP 주소 예약

이 실습에서 사용할 외부 IP 주소를 모두 예약해 보겠습니다. 이렇게 하면 소비자 및 제작자 VPC 모두에 모든 관련 NAT 및 방화벽 규칙을 작성하는 데 도움이 됩니다.

Cloud Shell에서

gcloud compute addresses  create nat-address-1 nat-address-2 \
 producer-address-1 producer-address-2 --region us-east4

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-1].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-2].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-1].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-2].

환경 변수로 예약된 IP 주소를 채웁니다.

export natip1=`gcloud compute addresses list --filter name:nat-address-1 --format="get(address)"`
export natip2=`gcloud compute addresses list --filter name:nat-address-2 --format="get(address)"`
export producerip1=`gcloud compute addresses list --filter name:producer-address-1 --format="get(address)"`
export producerip2=`gcloud compute addresses list --filter name:producer-address-2 --format="get(address)"`

출력된 내용은 없지만 주소가 제대로 채워졌는지 확인하기 위한 것입니다. 모든 환경 변수의 값을 출력해 보겠습니다.

env | egrep '^(nat|producer)ip[1-3]'

출력:

producerip1=<Actual Producer IP 1>
producerip2=<Actual Producer IP 2>
natip1=<NAT IP 1>
natip2=<NAT IP 2>

5. 프로듀서 VPC 및 인스턴스 설정

이제 프로듀서 리소스용 리소스를 만들어 보겠습니다. 제작자 VPC에서 실행 중인 인스턴스는 2개의 공개 IP인 'Producer-address-1'을 사용하여 인터넷 연결 서비스를 제공합니다. 'Producer-address-2' 에서 자세한 내용을 확인하실 수 있습니다.

먼저 VPC를 만들어 보겠습니다 Cloud Shell에서

gcloud compute networks create producer-vpc --subnet-mode custom

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project-ID>/global/networks/producer-vpc].
NAME      SUBNET_MODE  BGP_ROUTING_MODE  IPV4_RANGE  GATEWAY_IPV4
producer-vpc  CUSTOM       REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network producer-vpc --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network producer-vpc --allow tcp:22,tcp:3389,icmp

다음으로 us-east4에 서브넷을 만들어 보겠습니다. Cloud Shell에서

gcloud compute networks subnets create prod-net-e4 \
   --network producer-vpc --range 10.0.0.0/24 --region us-east4

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/prod-net-e4].
NAME         REGION    NETWORK       RANGE        STACK_TYPE  IPV6_ACCESS_TYPE  IPV6_CIDR_RANGE  EXTERNAL_IPV6_CIDR_RANGE
prod-net-e4  us-east4  producer-vpc  10.0.0.0/24  IPV4_ONLY

다음으로 NAT IP 주소가 포트 8080의 제작자 인스턴스에 도달할 수 있도록 허용하는 VPC 방화벽 규칙을 만들어 보겠습니다.

첫 번째 규칙의 경우 Cloud Shell에서 다음을 실행합니다.

gcloud compute firewall-rules create producer-allow-80 \
  --network producer-vpc --allow tcp:80 \
  --source-ranges $natip1,$natip2

출력:

Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/producer-allow-80].
Creating firewall...done.
NAME                 NETWORK       DIRECTION  PRIORITY  ALLOW     DENY  DISABLED
producer-allow-80    producer-vpc  INGRESS    1000      tcp:80          False

다음 단계는 두 개의 프로듀서 인스턴스를 만드는 것입니다.

제작자 인스턴스는 간단한 nginx 프록시 배포를 실행합니다.

인스턴스에 필요한 모든 소프트웨어를 신속하게 프로비저닝하기 위해 Debian APT 패키지 관리자를 사용하여 nginx를 설치하는 시작 스크립트로 인스턴스를 만듭니다.

NAT 규칙을 작성할 수 있도록 각 인스턴스에 다른 예약된 IP 주소를 프로비저닝합니다.

첫 번째 인스턴스를 만듭니다. Cloud Shell에서

gcloud compute instances create producer-instance-1 \
--zone=us-east4-a --machine-type=e2-medium \
--network-interface=address=producer-address-1,network-tier=PREMIUM,subnet=prod-net-e4 \
--metadata startup-script="#! /bin/bash
sudo apt update
sudo apt install -y nginx
mkdir /var/www/html/nginx/
cat <<EOF > /var/www/html/nginx/index.html
<html><body><h1>This is producer instance 1</h1>
</body></html>
EOF"

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/producer-instance-1].
NAME                 ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
producer-instance-1  us-east4-a  e2-medium                  10.0.0.2     <Producer IP1>  RUNNING

그런 다음 두 번째 인스턴스를 만듭니다. Cloud Shell에서

gcloud compute instances create producer-instance-2 \
--zone=us-east4-a --machine-type=e2-medium \
--network-interface=address=producer-address-2,network-tier=PREMIUM,subnet=prod-net-e4 \
--metadata startup-script="#! /bin/bash
sudo apt update
sudo apt install -y nginx
mkdir /var/www/html/nginx/
cat <<EOF > /var/www/html/nginx/index.html
<html><body><h1>This is producer instance 2</h1>
</body></html>
EOF"

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/producer-instance-2].
NAME                 ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
producer-instance-2  us-east4-a  e2-medium                  10.0.0.3     <Producer IP2>  RUNNING

6. 소비자 VPC, Cloud NAT, 인스턴스 설정

프로듀서 서비스를 만들었으므로 이제 소비자 VPC 및 Cloud NAT 게이트웨이를 만들 차례입니다.

VPC와 서브넷을 만든 후에는 TCP 소스 IP 범위에 대해 IAP를 허용하는 간단한 인그레스 방화벽 규칙을 추가합니다. 이렇게 하면 gcloud를 사용하여 소비자 인스턴스에 직접 SSH로 연결할 수 있습니다.

그런 다음 수동 할당 모드에서 간단한 Cloud NAT 게이트웨이를 만들고 예약된 주소인 'nat-address-1'을 만듭니다. 관련이 있습니다. Codelab의 이후 부분에서는 동적 포트 할당을 사용 설정하도록 게이트웨이의 구성을 업데이트하고 나중에 커스텀 규칙을 추가합니다.

먼저 VPC를 만들어 보겠습니다 Cloud Shell에서

gcloud compute networks create consumer-vpc --subnet-mode custom

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/consumer-vpc].
NAME          SUBNET_MODE  BGP_ROUTING_MODE  IPV4_RANGE  GATEWAY_IPV4
consumer-vpc  CUSTOM       REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network consumer-vpc --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network consumer-vpc --allow tcp:22,tcp:3389,icmp

다음으로 us-east4에 서브넷을 만들어 보겠습니다. Cloud Shell에서

gcloud compute networks subnets create cons-net-e4 \
   --network consumer-vpc --range 10.0.0.0/24 --region us-east4

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/cons-net-e4].
NAME         REGION    NETWORK       RANGE        STACK_TYPE  IPV6_ACCESS_TYPE  IPV6_CIDR_RANGE  EXTERNAL_IPV6_CIDR_RANGE
cons-net-e4  us-east4  consumer-vpc  10.0.0.0/24  IPV4_ONLY

다음으로 IAP 범위 주소가 포트 22의 소비자 인스턴스에 도달할 수 있도록 허용하는 VPC 방화벽 규칙을 만들어 보겠습니다.

첫 번째 방화벽 규칙의 경우 Cloud Shell에서 다음을 실행합니다.

gcloud compute firewall-rules create consumer-allow-iap \
  --network consumer-vpc --allow tcp:22 \
  --source-ranges 35.235.240.0/20

출력:

Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/<Project-ID>/global/firewalls/consumer-allow-iap].
Creating firewall...done.
NAME                 NETWORK       DIRECTION  PRIORITY  ALLOW     DENY  DISABLED
consumer-allow-iap  consumer-vpc  INGRESS    1000      tcp:22        False

NAT 게이트웨이를 만들기 전에 먼저 Cloud Router 인스턴스를 만들어야 합니다 (비공개 ASN 번호를 사용하지만 이 실습의 활동과는 관련이 없음). Cloud Shell에서

gcloud compute routers create consumer-cr \
--region=us-east4 --network=consumer-vpc \
 --asn=65501

출력:

Creating router [consumer-cr]...done.
NAME         REGION       NETWORK
consumer-cr  us-east4  consumer-vpc

그런 다음 NAT 게이트웨이 인스턴스를 만듭니다. Cloud Shell에서

gcloud compute routers nats create consumer-nat-gw \
    --router=consumer-cr \
    --router-region=us-east4 \
    --nat-all-subnet-ip-ranges \
    --nat-external-ip-pool=nat-address-1

출력:

Creating NAT [consumer-nat-gw] in router [consumer-cr]...done.

기본적으로 Cloud NAT 게이트웨이는 minPortsPerVm이 64로 설정된 상태로 생성됩니다.

소비자 테스트 인스턴스를 만듭니다. 나중에 인스턴스 내에서 참조할 수 있도록 예약된 제작자 IP를 여기에 채웁니다. Cloud Shell에서

gcloud compute instances create consumer-instance-1 --zone=us-east4-a \
--machine-type=e2-medium --network-interface=subnet=cons-net-e4,no-address \
--metadata=producer-service-ip1=$producerip1,producer-service-ip2=$producerip2

gcloud compute instances create consumer-instance-2 --zone=us-east4-a \
--machine-type=e2-medium --network-interface=subnet=cons-net-e4,no-address \
--metadata=producer-service-ip1=$producerip1,producer-service-ip2=$producerip2

출력:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/consumer-instance-1].
NAME                ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
consumer-instance-1  us-east4-a  e2-medium                  10.0.0.2                  RUNNING

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/consumer-instance-2].
NAME                ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
consumer-instance-2  us-east4-a  e2-medium                  10.0.0.3                  RUNNING

7. 기본 Cloud NAT 동작 확인

이 시점에서 소비자 인스턴스는 동일한 예약된 IP 'nat-address-1'을 사용하는 기본 Cloud NAT 동작을 사용합니다. 통신할 수 있습니다 또한 Cloud NAT에는 DPA가 아직 사용 설정되지 않았습니다.

다음 명령어를 실행하여 Cloud NAT가 소비자 인스턴스를 할당한 포트를 확인해 보겠습니다.

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

샘플 출력

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Consumer IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Consumer IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

위 출력에서 볼 수 있듯이 Cloud NAT는 동일한 외부 IP nat-address-1에서 인스턴스당 포트를 64개 할당했습니다.

DPA를 사용 설정하기 전에 동시에 열 수 있는 연결 수를 확인해 보겠습니다.

SSH를 통해 첫 번째 소비자 인스턴스에 연결합니다. Cloud Shell에서

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

이제 인스턴스 셸로 이동하게 됩니다.

샘플 출력 (간결성을 위해 전체 출력은 잘림)

External IP address was not found; defaulting to using IAP tunneling.
...
...
<username>@consumer-instance-1:~$

먼저 소비자 인스턴스 내에서 두 제작자 IP를 모두 가져와 환경 변수로 채웁니다.

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

그런 다음 두 프로듀서 인스턴스에 대해 curl을 실행하여 성공적으로 연결할 수 있는지 확인합니다.

<username>@consumer-instance-1:~$ curl http://$producerip1/nginx/
<html><body><h1>This is producer instance 1</h1>
</body></html>
<username>@consumer-instance-1:~$ curl http://$producerip2/nginx/
<html><body><h1>This is producer instance 2</h1>
</body></html>

이제 루프를 통해 curl을 실행하여 생산자 인스턴스 중 하나에 여러 개의 병렬 연결을 만들어 보겠습니다. Cloud NAT는 닫힌 소켓을 2분 동안 재사용할 수 없다는 점을 기억하세요. 따라서 2분 이내에 모든 연결 시도를 반복할 수 있는 한 이러한 방식으로 병렬 연결을 시뮬레이션할 수 있습니다.

인스턴스 SSH 세션에서 다음 명령어를 실행합니다.

while true; do for i in {1..64}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

64개의 병렬 연결을 성공적으로 열 수 있을 것으로 예상되며 스크립트는 다음을 출력합니다.

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

병렬 연결 수가 64개를 초과할 수 없음을 확인하려면 먼저 이전 소켓이 모두 삭제될 때까지 2분 정도 기다립니다. 그런 다음 동일한 한 줄을 다음과 같이 수정하고 다시 실행합니다.

while true; do for i in {1..70}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

이제 다음과 같은 출력이 표시됩니다.

Connection # 64 successful
Connection # 65 failed
Connection # 66 failed
Connection # 67 failed
Connection # 68 failed
Connection # 69 failed
Connection # 70 failed

Loop Done, Sleeping for 150s

이는 처음 64개 연결은 성공했지만 나머지 6개 연결은 포트 사용 불가로 인해 실패했음을 나타냅니다.

그런 다음 SSH 셸을 종료하고 다음 섹션에서 DPA를 사용 설정해 보겠습니다.

8. DPA 사용 설정 및 동작 확인

다음 gcloud 명령어를 실행하여 DPA를 사용 설정하고 VM당 최소 포트 할당을 64로, 최대 포트 할당을 1024로 설정합니다.

gcloud alpha compute routers nats update consumer-nat-gw --router=consumer-cr \
--region=us-east4 --min-ports-per-vm=64 --max-ports-per-vm=1024 \
--enable-dynamic-port-allocation

다음이 출력됩니다.

Updating nat [consumer-nat-gw] in router [consumer-cr]...done.

이제 get-nat-mapping-info를 다시 실행하여 두 인스턴스에 여전히 64개의 포트만 할당되어 있는지 확인합니다.

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

샘플 출력 (간략한 표시를 위해 잘림)

---
instanceName: consumer-instance-1
...
  - <NAT Consumer IP1>:1024-1055
  numTotalNatPorts: 32
...
- natIpPortRanges:
  - <NAT Consumer IP1>:32768-32799
  numTotalNatPorts: 32
...
---
instanceName: consumer-instance-2
...
  - <NAT Address IP1>:1056-1087
  numTotalNatPorts: 32
...
  - <NAT Address IP1>:32800-32831
  numTotalNatPorts: 32
...

인스턴스에서 아직 포트를 적극적으로 사용하지 않기 때문에 포트 할당 측면에서는 크게 변경되지 않았습니다.

SSH를 통해 인스턴스에 다시 연결해 보겠습니다.

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

제작자 IP 환경 변수를 다시 내보냅니다.

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

이전 루프를 다시 실행하여 병렬 연결을 시뮬레이션합니다.

while true; do for i in {1..70}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

이제 다음과 같은 출력이 표시됩니다.

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 70 successful
Loop Done, Sleeping for 150s

어떻게 되었을까요? Cloud NAT는 포트 사용량 증가 시 포트 할당을 증가시키지만, 이를 위해서는 네트워킹 레이어 전체에서 프로그래밍하는 데 다소 시간이 걸립니다. 따라서 나머지 연결 시도가 성공적으로 완료되기 전에 1~3회의 연결 제한 시간이 표시됩니다.

Google에서는 curl에 대해 엄격한 제한 시간 (5초)을 지정했지만, DPA가 포트 할당을 늘리는 동안 시간 제한이 더 긴 애플리케이션은 연결을 성공적으로 완료할 수 있습니다.

이러한 증가 동작은 다음과 같이 1024 연결 시도의 루프를 실행할 때 더 명확하게 볼 수 있습니다.

while true; do for i in {1..1024}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

이제 다음과 같은 출력이 표시됩니다.

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 129 successful
Connection # 130 failed

Connection # 131 failed
Connection # 258 successful
Connection # 259 failed

Connection # 260 failed
Connection # 515 successful
Connection # 516 failed

Connection # 1024 successful
Loop Done, Sleeping for 150s

Cloud NAT는 포트를 2의 거듭제곱으로 할당하므로 기본적으로 각 단계에서 할당을 두 배로 하게 되므로 64와 1024 사이의 2 거듭제곱 주변에서 연결 제한 시간이 강조 표시됩니다.

maxPortsPerVM를 1,024로 설정했으므로 연결 수는 1,024개를 넘을 수 없습니다. 비활성 포트를 재설정하기 위해 2분을 기다린 후 1,024보다 큰 수로 curl 루프를 다시 실행하여 테스트할 수 있습니다.

while true; do for i in {1..1035}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

예상대로 출력에 따르면 1024를 초과하는 연결은 실패하기 시작합니다.

<truncated output>
...
Connection # 1028 successful
Connection # 1029 failed
Connection # 1030 failed
Connection # 1031 failed
Connection # 1032 failed
Connection # 1033 failed
Connection # 1034 failed
Connection # 1035 failed
...
Loop Done, Sleeping for 150s

maxPortsPerVM를 1024로 설정하여 VM당 포트 할당을 1024 이상으로 확장하지 않도록 Cloud NAT에 지시했습니다.

SSH 세션을 종료하고 get-nat-mapping-info을 충분히 빠르게 다시 실행하면 할당된 추가 포트를 확인할 수 있습니다.

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

다음 출력을 관찰합니다.

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  - <NAT Address IP1>1088-1119
  -<NAT Address IP1>:1152-1215
  - <NAT Address IP1>:1280-1407
  - <NAT Address IP1>:1536-1791
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 512
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  - <NAT Address IP1>:32832-32863
  - <NAT Address IP1>:32896-32959
  - <NAT Address IP1>:33024-33151
  - <NAT Address IP1>:33536-33791
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 512
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

consumer-instance-1에는 1, 024개의 포트가 할당되었지만 consumer-instance-2에는 64개의 포트만 할당되어 있습니다. 이는 DPA 이전에는 쉽지 않았으며 Cloud NAT에 대한 DPA의 기능을 정확히 보여줍니다.

get-nat-mapping-info 명령어를 다시 실행하기 전에 2분 동안 기다리면 consumer-instance-1가 다시 최솟값인 포트 64개로 돌아온 것을 알 수 있습니다. 포트 할당을 늘리는 DPA의 기능뿐만 아니라 사용하지 않는 경우 동일한 NAT 게이트웨이 뒤에 있는 다른 인스턴스에서 잠재적으로 사용할 수 있도록 해제하는 기능을 설명합니다.

9. DPA로 Cloud NAT 규칙 테스트

또한 최근 Cloud NAT용 NAT 규칙 기능을 출시하여 고객이 특정 외부 대상에 특정 NAT IP를 사용하는 규칙을 작성할 수 있도록 했습니다. 자세한 내용은 NAT 규칙 문서 페이지를 참조하세요.

이 연습에서는 DPA와 NAT 규칙 간의 상호작용을 관찰합니다. 먼저 producer-address-2에 액세스할 때 nat-address-2를 사용하는 NAT 규칙을 정의해 보겠습니다.

다음 gcloud 명령어를 실행하여

gcloud alpha compute routers nats rules create 100 \
 --match='destination.ip == "'$producerip2'"' \
 --source-nat-active-ips=nat-address-2 --nat=consumer-nat-gw \
 --router=consumer-cr --router-region=us-east4

다음과 같은 출력이 표시되어야 합니다.

Updating nat [consumer-nat-gw] in router [consumer-cr]...done.

이제 get-nat-mapping-info를 다시 실행하여 새 NAT 규칙의 효과를 확인해 보겠습니다.

gcloud alpha compute routers get-nat-mapping-info consumer-cr --region=us-east4

다음이 출력됩니다.

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2

이제 ruleMappings 계층 구조 아래의 nat-address-2를 위해 추가 포트가 할당되었습니다 (지정된 최솟값도 64임).

그렇다면 인스턴스가 NAT 규칙에 의해 지정된 대상에 대해 많은 연결을 열면 어떻게 될까요? 지금부터 알아보겠습니다.

SSH를 통해 인스턴스에 다시 연결해 보겠습니다.

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

제작자 IP 환경 변수를 다시 내보냅니다.

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

이번에는 producerip2에 curl 루프를 다시 실행합니다.

while true; do for i in {1..1024}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip2/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

다음과 비슷한 출력이 표시됩니다.

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 129 successful
Connection # 130 failed

Connection # 131 failed
Connection # 258 successful
Connection # 259 failed

Connection # 260 failed
Connection # 515 successful
Connection # 516 failed

Connection # 1024 successful
Loop Done, Sleeping for 150s

기본적으로 이전 테스트를 미러링합니다. 인스턴스의 SSH 세션을 종료하고 nat 매핑을 다시 살펴보겠습니다.

gcloud alpha compute routers get-nat-mapping-info consumer-cr --region=us-east4

다음이 출력됩니다.

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    - <NAT Address IP2>:1088-1119
    - <NAT Address IP2>:1152-1215
    - <NAT Address IP2>:1280-1407
    - <NAT Address IP2>:1536-1791
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 512
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    - <NAT Address IP2>:32832-32863
    - <NAT Address IP2>:32896-32959
    - <NAT Address IP2>:33024-33151
    - <NAT Address IP2>:33280-33535
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 512
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1056-1087
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32800-32831
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2

위에서 볼 수 있듯이 consumer-instance-1의 기본 NAT IP ( nat-address-1의 IP)에는 여전히 64개의 포트만 할당되어 있지만 NAT 규칙의 IP (nat-address-2의 IP)에는 1,024개의 포트가 할당되어 있습니다. 그동안 consumer-instance-2는 모든 NAT IP에 대해 64개 포트의 기본 할당을 유지했습니다.

연습 삼아 이를 반대로 적용해 볼 수 있습니다. Cloud NAT가 모든 추가 포트를 할당 해제하도록 한 다음 producerip1에 대해 curl 루프를 실행하고 get-nat-mapping-info의 출력에 미치는 영향을 관찰합니다.

10. 정리 단계

반복 청구를 방지하려면 이 Codelab과 연결된 모든 리소스를 삭제해야 합니다.

먼저 모든 인스턴스를 삭제합니다.

Cloud Shell에서

gcloud compute instances delete consumer-instance-1 consumer-instance-2 \
 producer-instance-1 producer-instance-2 \
 --zone us-east4-a --quiet

예상 출력 :

Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/consumer-instance-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/consumer-instance-2].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/producer-instance-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/producer-instance-2].

다음으로 Cloud Router를 삭제합니다. Cloud Shell에서

gcloud compute routers delete consumer-cr \
 --region us-east4 --quiet

다음과 같은 출력이 표시됩니다.

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/routers/consumer-cr].

모든 외부 IP 주소를 해제합니다. Cloud Shell에서

gcloud compute addresses delete nat-address-1 \
 nat-address-2 producer-address-1 \
 producer-address-2 --region us-east4 --quiet

다음과 같은 출력이 표시됩니다.

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-2].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-3].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-2].

VPC 방화벽 규칙을 삭제합니다. Cloud Shell에서

gcloud compute firewall-rules delete consumer-allow-iap \
 producer-allow-80 --quiet

다음과 같은 출력이 표시됩니다.

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/consumer-allow-iap].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/producer-allow-80].

서브넷을 삭제합니다. Cloud Shell에서

gcloud compute networks subnets delete cons-net-e4 \
 prod-net-e4 --region=us-east4 --quiet

다음과 같은 출력이 표시됩니다.

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/cons-net-e4].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/prod-net-e4].

마지막으로 VPC를 삭제하겠습니다. Cloud Shell에서

gcloud compute networks delete consumer-vpc \
 producer-vpc --quiet

다음과 같은 출력이 표시됩니다.

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/consumer-vpc].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/producer-vpc].

11. 축하합니다.

Cloud NAT DPA 실습을 완료했습니다.

학습한 내용

  • DPA에 대비하여 Cloud NAT 게이트웨이를 설정하는 방법입니다.
  • DPA 없이 포트 할당을 검사하는 방법
  • NAT 게이트웨이에 대해 DPA를 사용 설정하고 구성하는 방법
  • 병렬 이그레스 연결을 실행하여 DPA의 영향을 관찰하는 방법
  • DPA가 사용 설정된 NAT 게이트웨이에 NAT 규칙을 추가하는 방법
  • 여러 대상에 대한 이그레스 연결을 실행하여 규칙을 통해 DPA의 동작을 확인하는 방법

다음 단계

©Google, Inc. or its affiliates. All rights reserved. 배포 금지.