컨테이너 네트워크 구조 쉽게 이해하기: Docker와 Kubernetes 통신 흐름

컨테이너 네트워크 구조를 이해하면 “왜 내 컨테이너는 실행 중인데 외부에서 접속되지 않을까?” 같은 문제를 훨씬 빨리 좁힐 수 있습니다. 핵심은 컨테이너가 그냥 호스트의 포트를 함께 쓰는 작은 프로세스가 아니라, 별도의 네트워크 공간에서 인터페이스와 IP, 라우팅, DNS 설정을 가진 것처럼 동작한다는 점입니다.

아파트 단지에 비유하면 컨테이너는 각 세대, 브리지 네트워크는 단지 내부 도로, NAT와 포트 매핑은 정문과 경비실, Kubernetes Service는 바뀌는 세대 위치를 대신 안내하는 관리사무소에 가깝습니다. 이 비유를 실제 기술 용어로 바꾸면 흐름은 대체로 “컨테이너 네트워크 네임스페이스 → 가상 인터페이스 → 브리지 또는 CNI 네트워크 → 라우팅/NAT → 외부 네트워크”입니다.

컨테이너 네트워크 구조와 브리지 NAT 통신 흐름

컨테이너는 어디에 연결되어 통신할까?

컨테이너는 일반적으로 독립된 네트워크 네임스페이스 안에서 실행됩니다. 그래서 컨테이너 안에서 ip addrroute를 보면 eth0, IP 주소, 기본 게이트웨이, 라우팅 테이블이 보입니다. 하지만 이 eth0은 물리 랜카드가 아니라 호스트 쪽의 가상 인터페이스와 한 쌍으로 연결된 veth pair인 경우가 많습니다.

같은 호스트의 컨테이너끼리 통신할 때는 컨테이너의 eth0에서 나온 패킷이 veth를 거쳐 호스트의 Linux bridge 또는 Docker bridge로 들어갑니다. 같은 브리지에 붙어 있는 다른 컨테이너라면 내부 스위치처럼 전달되고, 외부 네트워크로 나가야 한다면 호스트의 라우팅과 NAT 규칙을 통과합니다.

컨테이너 IP와 호스트 IP가 다르게 보이는 이유

컨테이너 IP는 컨테이너 네트워크 안에서 쓰이는 주소이고, 호스트 IP는 물리 또는 가상 서버가 외부 네트워크에서 사용하는 주소입니다. Docker bridge 환경에서는 컨테이너가 보통 172.x 또는 10.x 대역의 사설 IP를 받고, 외부 클라이언트는 이 IP를 직접 모르는 경우가 많습니다. 외부에서 접근하려면 호스트의 특정 포트를 컨테이너 포트로 연결하는 port publishing이 필요합니다.

반대로 컨테이너에서 인터넷으로 나갈 때는 호스트가 출발지 주소를 호스트 IP처럼 바꿔주는 masquerading을 수행할 수 있습니다. 그래서 컨테이너 내부에서는 자기 IP로 나간다고 생각하지만, 외부 서버 입장에서는 호스트에서 온 요청처럼 보일 수 있습니다.

Docker 네트워크 구조에서 자주 만나는 선택지

Docker는 bridge, host, overlay, macvlan, ipvlan, none 같은 여러 네트워크 드라이버를 제공합니다. 각 드라이버의 목적은 다르며, 공식 분류는 Docker 네트워크 드라이버 문서에서 확인할 수 있습니다. 실무에서는 “단일 호스트인가, 여러 호스트인가, 격리가 필요한가, 외부 네트워크에 직접 붙여야 하는가”를 기준으로 고르면 이해가 쉽습니다.

bridge 네트워크는 단일 호스트의 기본 구조다

Docker bridge는 한 Docker 호스트 안에서 컨테이너들을 소프트웨어 브리지에 연결합니다. 같은 bridge에 연결된 컨테이너는 서로 통신할 수 있고, 외부로 나갈 때는 NAT를 사용할 수 있습니다. 기본 bridge도 동작은 하지만, 실무에서는 user-defined bridge를 권장하는 경우가 많습니다.

user-defined bridge는 컨테이너 이름 기반 DNS 해석이 편하고, 애플리케이션 묶음 단위로 네트워크를 나누기 좋으며, 네트워크별 설정을 관리하기 쉽습니다. 예를 들어 web, app, db 컨테이너를 같은 사용자 정의 브리지에 두면 IP를 외우지 않고 서비스 이름으로 접근하는 구성이 가능해집니다.

Docker bridge 네트워크에서 컨테이너끼리 통신하는 구조

host, overlay, macvlan과 ipvlan은 목적이 다르다

host 네트워크는 컨테이너와 호스트 사이의 네트워크 격리를 줄이고 호스트 네트워크 스택을 직접 사용하게 합니다. 성능상 이점이 있을 수 있지만 포트 충돌, 보안 격리 약화, 운영 실수 가능성이 커지므로 “빠르니까 항상 좋다”라고 볼 수는 없습니다.

overlay 네트워크는 여러 Docker daemon host에 걸쳐 컨테이너 간 통신이 필요할 때 사용됩니다. 일반적으로 캡슐화가 들어가므로 환경에 따라 오버헤드가 생길 수 있고, 암호화 옵션을 쓰면 보안에는 도움이 되지만 성능 비용을 테스트해야 합니다. macvlan과 ipvlan은 컨테이너를 물리 네트워크에 더 직접적으로 붙여야 하거나 기존 네트워크 장비와 L2/L3 수준 통합이 필요할 때 검토합니다.

컨테이너 네트워크 구조별 특징 비교

구조 적용 범위 주요 장점 주의할 점 적합한 상황
Docker bridge 단일 호스트 구성이 쉽고 기본값으로 이해하기 좋음 외부 접근에는 포트 매핑이 필요할 수 있음 개발 환경, 단일 서버 앱
user-defined bridge 단일 호스트 이름 기반 DNS, 네트워크 격리, 관리 편의성 호스트를 넘어서는 통신에는 별도 구조 필요 Docker Compose 기반 서비스 묶음
Docker host 단일 호스트 네트워크 계층이 단순하고 포트 매핑이 덜 필요함 격리 약화와 포트 충돌 위험 특정 고성능 네트워크 워크로드
Docker overlay 멀티 호스트 여러 호스트의 컨테이너를 하나의 논리망으로 연결 캡슐화, MTU, 암호화 성능 확인 필요 Swarm 또는 멀티 호스트 Docker 구성
macvlan/ipvlan 호스트와 물리망 연동 컨테이너가 외부 네트워크의 일원처럼 동작 가능 네트워크 장비, IP 계획, 보안 정책과 맞춰야 함 레거시 시스템 연동, 고정 IP 요구
Kubernetes CNI Pod network 클러스터 Pod 간 통신 모델을 플러그인으로 구현 CNI별 기능과 정책 지원이 다름 Kubernetes 운영 환경
Kubernetes Service 클러스터 서비스 추상화 변하는 Pod 뒤에 안정적인 접근점 제공 bridge가 아니라 로드밸런싱 추상화임 동적 백엔드 Pod 연결

NAT와 포트 매핑은 어느 지점에서 등장할까?

컨테이너 외부 접속 문제는 대개 방향을 나눠 보면 단순해집니다. 컨테이너가 외부 API, 패키지 저장소, 데이터베이스로 나가는 방향이라면 라우팅, DNS, masquerading, 방화벽을 봐야 합니다. 외부 사용자가 컨테이너 안의 Nginx나 API 서버로 들어오는 방향이라면 published port, 리버스 프록시, 로드밸런서, 보안 그룹을 봐야 합니다.

예를 들어 컨테이너 내부 Nginx가 80번 포트에서 듣고 있어도, 호스트에서 -p 8080:80처럼 포트를 publish하지 않았다면 외부 사용자는 호스트의 8080으로 접속할 수 없습니다. 컨테이너 IP로 직접 접근하는 방식은 같은 브리지 내부나 라우팅이 구성된 네트워크에서는 가능할 수 있지만, IP가 재생성 때 바뀌고 외부 라우터가 그 대역을 모를 수 있어 운영 접근점으로는 취약합니다.

Kubernetes는 컨테이너보다 Pod를 네트워크 단위로 본다

Docker 단일 호스트를 이해한 뒤 Kubernetes 네트워킹을 보면 가장 중요한 차이는 네트워크 단위입니다. Kubernetes에서는 개별 컨테이너가 아니라 Pod가 기본 단위입니다. 같은 Pod 안의 여러 컨테이너는 네트워크 네임스페이스를 공유하므로 서로 localhost로 통신할 수 있습니다. 사이드카 프록시와 애플리케이션 컨테이너가 같은 Pod에서 로컬 포트로 대화하는 구조가 대표적입니다.

Kubernetes 네트워크 모델은 Pod마다 고유한 클러스터 IP를 부여하고, Pod 간 직접 통신이 가능하다는 전제를 둡니다. 이 모델의 전체 개념은 Kubernetes Services, Load Balancing, and Networking 문서에 정리되어 있습니다. 다만 “Kubernetes는 NAT를 전혀 쓰지 않는다”는 뜻은 아닙니다. Pod 간 기본 모델은 직접 통신을 지향하지만 Service, NodePort, 외부 통신, CNI 구현에 따라 NAT나 프록시 동작이 포함될 수 있습니다.

Kubernetes Service가 여러 Pod로 트래픽을 전달하는 구조

Service, DNS, kube-proxy가 안정적인 연결을 만든다

Pod IP는 안정적인 주소가 아닙니다. 배포가 갱신되거나 노드 장애가 발생하거나 오토스케일링이 일어나면 Pod가 삭제되고 새로 생성되며 IP도 바뀔 수 있습니다. 그래서 Kubernetes는 Service를 통해 변하는 Pod 집합 앞에 안정적인 이름과 가상 IP를 제공합니다.

Service는 라벨 셀렉터로 백엔드 Pod를 찾고, 현재 연결 가능한 엔드포인트 정보는 EndpointSlice를 통해 관리됩니다. 클라이언트는 개별 Pod IP 대신 Service DNS 이름이나 ClusterIP로 접근합니다. kube-proxy는 각 노드에서 iptables, IPVS, nftables 같은 데이터 플레인을 구성해 Service IP와 포트로 들어온 트래픽을 실제 endpoint로 전달합니다.

외부 트래픽을 클러스터 안으로 들여보내는 계층은 또 다릅니다. ClusterIP는 주로 클러스터 내부용이고, NodePort나 LoadBalancer는 외부 연결을 열 수 있습니다. HTTP/HTTPS 라우팅, 호스트명 기반 분기, TLS 종료 같은 기능이 필요하면 Ingress나 Gateway API를 검토합니다. 즉 Service는 “Pod 집합으로 가는 안정적인 내부 접근점”, Ingress와 Gateway는 “외부 진입점과 L7 라우팅”에 가깝습니다.

CNI는 Kubernetes Pod 네트워크를 실제로 구현한다

CNI는 Container Network Interface의 약자로, 컨테이너 런타임과 네트워크 플러그인 사이의 표준 인터페이스입니다. Kubernetes가 “Pod마다 IP가 있어야 한다”는 모델을 제시한다면, CNI 플러그인은 그 모델을 실제 노드의 인터페이스, 라우팅, 터널, 정책으로 구현합니다.

CNI가 담당하는 일은 플러그인에 따라 다르지만 일반적으로 Pod에 네트워크 인터페이스를 붙이고, IP를 할당하고, 노드 간 라우팅 또는 오버레이를 구성하며, 경우에 따라 NetworkPolicy를 적용합니다. 단, 모든 CNI가 같은 방식으로 동작하거나 모든 기능을 지원하는 것은 아닙니다. 특히 NetworkPolicy는 Kubernetes API로 선언하더라도 실제 차단과 허용은 플러그인의 구현 여부에 좌우됩니다.

CNI 선택은 성능, 보안, 운영 난이도에 영향을 줍니다. 작은 테스트 클러스터라면 단순성이 중요하고, 대규모 운영 환경이라면 노드 간 라우팅 방식, MTU, eBPF 활용 여부, 정책 가시성, 클라우드 네트워크 통합 방식을 함께 봐야 합니다. 애플리케이션 코드는 보통 바꾸지 않지만, 네트워크 정책이나 외부 노출 방식은 재검토가 필요할 수 있습니다.

설계 전에 확인하면 장애를 줄이는 질문들

  • 단일 호스트인가, 멀티 호스트인가? 단일 서버의 Docker Compose라면 user-defined bridge가 우선 후보입니다. 여러 노드에 걸친 운영이라면 overlay 또는 Kubernetes CNI 기반 Pod 네트워크를 봐야 합니다.
  • 외부에 공개해야 하는 포트는 무엇인가? 모든 컨테이너 포트를 publish하지 말고, 사용자 요청을 받는 진입점만 열어야 합니다.
  • 내부 통신과 외부 통신을 분리했는가? web, app, db를 같은 네트워크에 무조건 넣기보다 필요한 경로만 허용하는 구조가 안전합니다.
  • DNS 이름으로 접근하고 있는가? 컨테이너 IP와 Pod IP는 바뀔 수 있으므로 서비스 이름, Docker 네트워크 DNS, Kubernetes Service DNS를 활용하는 편이 운영에 유리합니다.
  • MTU와 방화벽을 확인했는가? overlay, VPN, 클라우드 네트워크가 겹치면 MTU 문제로 일부 요청만 실패할 수 있습니다.
  • NAT 병목과 관측 지점은 있는가? 대량 연결이 NAT 테이블, conntrack, 로드밸런서 제한에 걸릴 수 있으므로 모니터링 기준을 잡아야 합니다.

자주 헷갈리는 질문들

컨테이너끼리 통신할 때 반드시 포트 매핑이 필요한가?

같은 Docker user-defined bridge에 있는 컨테이너끼리는 보통 포트 매핑 없이 컨테이너 포트로 직접 통신할 수 있습니다. 포트 매핑은 주로 호스트 바깥에서 컨테이너로 들어올 때 필요합니다.

Docker bridge와 Kubernetes Service는 같은 개념인가?

아닙니다. bridge는 컨테이너를 연결하는 네트워크 구조이고, Kubernetes Service는 변하는 Pod 집합에 안정적인 접근점을 제공하는 추상화입니다. 둘 다 통신에 관여하지만 해결하는 문제가 다릅니다.

CNI 플러그인을 바꾸면 애플리케이션 코드도 바꿔야 하나?

대부분의 경우 애플리케이션 코드는 그대로 둡니다. 하지만 NetworkPolicy, Ingress, LoadBalancer, IP 대역, MTU, 관측 도구가 달라질 수 있어 운영 설정은 검증해야 합니다.

overlay 네트워크는 항상 느린가?

항상 그렇지는 않습니다. 캡슐화와 암호화가 오버헤드를 만들 수 있지만 실제 성능은 NIC, 커널, CNI 또는 Docker 구성, MTU, 트래픽 패턴에 따라 달라집니다. 운영 전 부하 테스트로 확인하는 것이 안전합니다.

컨테이너 네트워크는 계층별로 나누어 봐야 쉽다

컨테이너 네트워크 구조는 한 번에 외우기보다 계층별로 보면 명확해집니다. 단일 호스트에서는 컨테이너 네임스페이스, veth, bridge, NAT, port publishing을 먼저 이해하면 됩니다. Docker Compose 중심이라면 user-defined bridge와 이름 기반 DNS를 기본으로 잡는 것이 실용적입니다.

멀티 호스트나 Kubernetes 환경에서는 Pod 네트워크, CNI, Service, kube-proxy, Ingress 또는 Gateway를 분리해서 봐야 합니다. Pod IP는 실행 단위의 주소이고, Service는 안정적인 접근점이며, CNI는 그 통신 모델을 실제 네트워크에 구현하는 계층입니다. 이 구분만 잡아도 IP, 포트, DNS, 라우팅, 정책 중 어디에서 문제가 생겼는지 훨씬 빠르게 추적할 수 있습니다.

Scroll to Top