[네떡스터디🔥kans] 쿠버네티스 서비스 이해하기 - External IP

CloudNet@ 가시다님이 진행하는 쿠버네티스 네트워크 스터디 KANS 3기 내용을 정리한 글입니다.

 

서비스에는 로드밸런스 타입과 다르게 수동으로 외부 IP를 할당하여 노출시킬 수 있는 방법이 있습니다. 외부 IP는 쿠버네티스 클러스터에서 IP 할당을 관리하지 않습니다.

 

직접 테스트해보기

kind를 통해 여러 개의 노드로 구성된 클러스터를 생성하고, 가상의 IP를 하나 생성하여 연결해보겠습니다.

 

 

이제 pod와 서비스를 각각 생성하겠습니다.

# 파드 생성하기 
kubectl run nginx --image=nginx:latest

# 서비스 생성하기
kubectl expose pod nginx --port 80

 

이렇게 생성하면 ClusterIP로 설정되기 때문에 여기에 external IP를 추가해보겠습니다.

external IPs에 10.100.10.10을 임의로 설정했습니다. 재미있는 점은 external IP를 추가해도 여전히 ClusterIP 모드로 작동하는 것을 확인할 수 있습니다.

변경 전/후

 

iptables 룰 확인

이제 노드에 들어가 iptables 룰을 확인해보면, 다음과 같은 룰이 생성됩니다:

-A KUBE-SERVICES -d 10.100.10.10/32 -p tcp -m comment --comment "default/nginx external IP" -m tcp --dport 80 -j KUBE-EXT-2CMXP7HKUVJN7L6M
-A KUBE-EXT-2CMXP7HKUVJN7L6M -m comment --comment "masquerade traffic for default/nginx external destinations" -j KUBE-MARK-MASQ
-A KUBE-EXT-2CMXP7HKUVJN7L6M -j KUBE-SVC-2CMXP7HKUVJN7L6M
-A KUBE-SVC-2CMXP7HKUVJN7L6M ! -s 10.244.0.0/16 -d 10.96.183.18/32 -p tcp -m comment --comment "default/nginx cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SVC-2CMXP7HKUVJN7L6M -m comment --comment "default/nginx -> 10.244.5.2:80" -j KUBE-SEP-L7M6Y7PFE6MAOWFF
-A KUBE-SEP-L7M6Y7PFE6MAOWFF -s 10.244.5.2/32 -m comment --comment "default/nginx" -j KUBE-MARK-MASQ
-A KUBE-SEP-L7M6Y7PFE6MAOWFF -p tcp -m comment --comment "default/nginx" -m tcp -j DNAT --to-destination 10.244.5.2:80

 

iptables를 그래프화

 

Local로 변경하기

이제 externalTrafficPolicy를 Local로 변경해보겠습니다.

worker1의 iptables 룰

# worker 1의 iptables룰
-A KUBE-EXTERNAL-SERVICES -d 10.100.10.10/32 -p tcp -m comment --comment "default/nginx has no local endpoints" -m tcp --dport 80 -j DROP
-A KUBE-SERVICES -d 10.100.10.10/32 -p tcp -m comment --comment "default/nginx external IP" -m tcp --dport 80 -j KUBE-EXT-2CMXP7HKUVJN7L6M

worker2의 iptables 룰

# worker2의iptables 룰
-A KUBE-SERVICES -d 10.100.10.10/32 -p tcp -m comment --comment "default/nginx external IP" -m tcp --dport 80 -j KUBE-EXT-2CMXP7HKUVJN7L6M
:KUBE-EXT-2CMXP7HKUVJN7L6M - [0:0]
-A KUBE-EXT-2CMXP7HKUVJN7L6M -s 10.244.0.0/16 -m comment --comment "pod traffic for default/nginx external destinations" -j KUBE-SVC-2CMXP7HKUVJN7L6M
-A KUBE-EXT-2CMXP7HKUVJN7L6M -m comment --comment "masquerade LOCAL traffic for default/nginx external destinations" -m addrtype --src-type LOCAL -j KUBE-MARK-MASQ
-A KUBE-EXT-2CMXP7HKUVJN7L6M -m comment --comment "route LOCAL traffic for default/nginx external destinations" -m addrtype --src-type LOCAL -j KUBE-SVC-2CMXP7HKUVJN7L6M
-A KUBE-EXT-2CMXP7HKUVJN7L6M -j KUBE-SVL-2CMXP7HKUVJN7L6M
-A KUBE-SVL-2CMXP7HKUVJN7L6M -m comment --comment "default/nginx -> 10.244.5.2:80" -j KUBE-SEP-L7M6Y7PFE6MAOWFF
-A KUBE-SEP-L7M6Y7PFE6MAOWFF -s 10.244.5.2/32 -m comment --comment "default/nginx" -j KUBE-MARK-MASQ
-A KUBE-SEP-L7M6Y7PFE6MAOWFF -p tcp -m comment --comment "default/nginx" -m tcp -j DNAT --to-destination 10.244.5.2:80
-A KUBE-SVC-2CMXP7HKUVJN7L6M ! -s 10.244.0.0/16 -d 10.96.183.18/32 -p tcp -m comment --comment "default/nginx cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SVC-2CMXP7HKUVJN7L6M -m comment --comment "default/nginx -> 10.244.5.2:80" -j KUBE-SEP-L7M6Y7PFE6MAOWFF

 

여기서 nginx가 실행 중인 worker1에서는 external IP에 대한 처리 룰과 동시에 drop하는 룰이 함께 적용되어 있는 것을 알 수 있습니다.

Local로 설정했으므로 drop이 되어야 하는데, 노드 내에서 nginx 파드가 없더라도 호출이 가능하다는 점이 이상합니다.

 

카운터 초기화 및 확인

카운터를 확인하기 위해 먼저 카운터를 초기화합니다.

iptables -Z

 

이렇게 카운터를 초기화 하고 호출을 해보았습니다.

iptables -L -v -n

 

카운터 초기화 후 호출을 시도한 결과입니다. 이상하게도 Drop이 되어야하는 룰은 타지 않은것을 확인할 수 있습니다. 

 

상세 분석을 해본결과로는 KUBE-EXTERNAL-SERVICES를 통과하기전에 KUBE-SERVICES를 통과해서 (iptables 순서로 인해) drop이 되지 않고 호출이 되는 이러한 현상이 발생한 것 같습니다.

 

 

혹시 몰라 노드의 내부가 아닌 외부에서 테스트해보기 위해 external IP에 노드의 IP를 추가하고도 테스트를 해보았습니다.

결과적으로는 nginx가 없는 엔드포인트의 노드 IP를 설정했는데도 정상적으로 호출이 성공하는 것을 확인했습니다.

서비스와 External IP 정보

 

노드로 호출해본 결과입니다.

 

코드 확인

코드 상으로는 external IP일 때 Local로 설정되면 drop되어야 하는 것이 맞습니다. 하지만 테스트한 구성이 잘못되었을 가능성이 있으며, 추가 확인이 필요합니다.

코드의 해당 부분은 pkg/proxy/iptables/proxier.go#L1114에서 확인할 수 있습니다.

pkg/proxy/iptables/proxier.go#L1114