Network & Server Factory

개인 공부 기록

Cloud/Azure

[Azure] Private Link Service 정리

1nfra 2026. 9. 25. 20:28
Private Link Service는 내가 만든 서비스를 Standard Load Balancer 뒤에 두고, 다른 VNet이나 다른 회사의 Subscription에서 Private Endpoint로 접속하게 해 주는 기능입니다. 트래픽이 NAT IP로 변환되어 들어오므로 두 VNet의 주소 대역이 겹쳐도 되고, VNet Peering 없이 서비스 하나만 골라서 공개할 수 있습니다. Azure PaaS에 붙이는 Private Endpoint의 반대편, 즉 Provider 쪽 구성입니다.

1. Private Link Service란

Storage나 SQL Database에 Private Endpoint를 붙이면 Azure가 운영하는 서비스를 내 VNet의 사설 IP로 쓸 수 있습니다(Private Endpoint와 Service Endpoint 비교). Private Link Service는 같은 방식을 내 서비스에 적용하는 기능입니다. 사내 공통 API, SaaS 제품, 파트너에게 제공하는 서비스를 Private Link Service로 만들면 상대방은 자기 VNet에 Private Endpoint만 만들어 접속합니다.

 

다른 VNet의 서비스에 접근하는 방법과 비교하면 차이가 분명합니다.

 

방식 공개 범위 주소 대역 겹침 용도
VNet Peering VNet 전체
(NSG로 제한)
불가 같은 조직의 VNet 연결
Public IP + 방화벽 인터넷에 공개
(IP 허용 목록으로 제한)
상관없음 인터넷 사용자 대상 서비스
Private Link Service 서비스 하나
(Load Balancer frontend)
가능 다른 팀·다른 회사에 사설 공개

2. 동작 구조

Consumer VNet의 Private Endpoint로 들어온 요청이 Private Link를 거쳐 Provider VNet의 NAT IP로 바뀐 뒤 Standard Load Balancer 뒤 VM으로 전달되는 구성

 

Consumer는 자기 서브넷에 Private Endpoint를 만들고, 그 사설 IP로 요청을 보냅니다. 요청은 Microsoft 백본을 통해 Provider의 Private Link Service로 전달되고, Private Link Service가 출발지 주소를 Provider 서브넷의 NAT IP로 바꿔 Load Balancer frontend로 넘깁니다. 두 VNet은 서로 라우팅되지 않고 Private Endpoint와 Private Link Service 한 쌍으로만 연결되므로, 위 그림처럼 두 VNet이 모두 10.0.0.0/16이어도 동작합니다.

 

구성 요소 위치 역할
Private Endpoint Consumer 서브넷 Consumer가 접속하는 사설 IP
Private Link Service Provider 서브넷 연결 승인, NAT IP로 출발지 변환
Standard Load Balancer Provider 서브넷
(내부 frontend)
Backend Pool의 VM으로 분산
Backend VM Provider 서브넷 실제 서비스(Backend Pool은 NIC 기준)

 

Consumer는 Private Link Service를 Resource ID나 Alias로 찾습니다. Alias는 prefix.GUID.region.azure.privatelinkservice 형식의 고유 이름이라 Resource ID를 알려 주지 않고도 서비스를 공유할 수 있고, prefix는 만든 뒤에 바꿀 수 없습니다.

3. 접근 제어와 연결 승인

Visibility에 포함된 Consumer만 연결을 요청할 수 있고, Auto-approval 목록에 있으면 바로 연결되며 나머지는 Provider가 승인해야 연결되는 흐름

 

누가 서비스를 볼 수 있는지는 Visibility로, 누구를 자동으로 연결할지는 Auto-approval로 정합니다. Auto-approval은 Visibility 목록의 일부만 넣을 수 있고, 목록에 없는 요청은 Pending 상태로 남아 Provider가 Approve나 Reject를 해야 합니다. 다른 Microsoft Entra 테넌트에서 오는 연결도 가능하지만 이때는 수동 승인이 필요합니다.

 

Visibility 연결 요청 가능 범위 용도
RBAC Only Private Link Service에 권한이 있는 사용자 같은 조직의 여러 VNet·Subscription
Restricted by Subscription 지정한 Subscription 목록 계약한 고객·파트너에게만 제공
Anyone with Alias Alias를 아는 누구나 공개 SaaS 서비스
(승인 단계로 통제)

4. NAT IP와 원래 출발지 IP 확인

Backend VM에서 보이는 출발지 IP는 Consumer의 IP가 아니라 Private Link Service의 NAT IP입니다. NAT IP 하나는 Backend VM 하나당 TCP 연결 64,000개(포트 64k개)를 처리하고, Private Link Service 하나에 NAT IP를 최대 8개까지 붙일 수 있습니다. 연결이 많아지면 NAT IP를 늘리거나, Backend VM을 늘리거나, 같은 Load Balancer에 Private Link Service를 더 만듭니다(Load Balancer 하나에 최대 8개).

 

항목 값
NAT IP 개수 Private Link Service당 최대 8개
(최소 1개는 유지)
NAT IP 1개당 연결 Backend VM당 TCP 64,000개
Load Balancer당 Private Link Service 최대 8개(frontend IP별로 하나씩)
프로토콜 TCP, UDP(IPv4만, ICMP 불가)
Idle Timeout 약 5분(300초)

 

어느 Consumer가 보낸 요청인지 알아야 하면 TCP Proxy v2(Proxy Protocol)를 켭니다. 켜면 연결 앞에 원래 출발지 IP와 Private Endpoint의 LinkID가 붙어서 전달되고, LinkID는 Private Endpoint Connection의 linkIdentifier 값과 같아서 고객별 과금이나 로그 분리에 쓸 수 있습니다. 다만 같은 Load Balancer와 Backend Pool을 쓰는 모든 서버가 Proxy Protocol을 이해해야 하고, 그렇지 않으면 Health Probe부터 실패합니다.

5. Azure CLI로 구성해 보기

한 Subscription 안에서 Provider와 Consumer VNet을 같은 10.0.0.0/16으로 만들고, 주소가 겹쳐도 Private Link Service로 접속되는지 확인합니다. 실제로 다른 Subscription에서 연결할 때도 Consumer 쪽 명령은 같습니다.

5.1 Provider: Load Balancer와 Backend VM

RG=rg-pls
LOC=koreacentral
az group create --name $RG --location $LOC

# Provider VNet, Private Link Service를 둘 서브넷은 Network Policy를 끔
az network vnet create --resource-group $RG --name vnet-provider \
  --address-prefixes 10.0.0.0/16 --subnet-name snet-app --subnet-prefixes 10.0.1.0/24
az network vnet subnet update --resource-group $RG --vnet-name vnet-provider \
  --name snet-app --private-link-service-network-policies Disabled

# 내부 Standard Load Balancer
az network lb create --resource-group $RG --name lb-app --sku Standard \
  --vnet-name vnet-provider --subnet snet-app \
  --frontend-ip-name fe-app --backend-pool-name be-app
az network lb probe create --resource-group $RG --lb-name lb-app \
  --name probe-http --protocol tcp --port 80
az network lb rule create --resource-group $RG --lb-name lb-app --name rule-http \
  --protocol tcp --frontend-port 80 --backend-port 80 \
  --frontend-ip-name fe-app --backend-pool-name be-app --probe-name probe-http

# Backend VM을 만들고 NIC를 Backend Pool에 추가
az vm create --resource-group $RG --name vm-app --image Ubuntu2404 \
  --size Standard_D2s_v5 --vnet-name vnet-provider --subnet snet-app \
  --public-ip-address "" --nsg "" --admin-username azureuser --generate-ssh-keys
az network nic ip-config address-pool add --resource-group $RG \
  --nic-name vm-appVMNic --ip-config-name ipconfigvm-app \
  --lb-name lb-app --address-pool be-app

# 테스트용 웹 서버(인터넷 연결 없이 동작)
az vm run-command invoke --resource-group $RG --name vm-app \
  --command-id RunShellScript --scripts \
  "echo provider-ok > /tmp/index.html; \
   systemd-run --unit=web python3 -m http.server 80 --directory /tmp"

5.2 Provider: Private Link Service

az network private-link-service create --resource-group $RG --name pls-app \
  --vnet-name vnet-provider --subnet snet-app \
  --lb-name lb-app --lb-frontend-ip-configs fe-app

# Consumer에게 알려 줄 Resource ID와 Alias
PLS_ID=$(az network private-link-service show --resource-group $RG \
  --name pls-app --query id --output tsv)
az network private-link-service show --resource-group $RG \
  --name pls-app --query alias --output tsv

5.3 Consumer: Private Endpoint 요청

# Provider와 같은 주소 대역의 Consumer VNet
az network vnet create --resource-group $RG --name vnet-consumer \
  --address-prefixes 10.0.0.0/16 --subnet-name snet-pe --subnet-prefixes 10.0.2.0/24

# 수동 승인 요청(다른 Subscription의 Provider에 연결할 때와 같은 방식)
az network private-endpoint create --resource-group $RG --name pe-app \
  --vnet-name vnet-consumer --subnet snet-pe \
  --private-connection-resource-id $PLS_ID --connection-name conn-app \
  --manual-request true --request-message "team-a access"

5.4 Provider: 연결 승인과 확인

# Pending 상태의 연결을 찾아 승인
CONN=$(az network private-link-service show --resource-group $RG --name pls-app \
  --query "privateEndpointConnections[0].name" --output tsv)
az network private-link-service connection update --resource-group $RG \
  --service-name pls-app --name $CONN --connection-status Approved

# Private Endpoint의 사설 IP
PE_NIC=$(az network private-endpoint show --resource-group $RG --name pe-app \
  --query "networkInterfaces[0].id" --output tsv)
PE_IP=$(az network nic show --ids $PE_NIC \
  --query "ipConfigurations[0].privateIPAddress" --output tsv)

# Consumer VNet의 VM에서 호출하면 provider-ok가 돌아옴
az vm create --resource-group $RG --name vm-client --image Ubuntu2404 \
  --size Standard_D2s_v5 --vnet-name vnet-consumer --subnet snet-pe \
  --public-ip-address "" --nsg "" --admin-username azureuser --generate-ssh-keys
az vm run-command invoke --resource-group $RG --name vm-client \
  --command-id RunShellScript --scripts "curl -s http://$PE_IP"

# 실습이 끝나면 삭제
az group delete --name $RG --yes --no-wait

승인 전에는 Private Endpoint가 만들어져도 연결 상태가 Pending이라 호출이 되지 않습니다. PaaS와 달리 Private Link Service에는 Azure가 만들어 주는 privatelink DNS Zone이 없으므로, 이름으로 부르려면 Consumer가 자기 Private DNS Zone에 A 레코드(예: api.partner.internal → Private Endpoint IP)를 직접 만듭니다(Private DNS Zone과 DNS Private Resolver 정리).

6. 운영 시 주의점

항목 조치
Load Balancer SKU Basic Load Balancer는 쓸 수 없습니다. Standard Load Balancer에 Backend Pool을 NIC 기준으로 구성합니다.
Region Private Link Service는 Load Balancer, VNet과 같은 Region에 만듭니다. Private Endpoint는 다른 Region, 온프레미스(VPN·ExpressRoute)에서도 접속할 수 있습니다.
연결이 오래 유지되지 않음 Idle Timeout이 약 5분이므로 애플리케이션의 TCP keep-alive를 300초보다 짧게 잡습니다.
연결 수 부족 NAT IP(최대 8개), Backend VM, 같은 Load Balancer의 Private Link Service(최대 8개)를 늘립니다.
Proxy Protocol 켠 뒤 장애 같은 Load Balancer와 Backend Pool의 모든 서버가 Proxy Protocol을 처리하는지 확인합니다. 하나라도 못 하면 Health Probe가 실패합니다.
Inbound NAT Rule Backend Pool 타입의 Inbound NAT Rule은 Load Balancing Rule이 있어야 Private Link Service와 함께 동작합니다.
Load Balancer 없이 연결 사설 IP로 바로 연결하는 Direct Connect는 Public Preview이고 지원 Region에 Korea Central이 없습니다.

7. 정리

  • Private Link Service는 Standard Load Balancer frontend를 다른 VNet·Subscription·테넌트에 Private Endpoint로 공개하는 Provider 쪽 기능입니다.
  • 트래픽은 NAT IP로 변환되므로 주소 대역이 겹쳐도 되고, 원래 출발지가 필요하면 TCP Proxy v2로 LinkID를 받습니다.
  • Visibility로 요청 범위를, Auto-approval로 자동 연결 대상을 정하고, 나머지 요청은 Provider가 직접 승인합니다.

참고

728x90
서울
--:--:--
-전체 글
-카테고리
오늘 방문