Theme:

서버가 여러 대인 환경에서 각 서버의 컨테이너들이 서로 통신해야 한다면, bridge 네트워크만으로는 한계가 있습니다. Docker는 이 문제를 어떻게 해결할까요?

overlay 네트워크

왜 필요한가

bridge 네트워크는 단일 호스트 내에서만 동작합니다. 서로 다른 서버에 있는 컨테이너가 통신하려면 overlay 네트워크가 필요합니다.

PLAINTEXT
┌── 호스트 A ──┐              ┌── 호스트 B ──┐
│   ┌─────┐   │   overlay    │   ┌─────┐   │
│   │ web │───┼──────────────┼───│ api │   │
│   └─────┘   │  (VXLAN)    │   └─────┘   │
│   10.0.0.2  │              │   10.0.0.3  │
└─────────────┘              └─────────────┘

VXLAN 터널링

overlay 네트워크는 VXLAN(Virtual Extensible LAN) 기술을 사용합니다. 원래의 L2 프레임을 UDP 패킷으로 감싸서(encapsulation) 호스트 간에 전달합니다.

PLAINTEXT
원본 패킷 구조:
┌────────────┬─────────────┬──────────┐
│ 외부 L2/L3 │ VXLAN 헤더  │ 원본 L2  │
│ (호스트간)  │ (VNI 포함)  │ (컨테이너)│
└────────────┴─────────────┴──────────┘
  • VNI(VXLAN Network Identifier): 가상 네트워크를 식별하는 24비트 ID
  • 기본 포트: UDP 4789
  • 최대 약 1,600만 개의 가상 네트워크 가능

Docker Swarm에서 overlay 생성

BASH
# Swarm 초기화 (매니저 노드)
docker swarm init --advertise-addr 192.168.1.10

# 워커 노드 추가
docker swarm join --token SWMTKN-1-xxx 192.168.1.10:2377

# overlay 네트워크 생성
docker network create \
    --driver overlay \
    --subnet 10.0.0.0/24 \
    my-overlay

# 서비스 배포 (overlay 네트워크 사용)
docker service create \
    --name web \
    --network my-overlay \
    --replicas 3 \
    nginx:1.25-alpine

독립 컨테이너에서 overlay 사용

Swarm 서비스가 아닌 일반 컨테이너에서도 overlay를 사용할 수 있습니다.

BASH
# attachable 옵션 필요
docker network create \
    --driver overlay \
    --attachable \
    my-attachable-overlay

# 일반 컨테이너에서 사용 가능
docker run -d --name standalone-app \
    --network my-attachable-overlay \
    myapp:latest

overlay의 데이터 플레인과 컨트롤 플레인

PLAINTEXT
┌── 컨트롤 플레인 ──┐
│ Gossip 프로토콜   │  ← 네트워크 상태, 노드 정보 교환
│ (TCP/UDP 7946)   │
└──────────────────┘

┌── 데이터 플레인 ──┐
│ VXLAN 터널       │  ← 실제 컨테이너 트래픽
│ (UDP 4789)       │
└──────────────────┘

방화벽에서 다음 포트를 열어야 합니다.

  • TCP/UDP 7946: 노드 간 통신
  • UDP 4789: VXLAN 데이터
  • TCP 2377: Swarm 관리 (매니저 노드만)

암호화

BASH
# overlay 네트워크의 데이터 암호화 활성화
docker network create \
    --driver overlay \
    --opt encrypted \
    secure-overlay

--opt encrypted를 사용하면 VXLAN 트래픽이 IPsec으로 암호화됩니다. 성능 오버헤드가 있으므로 필요한 경우에만 활성화합니다.

macvlan 네트워크

동작 원리

macvlan은 컨테이너에 호스트의 물리 네트워크와 같은 대역의 IP를 직접 할당합니다. 네트워크에서 보면 컨테이너가 독립적인 호스트처럼 보입니다.

PLAINTEXT
물리 네트워크 (192.168.1.0/24)
┌─────────────────────────────────────────┐
│                                         │
│  호스트: 192.168.1.10                    │
│  ┌──────────┐  ┌──────────┐             │
│  │ 컨테이너1 │  │ 컨테이너2 │             │
│  │ .1.101   │  │ .1.102   │             │
│  └──────────┘  └──────────┘             │
│                                         │
│  다른 장비: 192.168.1.50                 │
└─────────────────────────────────────────┘

macvlan 네트워크 생성

BASH
# macvlan 네트워크 생성
docker network create \
    --driver macvlan \
    --subnet 192.168.1.0/24 \
    --gateway 192.168.1.1 \
    -o parent=eth0 \
    my-macvlan

# 컨테이너 실행 (물리 네트워크의 IP 직접 할당)
docker run -d --name db \
    --network my-macvlan \
    --ip 192.168.1.101 \
    postgres:16-alpine

macvlan의 특징

  • NAT 없이 물리 네트워크에 직접 참여
  • 네트워크 성능이 bridge보다 좋음
  • 기존 네트워크 인프라와 직접 통합 가능
  • DHCP 서버에서 IP를 받을 수도 있음

주의사항: 호스트-컨테이너 통신

macvlan의 중요한 제한이 있습니다. 컨테이너와 호스트 간 직접 통신이 안 됩니다. 이것은 macvlan의 보안 특성입니다.

BASH
# 호스트에서 macvlan 컨테이너로 ping → 실패!
ping 192.168.1.101
# 응답 없음

# 같은 macvlan 네트워크의 다른 컨테이너 → 성공
docker exec container2 ping 192.168.1.101
# 응답 있음

# 다른 물리 장비에서 → 성공
# (192.168.1.50에서) ping 192.168.1.101
# 응답 있음

우회 방법:

BASH
# 호스트에 macvlan 서브 인터페이스 생성
ip link add mac0 link eth0 type macvlan mode bridge
ip addr add 192.168.1.200/32 dev mac0
ip link set mac0 up
ip route add 192.168.1.101/32 dev mac0

macvlan 모드

BASH
# bridge 모드 (기본값) — 같은 호스트의 macvlan 컨테이너끼리 통신 가능
docker network create --driver macvlan -o macvlan_mode=bridge ...

# 802.1q 트렁크 모드 — VLAN 태깅 지원
docker network create --driver macvlan \
    --subnet 192.168.10.0/24 \
    -o parent=eth0.10 \
    vlan10

ipvlan 네트워크

macvlan과 유사하지만, MAC 주소를 공유합니다.

BASH
# ipvlan L2 모드
docker network create \
    --driver ipvlan \
    --subnet 192.168.1.0/24 \
    -o parent=eth0 \
    my-ipvlan

# L3 모드 — 라우팅 기반
docker network create \
    --driver ipvlan \
    --subnet 10.10.0.0/24 \
    -o parent=eth0 \
    -o ipvlan_mode=l3 \
    my-ipvlan-l3

macvlan은 스위치의 MAC 주소 테이블에 부하를 주지만, ipvlan은 MAC 주소를 공유하므로 이 문제가 없습니다.

Docker 내장 DNS 서버

동작 구조

사용자 정의 네트워크에서 Docker는 각 컨테이너에 내장 DNS 서버(embedded DNS server)를 제공합니다.

PLAINTEXT
┌── 컨테이너 ──────────────────────┐
│                                  │
│  애플리케이션                      │
│      │ DNS 질의                   │
│      ↓                           │
│  /etc/resolv.conf               │
│  nameserver 127.0.0.11          │
│      │                           │
│      ↓                           │
│  Docker 내장 DNS (127.0.0.11)    │
│      │                           │
└──────┼───────────────────────────┘

       ├── 컨테이너 이름/별칭 → Docker가 직접 응답

       └── 외부 도메인 → 호스트 DNS로 전달

DNS 해석 규칙

BASH
# 1. 컨테이너 이름으로 해석
docker exec app nslookup web
# → 같은 네트워크의 'web' 컨테이너 IP 반환

# 2. 네트워크 별칭으로 해석
docker exec app nslookup database
# → --network-alias database로 등록된 컨테이너 IP 반환

# 3. 서비스 이름으로 해석 (Swarm)
docker exec app nslookup my-service
# → 서비스의 VIP 또는 태스크 IP 목록 반환

# 4. 외부 도메인은 호스트 DNS로 전달
docker exec app nslookup google.com
# → 호스트의 DNS 서버를 통해 해석

DNS 옵션 커스터마이징

BASH
# 외부 DNS 서버 직접 지정
docker run --dns 8.8.8.8 --dns 8.8.4.4 alpine nslookup google.com

# DNS 검색 도메인 설정
docker run --dns-search example.com alpine nslookup myhost
# myhost.example.com으로 해석 시도

# /etc/hosts 엔트리 추가
docker run --add-host myhost:10.0.0.100 alpine ping myhost

Docker Compose에서의 DNS

YAML
# compose.yaml
services:
  web:
    image: nginx
    networks:
      - frontend
      - backend

  api:
    image: myapi
    networks:
      - backend

  db:
    image: postgres:16
    networks:
      - backend

networks:
  frontend:
  backend:

같은 네트워크에 속한 서비스는 서비스 이름으로 자동 해석됩니다.

  • web에서 api로: api → 해석 가능 (같은 backend 네트워크)
  • web에서 db로: db → 해석 가능 (같은 backend 네트워크)
  • api에서 web으로: web → 해석 가능 (같은 backend 네트워크)

네트워크 드라이버 비교

드라이버범위격리성능사용 사례
bridge단일 호스트좋음보통대부분의 경우
host단일 호스트없음최고고성능 요구
none단일 호스트완전N/A보안/배치
overlay멀티 호스트좋음보통Swarm/분산 환경
macvlan단일 호스트보통좋음기존 네트워크 통합
ipvlan단일 호스트보통좋음MAC 수 제한 환경

네트워크 트러블슈팅

BASH
# 네트워크 상세 정보 확인
docker network inspect my-network

# 컨테이너의 네트워크 설정 확인
docker inspect --format='{{json .NetworkSettings.Networks}}' mycontainer | jq

# 컨테이너 내부에서 네트워크 진단
docker exec mycontainer ip addr
docker exec mycontainer ip route
docker exec mycontainer cat /etc/resolv.conf

# DNS 해석 테스트
docker exec mycontainer nslookup target-service

# 연결 테스트
docker exec mycontainer wget -qO- http://target-service:8080/health

# 호스트에서 VXLAN 인터페이스 확인 (overlay)
ip -d link show type vxlan

정리

  • overlay 네트워크는 VXLAN 터널링으로 멀티호스트 컨테이너 통신을 구현하며, Docker Swarm이나 외부 KV 스토어가 필요합니다.
  • macvlan은 컨테이너에 물리 네트워크의 IP를 직접 할당하여, 기존 네트워크 인프라와 자연스럽게 통합됩니다.
  • Docker의 내장 DNS 서버(127.0.0.11)가 컨테이너 이름과 별칭을 자동으로 해석하여 서비스 디스커버리 역할을 합니다.
  • 용도에 맞는 네트워크 드라이버를 선택하는 것이 중요합니다. 대부분의 경우 사용자 정의 bridge로 충분하고, 멀티호스트가 필요하면 overlay를 사용합니다.
댓글 로딩 중...