0. Contents
1. Overview
03-1 정리: 방 안의 프로세스 하나
- 03-1 은 컨테이너를 방 안의 프로세스 하나로 봤다
- runC 가 방을 만들고, 네임스페이스가 무엇을 볼지, cgroup 이 얼마나 쓸지를 정했다
이 편의 주제: 방에서 밖으로 나가는 길
- 이 편은 그 방에서 밖으로 나가는 길이다
- 02-1 에서 손으로 만든 방·파이프·스위치가 다시 나타난다
- 도커에서는 모드라는 이름으로
- 쿠버네티스에서는 CNI 플러그인이 치는 명령으로
다루는 질문 네 가지
- 방을 만드느냐, 만들면 문을 어디로 내느냐 — 모드
- 브리지와 진짜 문(NIC) 사이는 무엇으로 이어지느냐 — 라우팅과 NAT
- 호스트 둘 사이는 어떻게 잇느냐 — 오버레이
- 그 모든 것을 누가 꽂느냐 — CNM 과 CNI
- 마지막 장에서 Go 서버 하나를 네 자리에서 두드려 이 넷이 실제로 어떻게 보이는지 확인한다
2. Docker Network Modes — 방을 만드느냐, 문을 다느냐
2.1 모드는 새 기술이 아니다
모드: 02-1 부품의 조합
docker run --network <모드>의 모드는 컨테이너의 네트워크 방을 어떻게 꾸밀지 고르는 선택지다- 전부 02-1 에서 만든 부품 — 방, 문, 파이프, 스위치 — 의 조합이다
- 질문은 둘뿐이다
- 방을 따로 만드는가
- 만들면 그 방의 문을 어디로 내는가
모드별 방과 문
- host — 방을 안 만든다
- 호스트의 방에서 그대로 산다
- 컨테이너 IP 가 따로 없고, 앱이 여는 포트는 호스트의 포트 공간에 속해 다른 프로세스와 충돌할 수 있다
-p는 적용되지 않는다
- none — 방은 만들되 문이 없다
- lo 만 남아 자기 자신과만 통한다
- bridge — 방을 만들고 문을 호스트 안의 스위치(docker0)에 꽂는다
- 기본값이고 2장 실습의 구조다
- 나가는 트래픽은 호스트가 NAT 로 내보내고, 들어오는 연결은
-p로 받는다
- macvlan, ipvlan — 방을 만들고 문을 물리 NIC 위에 직접 낸다
- 컨테이너가 LAN 에 꽂힌 별도 장비처럼 보인다
- 컨테이너가 호스트 뒤에 숨지 않고 호스트와 나란히 서는 구성이다
- 둘의 차이는 MAC 을 각자 갖느냐(macvlan) 호스트 것을 나눠 쓰느냐(ipvlan)다
- overlay — 여러 호스트의 방들을 터널로 이어 같은 스위치에 있는 것처럼 만든다
- 4장에서 다룬다
--network container:<이름>— 남의 방에 같이 산다- IP, 포트 공간, lo 를 공유해 127.0.0.1 로 서로에게 닿는다
- 쿠버네티스 Pod 의 pause 컨테이너가 하는 일이 정확히 이것이다
2.2 셋을 나란히 띄우면 [실습]
실습: 모드만 바꾼 busybox 셋
- 말로는 다 비슷해 보여서 VM 에서 busybox 를 모드만 바꿔 셋 띄웠다
- 비교한 것: 안에서 보이는 인터페이스와 경로, 그리고
/proc/PID/ns/net의 번호
for m in bridge none host; do docker run -d --name m-$m --network $m busybox sleep 600; done
for c in m-bridge m-none m-host; do docker exec $c ip -o -4 addr; docker exec $c ip route; done
sudo readlink /proc/1/ns/net
for c in m-bridge m-none m-host; do sudo readlink /proc/$(docker inspect -f '{{.State.Pid}}' $c)/ns/net; done
결과: 번호 하나가 셋을 가른다
- bridge 와 none 은 호스트와 다른 번호를 받았고, host 는 호스트 PID 1 과 같은 번호다
- 방을 안 만들었다는 것이 숫자로 보인다
- none 의 방에는 lo 하나뿐이고 경로가 한 줄도 없다
- bridge 의 방에는 eth0 이 있고 그 이름의
@if52는 호스트 쪽 짝 인터페이스의 번호다- veth52 라는 이름이 아니라 번호 52 번이다
- 호스트에서
ip link show master docker0을 치면 그 번호의 veth 가 docker0 에 꽂혀 있다
포트 공간 확인
- bridge 컨테이너와 host 컨테이너가 동시에 8080 을 열어도 충돌하지 않는다
- host 쪽 8080 은 호스트의
ss -lnt에 나타나고, bridge 쪽 8080 은 그 방 안에만 있다- 02-1 의 4.2 와 같은 이야기다
2.3 안과 밖 — 번호로 짝 찾기, 방에 들어가기 [실습]
실습: bridge 컨테이너 하나의 안과 밖
- 컨테이너 안 — eth0 이 어떤 번호를 달고 있는지, 라우팅 표에 무엇이 적혀 있는지
- 호스트 — docker0 에 어떤 인터페이스가 꽂혀 있는지, 호스트 라우팅 표에 docker0 으로 가는 줄이 있는지
docker exec m-bridge ip -o link show eth0
docker exec m-bridge ip route
ip link show master docker0
ip route | grep docker0
방 안의 라우팅 표 두 줄 읽기
- 조각으로 끊어 읽으면 된다
짝 찾기: eth0@if52 와 veth12ba5d7@if2
- 안의 eth0@if52 와 밖의 veth12ba5d7@if2 가 한 쌍이다
- 이름이 아니라 번호로 짝을 찾는다
- 안의 2번은 밖의 52번과, 밖의 52번은 안의 2번과 묶여 있다
- veth52 같은 이름은 없다
- 안의 기본 경로가 가리키는 172.17.0.1 은 밖의 docker0 주소다
- 도커가
docker run한 번에 방, veth, 주소, 경로를 전부 준비했다- 02-1 에서 손으로 친 명령 아홉 줄이 그 안에 들어 있다
방에 들어가는 길: 02-1 의 5.1 과 같다
ip netns list는 비어 있어도 PID 로 찾아가면 된다nsenter -t PID -n은 네트워크 방만 바꾸므로 이미지 안에 ip 명령이 없어도 호스트의 ip 를 쓸 수 있다- 책은
/run/netns/에 링크를 걸어ip netns exec로 들어가는 방식을 쓴다- 같은 일을 이름 등록으로 하는 것이라 해도 되고 안 해도 된다
- 정지된 컨테이너의 State.Pid 는 0 이니 재시작했으면 다시 조회한다
전체 명령과 출력 — 02-docker-modes
2.4 기본 네트워크 셋과 docker0 의 주소
기본 네트워크 객체 셋
docker network ls에는 bridge, host, none 이 기본으로 있다- 모드 셋이 네트워크 객체로 미리 만들어져 있는 것이다
--network를 안 주면 bridge 에 붙는다
docker0 의 주소와 상태
- 호스트 쪽 브리지 이름은 docker0 이고 이 VM 에서는 172.17.0.1/16 이다
- 이 값은 흔한 예일 뿐 보장되지 않는다
- 기존 네트워크와 겹치거나 데몬 설정이 다르면 다른 대역을 쓴다
docker network inspect bridge로 실제 값을 본다
- 컨테이너가 하나도 없을 때 docker0 이 DOWN 으로 보이는 것은 고장이 아니다
- 02-1 의 3.1 에서 본 그 DOWN 이다
3. Docker Networking Model — 이름 셋, 그리고 호스트 밖으로
3.1 CNM — Sandbox, Endpoint, Network
CNM 의 세 단어
- 도커는 자기 네트워크 모델에 CNM(Container Network Model)이라는 이름을 붙였다
- 구현체인 libnetwork 가 세 단어로 구성을 나눈다
- Sandbox — 컨테이너가 쓰는 네트워크 환경 전부
- 네트워크 네임스페이스에 인터페이스·경로·DNS 설정을 더한 것
- Endpoint — 그 Sandbox 를 네트워크 하나에 잇는 접점
- veth 한 쌍
- Network — 서로 통하는 Endpoint 들의 집합
- 브리지 하나
리눅스 브리지 구성과의 대응
- 리눅스 브리지 구성에 대응시키면 새 부품은 하나도 없다
Endpoint: 호스트가 아니라 연결 하나
- Endpoint 를 호스트로 읽으면 안 된다 — 연결 하나다
- Sandbox 하나에 Endpoint 를 둘 달면 컨테이너 하나가 네트워크 둘에 참여한다
- 앱용 bridge 와 DB 용 bridge 를 따로 만들고 앱 컨테이너만 둘 다에 붙이면
- 앱끼리는 app-net 으로 통한다
- DB 에는 db-net 으로만 닿는다
- 모델은 이 셋뿐이고, 실제로 어떻게 잇는지는 드라이버(bridge, host, overlay, macvlan …)가 정한다
- 책의 “custom” 은 드라이버 이름이 아니라 사용자가 만든 네트워크를 가리키는 말이다
3.2 브리지의 바깥 연결 — NAT 는 기본값이지 법칙이 아니다
기본 bridge 구성의 주소와 연결
- 기본 bridge 구성에서 컨테이너는 사설 주소를 받는다
- 밖으로 나갈 때는 masquerade 로 출발지가 호스트 주소로 바뀐다
- 밖에서 들어오는 연결은
-p로 호스트 포트를 컨테이너 포트에 이어야 받는다 - 같은 브리지 안의 컨테이너끼리는 컨테이너 IP 와 실제 포트로 바로 통한다
바탕: docker0 과 ens3 는 서로 꽂혀 있지 않다
- 둘은 호스트 루트 방의 문 둘이고, 사이에 호스트의 IP 계층이 서 있다
- 컨테이너가 바깥으로 보낸 패킷은 다섯 단계를 거친다
바깥행 패킷의 다섯 단계
- ① 컨테이너 방의 라우팅이 바깥행 패킷을 docker0 에게 넘긴다
- ② docker0 에 도착한 패킷은 목적지 MAC 이 docker0 자신이라 스위칭되지 않고 호스트 IP 계층으로 올라간다
- ③ 호스트 IP 계층은 자기 라우팅 표를 보고 ens3 를 고른다
- 남의 패킷을 넘겨 주려면
ip_forward가 켜져 있어야 한다
- 남의 패킷을 넘겨 주려면
- ④ 나가기 직전에 MASQUERADE 규칙이 출발지를 172.17.0.2 에서 호스트 주소 10.0.0.198 로 바꾼다
- ⑤ ens3 가 케이블로 내보내고, 답장은 02-2 의 conntrack 장부를 따라 거꾸로 돌아온다
들어오는 연결과 컨테이너끼리의 연결
- 들어오는 연결의
-p는 같은 자리에서 목적지를 바꾸는 DNAT 규칙이다 - 컨테이너 둘이 서로 통할 때는 이 다섯 단계 중 docker0 의 스위칭만 쓰고 IP 계층으로 올라가지 않는다
02-1 그림에서 ens3 를 따로 그린 이유
- 02-1 의 브리지 그림에서 ens3 를 브리지에 꽂지 않고 옆에 따로 그린 이유가 이것이다
- 책의 열 단계는 반대로 진짜 NIC 를 브리지의 포트로 직접 꽂는다
- 그러면 호스트 IP 계층을 거치지 않고 컨테이너가 건물 LAN 에 직접 선다
- 그 구성의 정식 버전이 2.1 의 macvlan 이고, 문서의 실습은 그 방식을 쓰지 않는다
문서가 못 박는 보정 두 가지
- 이건 기본 IPv4 bridge 의 이야기이지 도커의 법칙이 아니다
- IPv6, routed gateway 모드, macvlan·ipvlan, 라우팅을 따로 짠 환경에서는 NAT 없이 나간다
- 책은 도커가 iptables 로 격리한다고 쓰는데, 방화벽 구현을 하나로 고정하면 지금 구성을 놓친다
- Docker Engine 29.0 에 native nftables 백엔드가 들어왔고, 확인 시점 문서에서는 실험 기능이며 Swarm 에서는 켤 수 없다
- iptables 명령이 nft 호환 계층 위에서 도는 것과 도커의 native nftables 백엔드는 다른 설정이다
- 02-2 에서 본 VM 의 iptables 는 nf_tables 백엔드 위의 호환 계층이었다
3.3 Overlay — 호스트 둘 사이의 터널
브리지의 한계: 호스트 안의 연결만
- 호스트 하나의 브리지는 그 호스트 안의 연결만 준다
- 두 호스트에 docker0 을 하나씩 만들었다고 둘이 이어지지 않는다
- 여러 호스트의 컨테이너가 통하려면 상대 주소로 가는 경로, 주소 중복 방지, 노드 사이 전달 방식이 더 필요하다
- 답은 오버레이이거나 일반 IP 라우팅이다
- 오버레이는 이미 이어져 있는 호스트 네트워크(underlay) 위에 컨테이너용 논리 네트워크(overlay)를 얹는 것이다
도커 overlay 드라이버: VXLAN 터널
- 도커의 overlay 드라이버는 VXLAN 으로 이 터널을 만든다
- 컨테이너가 보낸 이더넷 프레임을 VTEP 가 UDP 4789 패킷에 통째로 담아 상대 호스트의 VTEP 에 보낸다
- 받은 쪽이 바깥 헤더를 벗겨 원래 프레임을 꺼낸다
- VLAN ID 가 12비트인 데 비해 VNI 는 24비트라 식별 값이 약 1,677만 개다
- 규격상의 수이지 그만큼 운영할 수 있다는 보장은 아니다
- 헤더가 50바이트쯤 붙으니 MTU 를 그만큼 줄여야 한다
- 캡슐화는 암호화가 아니라서 도커 overlay 의 암호화는 별도 옵션이다
- 헤더 비트 구조와 MTU 1450 의 계산은 VXLAN 위키에 있다
책과 다른 점: 외부 저장소는 옛 classic Swarm 이야기
- 책은 여러 호스트의 정보를 나누려면 Consul·etcd·ZooKeeper 같은 외부 저장소가 반드시 필요하다고 쓴다
- 옛 classic Swarm 의 이야기다
- 그 옵션은 Docker 23.0 에서 제거됐다
- 지금의 Swarm 모드는 manager 들이 Raft 합의로 클러스터 상태를 직접 관리한다
- 도커의 overlay 드라이버를 쓰려면 호스트들이 Swarm 에 참여해 있어야 한다
- 일반
docker run컨테이너를 붙이려면--attachable네트워크를 만든다
- 일반
- 이 편에서는 Swarm 을 세우지 않았다
- 오버레이의 실물은 4장의 쿠버네티스 노드 사이에서 본다
4. CNI — 런타임이 밖의 실행 파일을 부르는 약속
4.1 CNI 가 정하는 경계
CNI 의 뜻: 규격과 생태계
- CNI(Container Network Interface)는 컨테이너 실행 시스템이 네트워크 플러그인을 어떻게 부를지 정한 규격이다
- 그 규격을 따르는 라이브러리와 플러그인 생태계를 함께 가리키는 말이기도 하다
- CoreOS 의 rkt 에서 출발했고, 도커의 CNM 과는 추상화와 호출 경계가 다르다
- CNI 는 특정 브리지나 VXLAN 제품의 이름이 아니다
일반적인 리눅스 구성의 역할 분담
- 런타임이 네트워크 네임스페이스를 준비한다
- CNI 플러그인이 그 안의 인터페이스와 주소와 경로를 구성한다
- 필요하면 호스트 쪽 설정도 한다
- IP 할당은 IPAM 플러그인에 넘길 수 있다
- 플러그인 여럿을 이어서 인터페이스를 만든 뒤 추가 설정을 얹을 수도 있다
- 모든 플러그인이 veth 와 브리지와 NAT 를 똑같이 만드는 것은 아니다
플러그인: /opt/cni/bin/ 의 실행 파일
- 설정의
"type": "bridge"가 그 파일 이름이다 - 공식 저장소의 플러그인
- 인터페이스를 만드는 bridge·macvlan·ipvlan·host-device
- 주소를 주는 host-local·dhcp
- 뒤에 덧붙이는 portmap·bandwidth
- Flannel 은 bridge 와 host-local 을 그대로 쓰고 노드 사이 전달만 맡는다
- Cilium 은 자기 플러그인을 쓴다
bridge 플러그인 한 번의 호출 흐름
규격 버전과 설정 파일
- 규격 버전(1.1.0)과 런타임·플러그인의 릴리스 버전은 별개다
- STATUS 나 GC 를 실제로 지원하는지는 따로 본다
- 설정 파일의 모양과 체이닝은 CNI 위키에 있다
얇은 인터페이스의 범위
- CNI 는 실행 파일을 부르는 얇은 인터페이스이지만, 그 위에 올라간 네트워크 시스템 전체가 데몬 없이 돈다는 뜻은 아니다
- 많은 구현이 노드마다 에이전트를 두고 클러스터 컨트롤러를 함께 쓴다
- CNI 규격만으로 NetworkPolicy, 서비스 로드밸런싱, 암호화가 저절로 생기지도 않는다
4.2 kubelet 과 런타임의 역할
CNI 를 부르는 쪽: 런타임
- kubelet 은 CRI 로 런타임에 Pod sandbox 와 컨테이너를 만들어 달라고 요청한다
- 일반적인 containerd 나 CRI-O 구성에서는 그 런타임이 CNI 를 호출해 Pod 네트워크를 준비한다
- 책은 kubelet 이 직접 CNI 설정을 읽고 플러그인을 관리한다고 썼는데, 지금 구조와 다르다
- kubelet 의
--network-plugin,--cni-bin-dir같은 옛 옵션은 1.24 에서 제거됐다
- kubelet 의
- 03-1 의 런타임 스택 그림에서 CRI 선 아래, OCI 선 위에 있는 containerd 가 CNI 를 부르는 쪽이다
같은 Pod 의 네트워크 공유
- 같은 Pod 의 컨테이너들은 네트워크 네임스페이스를 공유하므로 같은 IP 와 같은 포트 공간을 쓴다
- 서로 localhost 로 통하고, 같은 포트를 같은 방식으로 열면 충돌한다
- 다른 Pod 사이의 통신은 네트워크 구현이 주는 경로와 정책을 따른다
- 2.1 의
--network container:공유와 03-1 의 4.3 이 이 이야기다
CNM 과 CNI: 관리 범위의 구분
- CNM 과 CNI 는 어느 쪽이 낫다는 비교 대상이 아니다
- 어떤 시스템이 무엇을 관리하는지 나누어 볼 대상이다
- 도커 CLI 의 네트워크 설정이 곧 쿠버네티스 Pod 네트워크 설정이 아니다
- 도커 bridge 의 주소 할당 방식이 쿠버네티스 전체에 그대로 적용되지도 않는다
4.3 대표 구현 넷 — 이름 하나로 패킷 경로를 단정하지 않는다
VXLAN·Geneve 오버레이도, native routing 도 된다. eBPF 를 쓴다고 오버레이가 없는 게 아니다.
연결성만 준다. NetworkPolicy 집행은 별도 컨트롤러나 Calico·Cilium 조합이 필요하다.
책의 "Calico 는 오버레이를 안 쓴다" 는 틀린 일반화다. 데이터플레인도 여럿이라 이름만으로 경로를 못 정한다.
오버레이가 없다고 늘 빠른 건 아니다. 인스턴스 유형, ENI 와 주소 한도, 서브넷 여유 IP 가 성능을 정한다. 보안 그룹과 NetworkPolicy 는 다른 층이다.
고르는 기준과 이 장의 목적
- 고르는 기준은 연결 방식, 쓰는 클라우드, 정책 요구, 운영자가 볼 수 있는 정보, 커널 조건이다
- 이 장의 목적은 특정 CNI 를 고르는 게 아니다
- 어떤 구현이든 네임스페이스·인터페이스·주소·경로를 어떻게 구성하는지 읽을 준비를 하는 것이다
- 5장에서 Cilium 을 노드에 직접 깔고 그 네 가지를 확인한다
5. Container Connectivity — 같은 서버, 부르는 자리 넷 [실습]
실습 구성: Go 서버 하나, 부르는 자리 넷
- 웹 서버 하나를 컨테이너로 띄우면, 그 서버를 부르는 자리마다 이름과 주소와 포트가 달라진다
- Go 표준 라이브러리로 짠 작은 웹 서버를 두 단계 Dockerfile(golang 에서 컴파일, scratch 에 실행 파일만)로 빌드해 13.5 MB 이미지를 만들었다
- VM 에 사용자 정의 브리지 하나, 그 서버 하나, busybox 클라이언트 하나를 띄워 네 자리에서 두드렸다
- 같은 브리지의 컨테이너, 도커 호스트, 다른 호스트(내 맥), 서버의 방을 공유한 컨테이너
- 서버는 응답에 자기 호스트명과 상대 주소를 같이 적어 돌려주게 했다
- 어느 자리에서 온 요청인지 서버 쪽에서도 보인다
5.1 이름은 사용자 정의 브리지에서만 풀린다
내장 DNS: 127.0.0.11
- cli 안의
/etc/resolv.conf에 nameserver 127.0.0.11 한 줄이 있다 - 이 주소가 도커가 그 네트워크에 붙여 둔 내장 DNS 다
- 같은 일을 기본 docker0 브리지에서 하면
wget: bad address 'web-def:8080'로 실패하고, IP 로는 된다 - 이름이 풀린 뒤에는 172.19.0.2 의 8080 으로 바로 가고 NAT 도 공개 포트도 거치지 않는다
- 쿠버네티스에서 Service 이름을 CoreDNS 가 푸는 것이 같은 자리의 확장이다
리슨 주소: 방의 모든 인터페이스
- 서버가
ss -lnt에*:8080으로 보이는 것이 “방의 모든 인터페이스에서 듣는다” 는 뜻이다 - 그래서 cli 와 호스트가 172.19.0.2:8080 으로 닿는다
- 서버를 방 안의 127.0.0.1:8080 에만 바인딩하면 둘 다 실패한다
- 서버가 돌려준 상대 주소가 자리마다 다른 것도 같은 이유다
- cli 에서 오면 172.19.0.3
- 호스트에서 오면 브리지 주소 172.19.0.1
- 맥에서 오면 집의 공인 IP
5.2 -p 는 호스트가 적어 둔 DNAT 한 줄이다
-p 127.0.0.1:18080:8080 의 실체
- nat 테이블의 규칙 한 줄이다
-A DOCKER -d 127.0.0.1/32 ! -i br-1eb8518464c8 -p tcp --dport 18080 -j DNAT --to-destination 172.19.0.2:8080
창구로 들어온 패킷이 방까지 가는 길
규칙의 범위: 호스트 루프백의 18080 만
- 호스트 루프백의 18080 으로 온 것만 172.19.0.2:8080 으로 바꾼다
- 공개한 적 없는 호스트의 127.0.0.1:8081 은 exit 7(연결 거부)로 끝난다
- cli 가 서버 IP 의 18080 으로 쳐도 거부된다
- 공개가 방 안의 리슨 포트를 바꾸는 게 아니라 호스트에 창구를 하나 내는 것이다
창구를 내는 주소에 따른 차이
- 호스트 주소를 적지 않은
-p 0.0.0.0:8080:8080은 모든 주소에 창구를 낸다- 호스트의 127.0.0.1:8080 도 되고 내 맥에서 VM 공인 IP 의 8080 으로도 닿았다
- 루프백에만 낸 18080 은 맥에서 닿지 않았다
- 02-2 의 외부 접속 실습과 같은 결과다
5.3 localhost 는 부르는 쪽의 방이다
cli 의 localhost:8080: 실패
- cli 의 localhost:8080 은 실패했다
- cli 의 방 번호는 4026532345, web 의 방 번호는 4026532266 으로 다르다
- 127.0.0.1 은 각자의 lo 다
방을 공유한 컨테이너의 localhost: 성공
--network container:web으로 띄운 컨테이너는 web 과 같은 번호 4026532266 을 받았다- 그 안에서 localhost:8080 이 성공했다
- 서버가 본 상대 주소는 127.0.0.1 이었다
- 03-1 의 4.3 에서 본 Pod 의 모양이 이것이다
- “컨테이너에서 localhost 로 DB 에 붙었는데 안 된다” 는 장애의 답이기도 하다
내 맥에서 172.19.0.2:8080: 실패
- 내 맥에서 172.19.0.2:8080 은 실패했다
- 사설 주소라서가 아니라 맥에 그 대역으로 가는 경로가 없어서다
- 겹치지 않는 주소 배정과 노드 사이 라우팅과 전달·방화벽 정책을 갖추거나 3.3 의 오버레이를 얹으면 사설 주소끼리도 통한다
- 쿠버네티스 네트워크 모델의 “모든 Pod 가 NAT 없이 서로 닿는다” 는 요구가 바로 이 조건을 네트워크 구현에 맡긴 것이다
전체 명령과 출력 — 03-connectivity
6. Discussion
6.1 도구 지도 — 질문에서 명령으로
“연결이 안 된다” 의 다섯 가지 고장
- “연결이 안 된다” 는 한 문장은 다섯 가지 다른 고장일 수 있다
- 이 편의 실습이 그 다섯을 하나씩 따로 보여 줬다
readlink /proc/PID/ns/net문이 있나 →
docker exec … ip -o -4 addr짝은 몇 번인가 →
ip -o link show eth0 의 @ifN기본 네트워크 셋 →
docker network lscat /etc/resolv.conf (127.0.0.11)브리지에 뭐가 꽂혔나 →
ip link show master docker0브리지 주소는 →
docker network inspect bridge서버가 어디서 듣나 →
nsenter -t PID -n ss -lntdocker port web그 DNAT 규칙은 →
iptables -t nat -S DOCKER나갈 때 NAT 는 →
iptables -t nat -S POSTROUTING호스트가 넘겨 주나 →
sysctl net.ipv4.ip_forwardls /etc/cni/net.d/실행 파일은 →
ls /opt/cni/bin/브리지 계열인가 →
ip -d link show cni0Pod 의 주소는 →
kubectl get pod -o wide못 닿을 때 확인 순서
- 서버가 0.0.0.0 에서 듣는가
- 부르는 쪽이 같은 방인가 다른 방인가
- 다른 방이면 이름이 풀리는가
- 호스트 밖이면 창구를 냈는가
- 다른 호스트면 그 대역으로 가는 경로가 있는가
문서 §14 의 다섯 항목
- 문서 §14 의 말로는 이름 해석, 리슨 주소·포트, 로컬 네임스페이스, 호스트 전달, 원격 경로 다섯이다
핵심 메시지
02-1 에서 손으로 친 명령 아홉 줄이 도커에서는
docker run한 번이고, 쿠버네티스에서는 containerd 가 부르는 플러그인 실행 파일 하나다. 이름이 바뀌었을 뿐 방과 파이프와 스위치는 같다. 그래서 연결이 안 될 때 볼 곳도 같다. 어느 방에서 부르는지, 이름이 풀리는지, 창구를 냈는지, 경로가 있는지. 다음 장은 그 방들이 수십 대의 노드에 흩어졌을 때 — Pod 와 Service 와 kube-proxy 가 이 편의 브리지·공개 포트·터널을 어떻게 다시 조립하는지다.
7. References
"Containers on the default bridge network can only access each other by IP addresses"
"The runtime must execute the plugin with the following environment variables"
"VXLAN is a Layer 2 overlay scheme on a Layer 3 network"
"pods can communicate with all other pods on any other node without NAT"
