✔️ Docker Network 개요
우분투 컨테이너를 하나 띄우고 ip a s 명령을 실행한다.
root@779202aa7aac:/# apt install iproute2
root@779202aa7aac:/# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
55: eth0@if56: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
eth0@if56 이라는 인터페이스가 하나 존재한다.
vagrant@docker ~ ip a s
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:c5:5d:8f:6e brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:c5ff:fe5d:8f6e/64 scope link
valid_lft forever preferred_lft forever
56: veth394aca2@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c2:7a:21:05:5e:25 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c07a:21ff:fe05:5e25/64 scope link
valid_lft forever preferred_lft forever
다시 도커 호스트에서 ip a s 명령을 치면 56: veth394aca2@if55 인터페이스를 확인할 수 있다.
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
779202aa7aac ubuntu "bash" 18 minutes ago Up 18 minutes elegant_stonebraker
vagrant@docker ~ docker rm -f 77
77
vagrant@docker ~ ip a s
----------------- 이전 생략 -----------------
여기서 컨테이너를 지우면 veth로 시작하던 인터페이스가 없어진다.
다시 컨테이너를 만들면 veth도 하나 생성된다.
이 구조를 그림으로 그려보자면 다음과 같다.
도커가 설치된 ubuntu 호스트가 있고 enp0s8(192.168.100.100) 인터페이스가 있다.
docker0은 엄밀히 네트워크 인터페이스가 아니라 virtual bridge라고 한다.
bridge란 무엇인가 ?
- bridge : switch의 전신
- L3 장치 router : routing 해주는 장치
- L2 장치 switch : bridge에서 명칭 변경만 했을 뿐
실제로 가상화에서 브릿지라는 용어를 많이 쓰는데 그냥 스위치라고 생각하면 된다.
가상의 브릿지, 가상의 스위치이기 때문에 컴퓨터 내부에서만 SW적으로 작동하며 논리적으로만 존재하는 것이다.
컨테이너를 만들면 veth 인터페이스가 만들어지며 이를 통해 브릿지에 연결되고 ip는 172.17.0.2, 3, 4 ....로 붙게된다.
앞서 veth 라는 인터페이스가 보였는데 그것이 docker0 이라고 하는 브릿지(스위치)의 인터페이스이다.
✔️ Virtual Bridge 확인 명령어
vagrant@docker ~ sudo apt install bridge-utils
vagrant@docker ~ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c55d8f6e no veth6566a6d
bridge-utils 패키지를 설치하고 brctl 명령을 입력하면 virtual bridge를 확인할 수 있다.
도커 엔진 설치시 브릿지 이름은 무조건 docker0으로 고정된다.
이 브릿지(docker0)에 연결되어있는 인터페이스는 컨테이너와 docker0을 연결하는 인터페이스인 veth인 것이다.
그리고 이 veth가 컨테이너의 eth0@if~에 연결된다.
컨테이너에서 인터넷 통신을 하려면 enp0s3, enp0s8(도커 호스트의 인터페이스)와 docker0의 중간에서 라우팅이 필요하다.
그렇다면 이 중간에서 라우팅 기능을 하는 것이 무엇인가 ?
✔️ Netfilter의 역할
- centos - firewalld
- ubuntu - ufw
커널 영역에는 netfilter 라는 핵심 기능이 있다. 이 netfilter는 모든 네트워크 기능을 담당한다.
netfilter라고 하는 도구를 사용하기 위한 명령어가 iptables이다. iptables 명령어를 사용하여 netfilter 기능을 구현할 수 있다.
하지만 iptables 명령어를 사용하기가 꽤 까다롭다. 이를 위해 레드헷 계열에서 만들어 놓은 도구가 firewalld인 것이다.
firewalld 명령을 사용하면 netfilter 기능을 구현할 수 있다.
데비안 계열은 uwf라는 방화벽을 쓰는데 역시 netfilter를 제어하는 것이다.
vagrant@docker ~ sudo iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
- -t : 여러 종류의 테이블이 존재한다.
- -L : 리스트
- -n : numeric(숫자)를 붙여 깔끔하게 출력한다.
Chain POSTROUTING 항목에서의 MASQUERADE는 일반적인 의미로는 "조작"의 의미를 가진다.
여기서는 ip의 헤더를 변경 시킨다는 의미이다.
docker0에 컨테이너가 있고 docker0은 항상 ip 172.17.0.1를 가진다. 그리고 docker0은 gateway 역할을 한다.
컨테이너가 가지는 ip가 172.17.0.3 라고 해보자 이 컨테이너는 gateway를 통해 외부로 나가는 것이며 인터넷 통신을 위해서는 docker0가 호스트의 인터페이스인 enp0s3으로 연결되어 나가야한다.
출발지 172.17.0.3(컨테이너)에서 외부로 통신하기위해 실제로 라우터가 있는 것처럼 NAT 기능을 하는 것이 iptables이다.
iptables가 라우터는 아니지만 NAT 기능을 하는 라우터의 역할을 iptables가 담당한다.
결론적으로는 컨테이너가 출발지를 바꿔서 나가야한다.
출발지 172.17.0.0/16는 모든 컨테이너를 의미하며 모든 컨테이너에서는 출발지 ip를 바꿔서 나가라는 뜻이다.
이 설정이 없으면 컨테이너 내부에서 외부로 나갈 수 없다.
'DevOps > Docker' 카테고리의 다른 글
[Docker] Netfilter의 역할 (0) | 2022.05.10 |
---|---|
[Docker] Docker Network - 2 (0) | 2022.05.10 |
[Docker] Docker Volume (볼륨) (0) | 2022.05.09 |
[Docker] Docker 컨테이너 관리 명령어 (3) (0) | 2022.05.07 |
[Docker] Docker 컨테이너 관리 명령어 (2) (0) | 2022.05.07 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!