Kubernetes에서 파드는 언제든 생성되고 삭제될 수 있는 일시적인 존재이지만, 그 위에서 동작하는 애플리케이션들은 서로 끊김 없이 통신할 수 있어야 합니다. 이러한 파드 간 통신을 실제로 구현해주는 것이 CNI(Container Network Interface) 플러그인이며, 그중에서도 Calico는 L3 라우팅 기반 아키텍처와 강력한 NetworkPolicy 기능 덕분에 프로덕션 환경에서 널리 사용되는 CNI 중 하나입니다. 이번 글에서는 Calico 환경에서 같은 노드 내부의 파드끼리 통신하는 방식과 서로 다른 노드에 있는 파드끼리 통신하는 방식을 살펴보겠습니다.
목차
1. Kubernetes 네트워크 모델과 Calico 기본 구조
2. 같은 노드 내부 파드 간 통신
3. 다른 노드에 있는 파드 간 통신
4. EKS에서 VPC CNI와 Calico를 사용하는 구조
5. 결론
#1 Kubernetes 네트워크 모델과 Calico 기본 구조
Kubernetes는 네트워크에 대해 다음과 같은 원칙을 요구합니다.
모든 노드와 파드는 NAT 없이도 다른 파드와 통신할 수 있어야 한다

Kubernetes CNI 플러그인 Calico는 이 요구사항을 L2 Bridge(스위칭)가 아닌 L3 Routing으로 구현한다는 점이 가장 큰 특징입니다. Flannel 같은 CNI가 노드 내부에 cni0 bridge를 만들어 파드들을 스위치처럼 연결하는 방식이지만, Calico는 파드 하나하나를 라우팅 대상으로 취급하여 호스트의 라우팅 테이블로 트래픽을 제어합니다. DaemonSet인 calico-node pod의 구성요소는 크게 다음 세 가지와 같습니다.
- Felix : kube-apiserver로부터 etcd에 저장된 Calico 리소스 상태를 감시하다가 NetworkPolicy와 같은 리소스가 생성되는 등의 변화가 생기면 리눅스 커널(라우팅 테이블, iptables 등)을 업데이트하는 Agent Daemon.
- BIRD : 노드 간 Pod Subnet IP Block(Pod 대역)을 BGP 기반으로 라우팅 테이블을 공유하는 Daemon.
- Veth Pair
veth pair란?
Virtual Ethernet Pair라는 뜻으로, 파드는 자신만의 네트워크 네임스페이스를 가지기 때문에, 기본적으로는 호스트나 다른 파드와 격리된 네트워크 환경을 가집니다. veth pair는 양쪽 끝이 서로 연결된 가상의 랜케이블입니다. 파드에서 나가는 모든 패킷은 이 veth pair를 통해 Host Namespace로 전달되고, 그 이후의 경로는 Host 커널의 라우팅 테이블이 결정합니다.
#2 같은 노드 내부 파드 간 통신

먼저 같은 노드 안에 있는 Pod A가 Pod B로 패킷을 보내는 상황부터 살펴보겠습니다. Pod A 입장에서는 단순히 Dest. IP가 Pod B의 IP인 패킷을 자신의 eth0 인터페이스로 내보냅니다. 하지만 실제로 이 eth0은 호스트 쪽의 veth 인터페이스와 한 쌍으로 연결되어 있기 때문에, 패킷은 곧바로 Host Namespace로 넘어오게 됩니다. 패킷은 Pod A의 eth0에서 출발해 veth pair를 거쳐 호스트로 올라오고, Host Linux Kernel의 라우팅 테이블을 Look-Up한 뒤 다시 Pod B 쪽 veth pair를 통해 파드 B의 eth0으로 들어갑니다.
여기서 중요한 점은 Calico가 Flannel처럼 cni0와 같은 bridge를 사용하지 않는다는 것입니다. 같은 노드 안에 있는 파드끼리 통신하더라도, Calico는 L2 스위칭하는 방식이 아니라 L3 라우팅을 사용합니다. Host Network Namespace의 라우팅 테이블을 보면 해당 노드에 존재하는 파드마다 /32 단위의 라우트가 등록되어 있는 것을 확인할 수 있습니다.

위 예시에서 192.168.243.209, 192.168.243.210 ...은 각각 이 노드에 존재하는 파드 IP입니다. 각 파드 IP가 특정 cali~라는 device 인터페이스와 직접 연결되어 있습니다. 마지막의 blackhole이라는 행은 이 노드에 할당된 파드 IP 블록 중 아직 실제 파드에 배정되지 않은 IP로 향하는 트래픽을 버리는 역할을 합니다.
Service IP로 통신하는 경우
지금까지는 Pod A에서 Dest. IP를 Pod B로 지정했다는 전제였습니다. 하지만 실제 애플리케이션에서는 파드가 재시작되면서 IP가 바뀔 수 있기 때문에 직접 Pod IP를 목적지로 사용하지 않습니다. 그래서 Kubernetes 환경에서는 파드 앞에 Service를 두고, 애플리케이션은 파드 IP가 아니라 Service의 ClusterIP를 바라보게 만듭니다. 예를 들어 파드 A가 다음 주소로 요청을 보낸다고 가정해 보겠습니다.
10.96.0.10:80
이 주소는 Service IP입니다. 이 가상 IP로 향하는 패킷을 실제 Pod IP로 DNAT해주는 역할을 하는 것이 kube-proxy와 iptables입니다. kube-proxy는 각 노드에서 실행되며, API 서버를 감시하다가 Service나 EndpointSlice가 변경되면 그 내용을 각 노드의 iptables 규칙으로 반영합니다. 파드 A가 Service IP로 요청을 보냅니다.
DNAT가 끝난 뒤에는 Dest. IP가 실제 Pod IP로 바뀌었기 때문에, 이후에는 일반적인 파드 간 통신과 동일하게 호스트 라우팅 테이블을 따라갑니다. 참고로 응답 패킷은 커널의 conntrack이 기존 연결 정보를 기억하고 있기 때문에, 자동으로 역변환되어 요청을 보낸 파드에게 돌아갑니다. 같은 노드 내부 통신 문제가 발생했을 때는 다음 명령어들로 확인할 수 있습니다.
ip route
iptables-save -t nat | grep KUBE
tcpdump -i caliXXX
ip route로 /32 라우트가 존재하는지 확인하고, iptables-save로 Service IP에 대한 DNAT 규칙이 제대로 생성되었는지 확인할 수 있습니다. 실제 패킷이 veth를 지나가는지는 tcpdump로 확인할 수 있습니다.
#3 다른 노드에 있는 파드 간 통신

다른 노드에 있는 파드와 통신하려면, 각 노드는 어떤 Pod IP 대역이 어느 노드에 할당되어 있는지를 알고 있어야 합니다. 이러한 라우팅 정보를 교환하는 데 OSPF를 사용할 수도 있지만, Calico는 노드 간 경로 advertise와 Policy 제어, 대규모 환경에서의 확장성에 더 적합한 BGP(Border Gateway Protocol)를 사용합니다. 각 노드의 BIRD 데몬은 자신이 담당하는 Pod IP Block을 다른 노드에 광고하고, 전달받은 라우팅 정보는 각 노드의 리눅스 라우팅 테이블에 반영됩니다.
#2 같은 노드 내부 통신에서 확인했던 호스트 라우팅 테이블에는 다른 노드의 파드 대역에 대한 정보도 함께 등록되어 있습니다.

위 라우팅 테이블을 살펴보겠습니다. 목적지가 192.168.38.128/26 대역이면 패킷은 enp0s8 인터페이스를 통해 Next Hop인 10.50.10.30 노드로 전달되고, 192.168.79.0/26 대역이면 10.50.10.20 노드로 전달됩니다. 이는 Calico의 BGP 라우팅을 통해 학습된 다른 노드의 파드 CIDR 경로이며, proto 80은 해당 경로가 동적 라우팅 프로토콜에 의해 등록되었음을 나타냅니다. 10.50.0.0/16은 노드 간 통신에 사용하는 네트워크로, enp0s8에 연결되어 있습니다. 반면 파드 대역이나 내부 네트워크와 일치하지 않는 외부 목적지로 향하는 패킷은 기본 경로인 default via 10.0.2.1 dev enp0s3을 따라 외부 네트워크로 전달됩니다.
위 라우팅 테이블은 Direct 모드로 구성된 경로입니다. Direct 모드 이외에도 노드 간 트래픽을 실제로 전달하는 방식은 크게 세 가지로 나눌 수 있습니다.
Direct 모드
Direct 모드는 캡슐화 없이 파드 IP를 그대로 사용해 물리 네트워크에서 라우팅하는 방식입니다. 성능은 가장 좋지만, 물리 네트워크가 파드 IP 대역을 라우팅할 수 있어야 합니다. 즉, 노드들이 같은 L2 네트워크에 있거나, 네트워크 장비가 파드 대역에 대한 라우팅 정보를 알고 있어야 합니다. On-premise환경에서는 네트워크 장비와 BGP Peering을 맺어 파드 CIDR을 직접 advertise하는 방식으로 구성할 수도 있습니다.
IPIP 모드
IPIP 모드는 원래 파드 패킷을 노드 IP 헤더로 한 번 감싸서 전달하는 방식입니다. 이때 tunl0 인터페이스가 사용됩니다. IPIP 모드가 적용된 노드의 라우팅 테이블에는 원격 노드의 Pod CIDR로 향하는 경로가 다음과 같이 표시될 수 있습니다.
192.168.38.128/26 via 10.50.10.30 dev tunl0 proto 80 onlink
192.168.79.0/26 via 10.50.10.20 dev tunl0 proto 80 onlink
이는 192.168.38.128/26 대역의 파드로 가는 패킷은 10.50.10.30 노드를 통해 전달하고, 192.168.79.0/26 대역은 10.50.10.20 노드를 통해 전달하라는 의미입니다. 이때 패킷은 물리 인터페이스로 바로 전달되지 않고 먼저 tunl0 인터페이스에서 IPIP 캡슐화됩니다. 예를 들어 내부의 원래 파드 패킷 헤더가 다음과 같다면,
Source IP: 192.168.10.5
Destination IP: 192.168.79.5
IPIP 캡슐화 후에는 외부에 노드 IP 헤더가 추가됩니다.
Source IP: 10.50.10.10
Destination IP: 10.50.10.20
Protocol: IP-in-IP(4)
물리 네트워크에서는 외부 헤더만 기준으로 패킷을 전달하므로, 파드 IP 대역이나 Pod CIDR을 알 필요가 없습니다. 외부 헤더의 목적지가 상대 노드 IP인 10.50.10.20이기 때문에 일반적인 노드 간 IP 통신처럼 패킷을 전달할 수 있습니다. 목적지 노드에 도착하면 tunl0에서 외부 헤더를 제거한 뒤, 내부 패킷을 실제 목적지 파드로 전달합니다.
VXLAN 모드
VXLAN 모드는 UDP 기반 VXLAN 캡슐화를 사용하는 방식입니다. 특히 Azure 환경에서는 IPIP 프로토콜이 제한되므로 VXLAN을 선택하는 경우가 있습니다. 다만 VXLAN은 IPIP보다 헤더 오버헤드가 더 크기 때문에, MTU 설정을 더 신경 써야 합니다.
노드 간 통신에서 고려할 점
노드 간 통신에서는 캡슐화 방식과 MTU 설정이 중요합니다. Direct 모드는 캡슐화가 없기 때문에 성능상 가장 유리합니다. 하지만 물리 네트워크가 파드 IP 대역을 라우팅할 수 있어야 하므로 네트워크 환경의 제약을 받습니다. 반면 IPIP나 VXLAN은 물리 네트워크가 파드 IP를 몰라도 노드 간 통신이 가능하다는 장점이 있습니다. 대신 캡슐화 헤더가 추가되므로 MTU를 적절히 조정해야 합니다. 일반적으로는 다음과 같은 방향으로 설계합니다.
- IPIP 사용 시 MTU를 약 1480 수준으로 조정
- VXLAN 사용 시 MTU를 약 1450 수준으로 조정
또한 Service 수가 많아지는 대규모 클러스터에서는 kube-proxy의 iptables 모드가 부담이 될 수 있습니다.
iptables 모드는 규칙을 순차적으로 평가하는 구조이기 때문에, Service와 Endpoint가 많아질수록 규칙 수도 함께 늘어납니다. 이런 경우에는 다음과 같은 선택지도 고려할 수 있습니다.
- kube-proxy IPVS 모드 사용
- Calico eBPF CNI 사용
IPVS, eBPF CNI 모드에 대해서는 다음 글에서 성능을 비교해보며 다뤄보도록 하겠습니다.
#4 EKS에서 VPC CNI와 Calico를 함께 사용하는 구조
Amazon EKS에서는 일반적으로 Amazon VPC CNI가 파드 네트워크를 구성하고, Calico는 NetworkPolicy만 담당하는 방식으로 함께 사용합니다. Amazon VPC CNI를 사용하면 VPC Subnet의 실제 사설 IP를 할당받습니다.
Node 1: 10.0.1.10
Pod A: 10.0.1.101
Node 2: 10.0.2.10
Pod B: 10.0.2.102
Pod A와 Pod B의 IP는 모두 VPC 내부에서 직접 라우팅할 수 있는 주소입니다. 따라서 일반적인 Calico 구성처럼 IP-in-IP 캡슐화나 BGP, VXLAN을 사용하지 않습니다. 다른 노드의 파드로 패킷을 보낼 때도 Pod IP를 그대로 유지한 채 EC2 ENI와 AWS VPC 네트워크를 통해 전달됩니다.
#5 결론
온프레미스 환경이라면 Calico의 BGP와 IPIP·VXLAN 구성을 직접 설계할 수 있습니다. 반면 EKS에서는 파드 IP와 라우팅을 AWS VPC CNI에 맡기고, Calico는 NetworkPolicy에 집중시키는 구성이 운영 복잡도를 줄이는 데 더 적합합니다. CNI를 구성할 때에는 성능 비교, 네트워크 경로를 직접 제어할 것인지, 클라우드의 Native Routing에 맡길 것인지를 잘 고민해야 합니다.
'Computer Science' 카테고리의 다른 글
| Amazon Bedrock 기반 RAG와 Agent 아키텍처 설계 (0) | 2026.05.22 |
|---|---|
| ALB와 TLS/SSL 인증서로 HTTPS 암호화 통신 구현하기 (0) | 2026.05.15 |
| Terraform Remote Backend & State Locking (0) | 2026.05.08 |
| ISMS-P 인증 받는 클라우드 아키텍처 핵심 7가지 (0) | 2026.05.01 |
| ECS on EC2와 ECS on Fargate를 비용과 운영 관점에서 비교하기 (0) | 2026.04.15 |