Kubernetes 아웃바운드 트래픽 플로우

파드의 아웃바운드 트래픽 흐름

1. DNS 질의 (CoreDNS → 외부 DNS)

  • 파드 안 애플리케이션이 api.github.com 요청 → CoreDNS로 DNS 질의

  • CoreDNS가 /etc/resolv.conf에 지정된 상위 DNS(예: 구글 8.8.8.8, 클라우드 제공 DNS)로 포워딩 → IP 획득 후 파드에 응답

    → 이렇게 해서 파드가 목표 서버의 IP 주소를 알게 됩니다.


2. CNI 플러그인의 역할 (네트워크 레벨 L3 + NAT)

  • 파드 IP 특징: Pod는 클러스터 내부 전용의 사설 IP (예: 10.x, 192.168.x).

    외부 인터넷에서 이 IP를 알지도 못하고 도달할 수도 없습니다.

  • *CNI 플러그인(Calico, Flannel, Cilium 등)**은 파드 네트워크를 관리합니다.

    • 라우팅(L3): 파드 → 노드 인터페이스로 트래픽 전달
    • NAT(Masquerade): iptables(or nftables)를 이용해 소스 IP를 Pod IP → Node IP로 변환
      • 이 과정을 SNAT(Source NAT)라고 합니다.
      • 외부에서 볼 때는 “노드에서 요청이 들어온 것”처럼 보입니다.

3. 외부 통신 (노드 IP로 송신)

  • 변환된 패킷은 이제 노드의 공인 IP를 소스로 해서 인터넷을 나갑니다.
  • 외부 서버(api.github.com) 입장에서는 → 단일 노드 IP에서 요청이 온 것처럼 보임.
  • 응답이 돌아오면, 노드의 NAT 테이블이 이를 다시 찾아서 → 원래 파드로 전달합니다.

4. kube-proxy와의 관계

  • kube-proxy는 **클러스터 내부 서비스(ClusterIP, NodePort, LoadBalancer 등)**로 인바운드/내부 요청을 분배하는 역할입니다.
  • 즉, 파드 → 외부 방향의 아웃바운드 요청에는 직접 개입하지 않습니다.
  • 아웃바운드는 CNI 플러그인 + iptables NAT가 핵심입니다.

🔹 트래픽 요약 흐름

[Pod] --DNS Query--> [CoreDNS] --forward--> [외부 DNS]
[Pod] --패킷--> [CNI 네트워크] --L3 라우팅--> [Node]
[Node] --SNAT(Masquerade)--> [Node Public IP]
[Internet] <---> [외부 서버(api.github.com)]
[Node] --DNAT(reverse)--> [Pod]
+-----------------+        +-------------+        +------------------+        +-------------------+
|      Pod        |        |   CoreDNS   |        |    Node (NAT)    |        |   External Server |
| (10.244.x.x IP) |        | (ClusterIP) |        | (Public IP 보유) |        | api.github.com    |
+-----------------+        +-------------+        +------------------+        +-------------------+
        |                        |                         |                           |
        | 1. DNS Query           |                         |                           |
        |----------------------->|                         |                           |
        |                        | 2. Forward to 외부 DNS   |                           |
        |                        |------------------------>| (ex. 8.8.8.8)             |
        |                        |<------------------------|                           |
        |<-----------------------|                         |                           |
        |   (IP 주소 응답)         |                         |                           |
        |                        |                         |                           |
        | 3. 패킷 송신             |                         |                           |
        |----------------------->|   (CNI L3 라우팅)        |                            |
        |                        |------------------------>|                           |
        |                        |                         |                           |
        |                        |   4. SNAT (Pod→Node IP) |                           |
        |                        |------------------------>|-------------------------->|
        |                        |                         |     5. 요청 전달            |
        |                        |                         |                           |
        |                        |                         |<--------------------------|
        |                        |   6. DNAT (역변환)        |                           |
        |<-------------------------------------------------|                           |
        |          7. 응답 전달    |                         |                           |
        |                        |                         |                           |
┌─────────────┐
   │     Pod     │  (예: 10.244.0.5)
   │  App 프로세스 │
   └──────┬──────┘
          │
          │ 패킷 생성 (src=10.244.0.5, dst=api.github.com)
          ▼
   ┌─────────────┐
   │   CNI 계층   │  (가상 네트워크, veth pair, bridge 등)
   │   L3 라우팅   │
   └──────┬──────┘
          │
          │ 패킷 전달
          ▼
   ┌─────────────┐
   │    Node     │  (예: 192.168.0.10)
   │ iptables NAT│
   └──────┬──────┘
          │
          │ SNAT 수행
          │ src=192.168.0.10 (공인/사설 IP) 로 변경
          ▼
   ┌─────────────┐
   │   Internet  │
   │   외부 서버   │  (예: api.github.com / 140.82.x.x)
   └─────────────┘

🔹 추가 이해 포인트

  • Pod 간 통신(동일 클러스터 내부) → NAT 불필요 (CNI가 직접 라우팅)

  • Pod → 외부 인터넷 통신 → NAT 필요 (노드 공인 IP 사용)

  • 외부 → Pod 직접 접근 → 불가능 (ClusterIP는 내부 전용).

    이 경우 **Service(NodePort/LoadBalancer/Ingress)**가 필요합니다.


👉 질문 주신 정리 그대로 맞는데, 핵심 차이를 딱 정리하면:

  • CoreDNS는 “도메인 → IP” 변환
  • CNI + NAT는 “Pod 사설 IP → Node 공인 IP” 변환
  • kube-proxy는 “외부에서 들어오는 요청 → 내부 파드 분배”

혹시 원하시면 제가 이 과정을 패킷 이동 다이어그램으로 텍스트 그림(Pod → Node → NAT → 외부) 만들어드릴까요?

Comments

💬 Sign in with GitHub to leave a comment. Comments are public and stored in GitHub Discussions.