Azure VM 에 직접 올린 쿠버네티스에서 서비스를 NodePort 로 노출했다. 같은 VNet 안에서 사설IP:30080 으로는 잘 붙는데, 밖에서 공인IP:30080 으로는 응답이 없다.
사설 IP 로 되고 공인 IP 로만 안 된다는 것은 쿠버네티스 쪽은 정상이고 경로 어딘가에서 패킷이 막혔다는 뜻이다. 서비스 타입이나 kube-proxy 를 뒤질 필요가 없다.
바깥에서 포트가 열려 있는지부터 본다.
nc -zv <VM_PUBLIC_IP> 30080
curl -v --connect-timeout 5 http://<VM_PUBLIC_IP>:30080/
Connection timed out 이면 방화벽 계층에서 버려진 것이고, Connection refused 면 패킷은 VM 까지 갔는데 듣는 프로세스가 없다는 뜻이다. 이 구분으로 원인을 절반으로 줄인다.
Azure 는 네트워크 보안 그룹의 기본 규칙에서 인터넷발 인바운드를 전부 막는다. NodePort 대역(기본 30000-32767) 중 실제 쓰는 포트를 열어야 한다.
az network nsg rule list -g <RG> --nsg-name <NSG> -o table
az network nsg rule create -g <RG> --nsg-name <NSG> \
--name allow-nodeport-30080 --priority 1010 \
--direction Inbound --access Allow --protocol Tcp \
--source-address-prefixes '<접속할_IP_대역>' \
--destination-port-ranges 30080
NSG 는 서브넷과 NIC 양쪽에 붙을 수 있고 둘 다 통과해야 트래픽이 들어온다. 서브넷 NSG 만 열고 NIC NSG 를 잊는 경우가 흔하다.
az network vnet subnet show -g <RG> --vnet-name <VNET> -n <SUBNET> --query networkSecurityGroup
az network nic show -g <RG> -n <NIC> --query networkSecurityGroup
원본 주소는 * 대신 접속할 사무실 대역이나 VPN 대역으로 좁힌다. NodePort 대역 전체를 인터넷에 열어 두면 클러스터의 모든 NodePort 서비스가 노출된다.
sudo firewall-cmd --list-all # RHEL 계열
sudo firewall-cmd --permanent --add-port=30080/tcp && sudo firewall-cmd --reload
sudo ufw status # Ubuntu
sudo ufw allow 30080/tcp
kubectl get svc -n <NS>
sudo ss -lntp | grep 30080
TYPE 이 ClusterIP 면 애초에 밖에서 닿지 않는다. NodePort 로 바꾸거나 인그레스를 앞에 둔다.
kubectl expose deployment nginx --port=80 --type=NodePort
NodePort 는 모든 노드에서 열리지만, 공인 IP 가 붙은 노드가 하나뿐이면 그 노드로만 들어올 수 있다. externalTrafficPolicy: Local 로 두면 파드가 떠 있지 않은 노드로 들어온 요청은 버려진다. 파드가 어느 노드에 있는지 확인한다.
kubectl get pod -o wide -n <NS>
kubectl get svc <SVC> -n <NS> -o jsonpath='{.spec.externalTrafficPolicy}{"\n"}'
az vm list-ip-addresses -g <RG> -n <VM> -o table
공인 IP 가 동적(Dynamic) 이면 VM 을 중지했다 켤 때 주소가 바뀐다. 고정으로 쓸 것이면 Static 으로 바꾼다. Azure 의 공인 IP 는 VM 안에서는 보이지 않는다. VM 의 NIC 에는 사설 IP 만 있고 NAT 는 플랫폼이 한다. ip addr 에 공인 IP 가 없는 것은 정상이다.
NodePort 를 인터넷에 직접 여는 것은 시험용으로만 쓴다. 상시 서비스라면 Azure Load Balancer 나 Application Gateway 를 앞에 두고 백엔드 풀에 VM 을 넣는다. AKS 가 아니라 직접 올린 클러스터에서는 LoadBalancer 타입 서비스가 자동으로 프로비저닝되지 않으므로, 로드밸런서를 손으로 만들어 NodePort 를 백엔드로 지정하거나 MetalLB 같은 온프레미스용 구현을 쓴다.