Kubernetes/Kubernetes 네트워크

Kubernetes Network

redcedar137 2025. 10. 5. 13:17

Kubernetes에서 네트워크를 이야기 하려면 먼저 Pod Network Service Network로 구분

 

 

 

 

Pod Network

Kubernetes에서 Pod Network는 Pod에 IP를 할당하고 Pod간 통신을 담당

먼저 Pod A와 Pod B간에 통신에 대해서 생각 해보고 (같은 Node에 있는 pod간 통신)

Pod A와 Pod C간의 통신을 생각(서로 다른 Node에 있는 Pod간 통신)

이렇게 Pod에 IP를 부여하고 Pod간 통신을 담당하는 역할이 CNI(Container Network Interface)

Kubernetes에는 기본적으로 Kubenet이라는 간단하고 기본적인 네트워크 플러그인을 제공해주지만

기본적이고 간단한 기능만 제공을 해주고 위 그림에서 예시 두 번째처럼 서로 다른 Node에 있는 Pod간의 통신은 제공하지 않음




그래서 Kubernetes를 제대로 쓰려면 CNI스펙을 준수하는 네트워크 플러그인을 사용

더 자세한 내용은 아래 사이트를 참고

https://github.com/containernetworking/cni




즉 CNI Plugin은 실제 Pod간 통신이 가능

Pod A와 Pod B가 통신을 하려고 하거나 Pod A와 Pod C가 통신 하려고 한다면 다음 두 가지가 필요

첫 번째, Pod마다 유일한 IP 주소가 있어야 하고 두 번째, Pod A의 입장에서 Pod B또는 Pod C의 경로 정보가 있어야 함




실습을 위해서 아래와 같은 네트워크를 구성

노드간 통신 Network는 192.168.56./0/24 이고 여기

Control Plan(Master)와 Node1과 Node2

구성도에서 Control plane은 생략했고

Node1의 IP는 192.168.56.110이고 Node2는 192.168.56.111

Node1에는 nginx Pod가 배포

Node2에는 nginx2 Pod가 배포

그리고 이 예제에서 CNI는 calico를 사용

먼저 Pod의 상태를 확인(위 그림의 내용)

먼저 node1에 실행 중인 Pod만 검색

kubectl get pods --field-selector spec.nodeName=node1 -o wide -A

kube-proxy와 Calico관련 pod는 node IP와 동일

이번에는 node2에서 실행 중인 Pod만 검색

kubectl get pods --field-selector spec.nodeName=node2 -o wide -A

kube-proxy와 Calico관련 pod는 node IP와 동일

마지막으로 control plane인 master node의 pod만 검색

kubectl get pods --field-selector spec.nodeName=master -o wide -A

여기서 control plane (master) node에서 보여지는 pod 중에서

ETCD, API Server, Controller manager, Sheduler, kube-proxy 등은 Node의 IP와 동일




Routing 정보 확인

이제 Pod간 통신을 위해서 Routing table이 어떻게 구성 되었는지 확인

node1의 Routing Table을 확인

node2의 Routing Table을 확인

Control Plane의 Routing table도 확인

결론

아래와 같이 Node1에 배포된 nginx pod에서 Node2에 배포된 nginx2 Pod와 통신이 가능한 이유는

Node1 Routing Table에 Node2에서 생성된 Pod를 위한 Network 대역이 Node2를 next hop으로 바라보고 있기 때문

node1에 배포된 nginx(192.168.166.137)에서 node2 배포된 nginx2(192.168.104.2)로 ping 테스트

그리고 node1에 배포된 nginx(192.168.166.137)에서 같은 node1에 있는 Pod인 192.168.166.129로 ping 테스트

첫 번째 테스트의 응답을 자세히 보면 ttl이 62로 2개 hop(Router)을 지난 것이 확인

반면 두 번째 테스트는 63으로 1개 hop(Router)만 지난 것이 확인

ping 테스트를 위해서 Pod에 ping util을 설치

apt-get update
apt-get install iputils-ping

추가적으로 node2의 nginx에서 tcpdump로 확인하면 아래와 같이 node1의 nginx 주소가 그대로 보임(NAT 되어지지 않음)





Service Network

Pod Network가 CNI의 몫이었다면, Service Network는 kube-proxy의 몫

Kube-Proxy에는 3가지 모드가 있음

  1. User Space Proxy Mode: 초기 Kubernetes 버전에서 사용된 모드입니다. 이 모드에서 kube-proxy는 들어오는 연결을 수신하고, 대상 파드 중 하나로 연결을 포워딩합니다. 연결이 사용자 공간을 통해 프록시되기 때문에 성능이 다른 모드에 비해 낮을 수 있습니다.
  2. iptables Proxy Mode: 이 모드에서 kube-proxy는 네트워크 트래픽을 파드로 라우팅하기 위해 Linux의 iptables 규칙을 사용합니다. 연결이 커널 공간에서 직접 처리되므로 사용자 공간 모드에 비해 성능이 향상됩니다. iptables 모드는 네트워크 트래픽을 효율적으로 처리할 수 있으나, 동적인 라우팅 로직이 커널에 의존하기 때문에 높은 수준의 커널 튜닝이 필요할 수 있습니다.
  3. IPVS (IP Virtual Server) Proxy Mode: IPVS 모드는 네트워크 트래픽을 처리하기 위해 IPVS 라이브러리를 사용합니다. IPVS는 L4 로드 밸런싱을 위해 설계되었으며, iptables 기반의 솔루션보다 훨씬 더 많은 연결과 높은 처리량을 지원합니다. IPVS 모드는 높은 성능과 확장성을 제공하지만, IPVS를 지원하는 커널이 필요합니다.

현재 구성 환경은 아래와 같음

위에서 구성된 2개의 nginx, nginx2 Pod를 노출하기 위한 nginx service를 배포

Kubernetes Cluster를 구성하면 core dns 혹은 Kube dns pods가 배포 되며

해당 pod를 위한 servcie도 배포

아래 명령어로 dns pod와 Service 확인이 가능

# dns pod 확인 하기 
kubectl get pods -o wide -n kube-system -l k8s-app=kube-dns

# dns service 확인 하기
kubectl get svc -n kube-system -l k8s-app=kube-dns

그리고 Pod 생성 시 /etc/resolve.conf에 dns service IP와

아래 내용은 nginx pod에 접속해서 etc/resolve.conf 를 출력한 결과

서비스를 배포하게 되면 먼저 core-dns 혹은 kube-dns에서 서비스 FQDN을 service IP를 value로 하는 DNS 레코드를 생성

아래 내용은 nginx pod에서 nginx서비스의 FQDN query 결과

즉 Kube-proxy는 Kubernetes 클러스터 내에서 서비스의 네트워크 트래픽을 관리

이 관리 방식에는 앞에서 언급한대로 3종류

User-space mode, iptables, IPVS가 해당


기본적으로, kube-proxy는 iptables를 사용하여, Kube-proxy에 의해 생성된 iptables 규칙을 보려면

iptables -t nat -L -n -v 을 사용

추가적으로 특정 서비스의 IP table을 보려면

iptables -t nat -L -n -v | grep -i 서비스명으로 확인

**iptables -t nat -L -n -v | grep -i nginx**

  • KUBE-SVC-2CMXP7HKUVJN7L6M: 이 규칙은 nginx 서비스의 클러스터 IP (10.103.40.64)로 들어오는 TCP 포트 80의 트래픽을 처리합니다. 주석에서 볼 수 있듯이, 이는 "default/nginx cluster IP"에 대한 것입니다.
  • KUBE-MARK-MASQ: 이 규칙은 마스커레이딩을 위해 특정 조건을 충족하는 트래픽에 대해 마크를 합니다. 마스커레이딩은 소스 IP를 변경하여 트래픽이 올바른 방향으로 돌아갈 수 있도록 하는 NAT의 한 형태입니다. 여기서는 클러스터 외부에서 nginx 서비스로 들어오는 트래픽과 특정 파드로 리디렉션되는 트래픽에 적용됩니다.
  • KUBE-SEP-3WSSZW54A3RPFGDC  KUBE-SEP-W7EB3RCP67253NQ5: 이 규칙들은 서비스 엔드포인트(특정 파드)로 트래픽을 리디렉션합니다. 예를 들어, "default/nginx -> 192.168.104.4:80"는 nginx 서비스를 제공하는 파드 중 하나로 트래픽을 전달합니다. "statistic mode random probability"는 여러 파드가 서비스를 제공할 때 로드 밸런싱을 위해 사용됩니다.
  • DNAT: 이 규칙은 목적지 NAT를 수행하여, 서비스의 클러스터 IP로 들어오는 트래픽을 실제 파드의 IP로 변경합니다. 여기서는 192.168.104.4:80  192.168.166.143:80으로 리디렉션하는 두 규칙이 있습니다.

위의 규칙들은 Kubernetes의 네트워크 트래픽을 파드로 올바르게 라우팅하기 위해 설정되어 있음

이는 클라이언트가 서비스의 클러스터 IP나 외부 IP를 통해 요청을 보낼 때, 이 요청이 실제로 서비스를 제공하는 파드 중 하나로 전달되도록 보장

Kubernetes는 이러한 규칙을 자동으로 관리하여, 서비스 디스커버리와 로드 밸런싱을 효율적으로 수행