Network - 정리(1)

2026. 1. 5. 22:11·CKA

스위치·라우팅·게이트웨이·IP 포워딩 → DNS(/etc/hosts, resolv.conf, CoreDNS) → 네트워크 네임스페이스 → Docker 네트워킹 → CNI → 쿠버네티스 노드 네트워크 점검 포인트


0. 왜 이걸 알아야 하나?

쿠버네티스 네트워킹은 결국 리눅스에서 이미 존재하는 기능(인터페이스, 라우팅 테이블, ARP, iptables, 네임스페이스, 브리지)을 조합한 것입니다.

  • Pod = (리눅스 프로세스 + 네트워크 네임스페이스)
  • Pod 네트워크 연결 = veth + 브리지 + 라우팅(+ 오버레이면 터널/VXLAN)
  • 외부 통신/외부에서 접근 = NAT(마스커레이드) + 포트포워딩(DNAT)
  • 여러 네트워크 솔루션을 표준화한 인터페이스 = CNI

아래는 “쿠버네티스를 이해하기 위한 리눅스 네트워킹 기초”부터 이어지는 내용을 한 편의 글로 엮은 정리입니다.


1. 리눅스 네트워킹 기초: 스위치·라우팅·게이트웨이·IP 포워딩

1.1 인터페이스 확인: ip link, ip addr

리눅스에서 네트워크 “포트”는 인터페이스로 나타납니다.

ip link
ip addr
  • lo: loopback. 자기 자신(127.0.0.1)로 돌려보내는 내부 인터페이스
  • eth0: (물리/가상) NIC. 외부 네트워크(LAN/VPC 등)로 나가는 실제 통로

1.2 같은 네트워크 안의 통신: 스위치(= L2)

같은 IP 대역(예: 192.168.1.0/24)에 있는 두 호스트는 스위치를 통해 통신합니다.

  • 같은 서브넷이면 “저 IP는 같은 네트워크 안이네?” → ARP로 MAC을 찾고 → L2로 전달

1.3 다른 네트워크로 가려면: 라우터 + 라우팅 테이블

다른 대역(예: 192.168.2.0/24)로 가려면 라우터(= 게이트웨이 역할) 가 필요합니다.

라우팅 테이블 확인:

ip route
# 또는
route -n

라우팅 테이블은 “이 목적지(대역/호스트)로 갈 땐 어느 게이트웨이/인터페이스로 보낼까?”를 결정합니다.

  • 게이트웨이(door)는 “내 네트워크 밖으로 나가는 출입구”
  • 라우터는 그 출입구 역할을 수행하는 장치/호스트입니다
    → 실무 표현으로 “라우터가 게이트웨이가 된다”가 대부분의 경우 맞습니다.

기본 게이트웨이(디폴트 라우트) 예시:

ip route add default via 192.168.1.1 dev eth0

1.4 리눅스 호스트를 라우터로 만들기: IP 포워딩

두 NIC(eth0, eth1)를 가진 호스트 B가 네트워크 A와 네트워크 C 사이를 중계하려면 “패킷 포워딩”이 필요합니다.

현재 포워딩 여부:

cat /proc/sys/net/ipv4/ip_forward

켜기(즉시 반영):

sudo sysctl -w net.ipv4.ip_forward=1

영구 반영(재부팅 후 유지):

sudo vi /etc/sysctl.conf
# net.ipv4.ip_forward=1
sudo sysctl -p

쿠버네티스 노드가 “Pod 네트워크 ↔ 노드 네트워크 ↔ 외부”를 중계하는 구조라면, 이 포워딩 개념이 계속 등장합니다.


2. Linux DNS 입문: /etc/hosts, resolv.conf, nsswitch.conf, 검색 도메인

2.1 /etc/hosts: 가장 로컬한 이름 해석

호스트 A에서 db라는 이름을 192.168.1.11로 해석하고 싶다면:

sudo vi /etc/hosts
# 192.168.1.11  db
  • /etc/hosts는 로컬 머신만의 “정적 이름 해석” 입니다.
  • 여기에 적힌 내용은 그 머신에서 “진실”로 취급됩니다(실제 호스트네임과 달라도 상관 없음).

2.2 /etc/resolv.conf: DNS 서버(네임서버) 지정 + search 도메인

DNS 서버를 쓰려면:

cat /etc/resolv.conf

예:

nameserver 192.168.1.100
search mycompany.com
  • nameserver: “이 DNS 서버에게 물어봐”
  • search: “web만 치면 web.mycompany.com도 함께 시도해봐”

즉, 내부망에서 web 같은 짧은 이름을 쓸 수 있게 만드는 장치입니다.

2.3 nsswitch.conf: /etc/hosts vs DNS 우선순위

어느 순서로 이름을 찾을지 정의:

cat /etc/nsswitch.conf | grep hosts
# hosts: files dns
  • files = /etc/hosts
  • dns = DNS 서버 질의

기본은 보통 files → dns 순서입니다.

2.4 DNS 진단 도구: nslookup, dig

  • nslookup, dig는 DNS 서버에 직접 질의하는 도구입니다.
  • /etc/hosts 엔트리는 고려하지 않을 수 있습니다(실습에서 많이 헷갈리는 포인트).
nslookup web
dig web

3. (Prerequisite) CoreDNS로 DNS 서버 직접 띄워보기

쿠버네티스에서 CoreDNS는 클러스터 DNS의 핵심 구성요소입니다. 그 전에 “CoreDNS가 그냥 DNS 서버 프로그램”이라는 감각을 잡아두면 이후가 쉬워집니다.

3.1 CoreDNS 바이너리 설치/실행(전통적인 방식)

curl -LO https://github.com/coredns/coredns/releases/download/v1.12.4/coredns_1.12.4_linux_amd64.tgz
tar -zxf coredns_1.12.4_linux_amd64.tgz
./coredns
  • 기본적으로 DNS 서버 포트 53에서 리슨합니다.

3.2 /etc/hosts를 CoreDNS가 읽게 만들기: Corefile

CoreDNS는 Corefile로 설정을 읽습니다. 아래 예시는:

  1. DNS 엔트리는 DNS 서버 자신의 /etc/hosts에 넣고
  2. CoreDNS가 그 파일을 읽어 질의에 응답하게 하는 설정입니다.
.:53 {
    hosts /etc/hosts {
        reload 1m
        fallthrough
    }

    forward . /etc/resolv.conf {
       max_concurrent 1000
    }

    cache 30
    log
    errors
}
  • hosts /etc/hosts: 호스트 파일 기반 응답
  • reload 1m: hosts 파일 변경 감지
  • fallthrough: hosts에서 못 찾으면 다음 플러그인으로 넘어감
  • forward . /etc/resolv.conf: 나머지는 상위 DNS로 포워딩(인터넷 도메인 등)
  • cache/log/errors: 캐시/로그/에러

쿠버네티스에서는 이 CoreDNS가 “kubernetes 플러그인”을 통해 Service/Pod 이름을 해석합니다. (이 글은 DNS 서버의 기본 구조 감각을 위한 파트)


4. Linux Network Namespace: 컨테이너 네트워크 격리의 핵심

컨테이너는 “프로세스 격리”를 네임스페이스로 합니다. 네트워크도 마찬가지로 네트워크 네임스페이스를 사용합니다.

4.1 네임스페이스 만들기/확인

ip netns add red
ip netns add blue
ip netns

네임스페이스 안에서 명령 실행:

ip netns exec red ip link
# 또는 축약
ip -n red link

처음엔 lo만 보입니다. 호스트의 eth0는 보이지 않습니다(격리 성공).

4.2 veth: 네임스페이스를 잇는 “가상 케이블”

두 네임스페이스를 직접 연결:

ip link add veth-red type veth peer name veth-blue
ip link set veth-red netns red
ip link set veth-blue netns blue

IP 부여(여기서 /24가 중요했던 이유):

ip -n red addr add 192.168.5.1/24 dev veth-red
ip -n blue addr add 192.168.5.2/24 dev veth-blue
ip -n red link set veth-red up
ip -n blue link set veth-blue up

왜 /32가 아니라 /24였나?

  • /24는 “같은 L2 네트워크(192.168.5.0/24)에 이웃이 있다”는 의미
    → 이웃 IP(192.168.5.2)에 대해 ARP를 수행하고 직접 통신 가능
  • /32는 “내 IP 한 개만 존재(호스트 라우트)” 의미라
    → 같은 네트워크 개념이 약해지고, 보통은 게이트웨이/라우팅 기반 설계에서 사용됩니다.

4.3 ARP 테이블 vs 라우팅 테이블

  • ARP 테이블: “이 IP는 어떤 MAC이지?” (L2 주소 해석)
  • 라우팅 테이블: “이 목적지 IP(대역)는 어디로 보내지?” (L3 경로 결정)

확인:

ip neigh        # ARP/neighbor table
ip route        # routing table

veth로 연결하면 라우팅이 되는가?

  • veth 자체는 “케이블”일 뿐이고, 실제로는
    1. 같은 서브넷 설정(/24 등) → ARP로 이웃 MAC을 알아내고
    2. L2로 프레임을 보내서 통신이 됩니다.
  • 다른 네트워크로 가려면 라우팅 테이블/게이트웨이가 필요합니다.

4.4 bridge: 여러 네임스페이스를 한 네트워크에 묶기

브리지 생성:

ip link add vnet0 type bridge
ip link set vnet0 up

veth 한쪽을 브리지에 붙이기(질문에 있던 명령):

ip link set veth-blue-br master vnet0

이 의미는:

  • veth-blue-br 인터페이스를 브리지 vnet0의 포트로 등록한다
  • 즉, L2 스위치에 랜선을 꽂는 것과 같습니다.

5. 네임스페이스/브리지에서 외부로: Routing + NAT + Port Forward

5.1 “왜 포워딩/NAT가 필요하지?” 핵심 논리

네임스페이스(예: 192.168.15.0/24)는 호스트 내부의 사설망이고, 외부 LAN(예: 192.168.1.0/24)은 그 사설망을 모릅니다.

  • 네임스페이스 → 외부로 나갈 때:
    외부는 192.168.15.x를 모름 → 응답이 돌아오지 않음
    → NAT(마스커레이드) 로 “호스트 IP로 나간 것처럼” 바꿔줘야 함

또한 호스트가 네임스페이스 트래픽을 중계하려면:

  • IP 포워딩이 켜져 있어야 합니다.

5.2 NAT 마스커레이드 예시

sudo iptables -t nat -A POSTROUTING -s 192.168.15.0/24 -o eth0 -j MASQUERADE
  • POSTROUTING: 밖으로 나가기 직전
  • -s 192.168.15.0/24: 소스가 내부 사설망이면
  • -o eth0: eth0로 나갈 때
  • MASQUERADE: 소스 IP를 호스트 IP로 바꿔서 나가게 함

5.3 외부 → 내부 서비스 접근: 포트포워딩(DNAT)

예: 외부에서 호스트 80으로 들어온 걸 네임스페이스(blue) 80으로 전달

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.15.2:80

6. Docker 네트워킹: none / host / bridge, 그리고 docker0·iptables 포트포워딩

Docker는 위에서 우리가 손으로 만든 것과 거의 동일하게 동작합니다.

6.1 Docker 네트워크 옵션 3가지

  1. none
  • 네트워크에 붙지 않음. 외부도 못 나가고 컨테이너끼리도 통신 어려움
  1. host
  • 컨테이너가 호스트 네트워크를 그대로 사용
  • 포트 매핑 없이도 호스트의 80이 곧 컨테이너 80
  • 단점: 같은 포트를 여러 컨테이너가 동시에 못 씀(충돌)
  1. bridge (기본)
  • 내부 사설 네트워크 생성(기본 docker0, 대역 보통 172.17.0.0/16 계열)
  • 컨테이너마다 별도 netns + veth로 docker0에 붙음
  • 외부 접근은 포트 퍼블리싱(-p)으로 열어줘야 함

호스트에서 확인:

docker network ls
ip link show docker0
ip addr show docker0

6.2 “그냥 80으로 띄운 것” vs “8080:80으로 띄운 것” 차이

여기서 말하는 두 케이스:

  • 케이스 A: docker run nginx (포트 퍼블리싱 없음)
  • 케이스 B: docker run -p 8080:80 nginx (호스트 8080 → 컨테이너 80)

케이스 A: 포트 퍼블리싱이 없으면 외부에서 컨테이너 80으로 못 들어온다

  • 컨테이너는 자신의 netns 내부에서 80 리슨
  • 호스트에는 “외부 트래픽을 그 컨테이너로 보내는 규칙”이 없음
  • 따라서 외부에서 host:80으로 들어오면:
    • 호스트에 80 리슨 프로세스가 없으면 연결 실패
    • 호스트에 다른 80 프로세스가 있으면 그 프로세스로 감

즉, 컨테이너가 80을 열었다 ≠ 호스트가 80을 외부에 제공한다

케이스 B: -p 8080:80은 호스트가 DNAT 룰을 만들어서 연결해준다

  • 호스트 8080으로 들어오는 트래픽을
  • iptables DNAT로 컨테이너 IP:80으로 바꿈
  • 그래서 외부에서 host:8080으로 접근 가능

Docker는 내부적으로 아래와 유사한 룰을 만듭니다(개념):

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.3:80

6.3 시퀀스 다이어그램으로 이해하기

A) 포트 퍼블리싱 없이(docker run nginx) 외부에서 접근 시도

[Client] ---TCP:80---> [Host eth0]
                         |
                         | (호스트에 80 리슨 프로세스 없음)
                         v
                      (Connection Refused / Timeout)

B) -p 8080:80으로 퍼블리싱한 경우

[Client] ---TCP:8080---> [Host eth0:8080]
                           |
                           | iptables DNAT (8080 -> 172.17.0.3:80)
                           v
                        [docker0/bridge]
                           |
                           | veth pair
                           v
                      [Container netns:80 nginx]

핵심: 외부에서 들어오는 트래픽을 컨테이너로 “맵핑(포워딩)”해주는 규칙이 있어야 한다 입니다.


7. CNI(Container Network Interface): 네트워크 세팅을 표준화해서 플러그인으로 분리한다

7.1 CNI가 해결하는 문제

여러 런타임/오케스트레이터가 “컨테이너를 네트워크에 붙이는 로직”을 매번 구현하지 않도록:

  • 런타임이 플러그인을 어떻게 호출할지
  • 플러그인이 어떤 입력/출력을 가져야 할지
    를 표준화한 것이 CNI입니다.

7.2 런타임 vs 플러그인 책임

  • 런타임: netns 생성, ADD/DEL 호출
  • 플러그인: veth/브리지 연결, IP 할당(IPAM), 라우팅 설정 등 수행

CNI 플러그인 예:

  • bridge, vlan, macvlan
  • IPAM: host-local, dhcp
  • 서드파티: flannel, calico, cilium, weave 등

7.3 “Docker는 CNM인데 CNI가 어떻게 동작하나?”

핵심은 이겁니다.

  • CNI는 “도커 네트워크(CNM)를 확장하는 기능”이 아니라
  • 리눅스 netns에 네트워크를 세팅하는 방식입니다.

쿠버네티스가 Docker를 런타임으로 쓰던 시절(역사적 흐름)에는:

  1. Docker로 컨테이너(netns)를 만들고(네트워크는 최소/없음)
  2. 그 netns에 대해 kubelet이 CNI 플러그인을 호출해
  3. veth/브리지/IP/라우팅을 구성

즉, Docker가 CNM을 쓰느냐와 별개로, Kubernetes는 CNI로 “netns를 직접 세팅”할 수 있었습니다.


8. 쿠버네티스 노드 네트워크 점검 포인트(필수 포트 포함)

쿠버네티스 클러스터는 컨트롤플레인/워커 모두 “노드로서의 네트워크”가 정상이어야 합니다.

8.1 노드 기본 조건

  • 각 노드는 최소 1개 인터페이스 + IP 필요
  • hostname 유니크
  • MAC 유니크(특히 VM 클론 시 주의)

확인:

ip link
ip addr
hostname

8.2 자주 언급되는 포트(대표)

  • API Server: 6443
  • kubelet: 10250
  • scheduler: 10259
  • controller-manager: 10257
  • NodePort range: 30000-32767
  • etcd: 2379 (client), 2380 (peer)

포트 리슨 확인(둘 중 하나):

sudo ss -lntp
sudo netstat -lntp

netstat -anp | grep etcd에서 옵션 의미:

  • -a: 전체 소켓(리스닝+연결)
  • -n: 숫자(IP/포트) 그대로
  • -p: PID/프로세스 표시(보통 sudo 필요)

9. 라우팅 테이블 읽는 법: ip route 실전 예시 해석

예시:

ip route
default via 169.254.1.1 dev eth0 
169.254.1.1 dev eth0 scope link 
172.17.0.0/24 dev cni0 proto kernel scope link src 172.17.0.1 
172.17.1.0/24 via 172.17.1.0 dev flannel.1 onlink
  • dev = device(인터페이스)
    → 이 경로로 나가는 패킷이 “어느 인터페이스로 나가야 하는지”를 뜻함

라인별 의미:

  1. default via ... dev eth0
    • 기본 경로(모르는 목적지는 전부) → eth0로 게이트웨이에 전달
  2. 169.254.1.1 dev eth0 scope link
    • 게이트웨이 IP 자체는 eth0 링크에서 직접 도달 가능
  3. 172.17.0.0/24 dev cni0 ... src 172.17.0.1
    • 이 노드의 로컬 Pod 네트워크(또는 브리지 대역)가 cni0에 직접 연결
    • cni0의 주소가 172.17.0.1인 형태
  4. 172.17.1.0/24 ... dev flannel.1 onlink
    • 다른 노드(다른 Pod CIDR)로 가는 트래픽을 flannel 오버레이 인터페이스로 보냄
    • onlink는 “직접 연결처럼 취급하고 보내라”는 강제 플래그로 이해하면 됨

10. 덤: /32 IP가 보이는 이유(쿠버네티스/컨테이너에서 흔함)

컨테이너/파드 내부에서 ip addr를 보면 이런 형태가 자주 보입니다.

inet 192.168.227.158/32 scope global eth0
  • /32는 “내 IP 한 개만”을 의미하는 호스트 라우트 스타일
  • 이런 경우 통신은 보통:
    • 기본 게이트웨이로 보내면
    • 노드가 라우팅/오버레이로 목적지까지 전달하는 구조입니다.
  • 반대로 우리가 netns 실습에서 /24를 준 이유는 “같은 L2에서 ARP로 이웃을 찾아 직접 통신”시키려는 목적이었습니다.

마무리: 쿠버네티스 네트워킹을 보는 프레임

여기까지를 한 줄로 정리하면:

  • 리눅스: 인터페이스/라우팅/ARP/iptables(포워딩·NAT·DNAT)
  • 컨테이너: netns + veth + bridge
  • Docker: docker0 + iptables로 포트 퍼블리싱
  • Kubernetes: Pod 네트워크를 “CNI 플러그인”으로 표준화해서 구성
  • 문제 해결 순서: 노드 네트워크(포트/방화벽/라우트) → CNI/브리지/오버레이 → 서비스/포트포워딩

'CKA' 카테고리의 다른 글

Network - IPAM(IP Address Management)  (0) 2026.01.05
Network - Pod Networking & CNI  (1) 2026.01.05
Network - CNI(Container Network Interface)  (0) 2026.01.05
Network - Docker Network  (0) 2026.01.05
Network - 네트워크 기초(veth, bridge, routing, NAT, port-forward)  (1) 2026.01.05
'CKA' 카테고리의 다른 글
  • Network - IPAM(IP Address Management)
  • Network - Pod Networking & CNI
  • Network - CNI(Container Network Interface)
  • Network - Docker Network
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      cglib
      jdk 동적 프록시
      버퍼
      양방향 맵핑
      @discriminatorvalue
      조회 성능 최적화
      고급
      @discriminatorcolumn
      프록시 팩토리
      빈 후처리기
      reentarantlock
      JPQL
      스레드
      requset scope
      log trace
      @args
      @within
      gesingleresult
      hibernate5module
      김영한
      Thread
      typequery
      프록시
      자바
      WAS
      jpq
      단방향 맵핑
      락
      Target
      페치 조인
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Network - 정리(1)
    상단으로

    티스토리툴바