0x0102

도커 네트워크 기초 본문

Study/System Engineer

도커 네트워크 기초

jxx_yxjx 2024. 2. 6. 11:43

1. 컨테이너의 네트워크 이해하기

1) 기반 기술인 리눅스 네트워크의 적용

도커 네트워크는 곧 리눅스 네트워크라고 보아도 무방하다.

도커 네트워크는 CNM(Container Network Model) 인터페이스 위에 구축되며 OS나 인프라에 구애 받지 않고 사용할 수 있다.

 

리눅스 네트워크 빌딩 블록은 리눅스 브릿지, 네트워크 네임스페이스, veth pair, iptables등이 포함되는데 이 조합은 복잡한 네트워크 정책을 위한 규칙 및 네트워크 분할 및 관리 도구를 제공한다.

그 중 2계층에 해당하는 도구로 MAC 주소를 활용해서 식별하고 통신한다.

 

[리눅스 브릿지]

커널 내부의 물리적인 스위치를 프로그래밍적으로 가상 구현한 것이OSI Layer 2인 디바이스인데

트래픽을 검사하여 동적으로 학습되는 MAC Address를 기반으로 트래픽을 전달한다.

 

브릿지 네트워크의 기본 대역은 다음과 같다.

  1. 172.<17~31>.0.0/16 (65536개)
  2. 192.168.<0~240>.0/20(4096개)

 

Dokcer0를 두 영역으로 나눠야하는 상황에서

docker0만 놓고 보면 linux커널과 os도구를 통해 관리하고

해당 docker0위에 bridge들이 위치해서 도커엔진하에 관리되며

브릿지와 컨테이너 사이에 vethernet이 위치해 연결해준다.

 

+) 할당된 이더넷 브릿지 대역 확인 명령어

$ ifconfig docker0

 

2) 도커 네트워크

네트워크 네임스페이스

  • 커널에 격리된 네트워크 스택으로 자체 인터페이스, 라우트 및 방화벽 규칙 보유
  • 컨테이너와 리눅스의 보안적인 측면으로 컨테이너를 격리하는데 사용
  • 네트워크 네임스페이스는 도커 네트워크를 통해 구성된 경우가 아니면 동일한 호스트의 두 컨테이너가 서로 통신할수 있음이나 혹은 호스트 자체와 통신할 수 없음을 보장(방화벽 설정)
  • 일반적으로 CNM(Container Network Model)네트워크 드라이버는 각 컨테이너별로 별도 네임스페이스가 구현됨

 

sandbox는 격리된 네트워크 자체를 의미하며  ethernet, port, route table, DNS 구성등을 총체적으로 그룹화한다.

해당 컨테이너가 갖는 네트워크적 옵션이라고 생각해도 된다.

endpoint는 가상 이더넷의 인터페이스로 접근 ip, mac주소 등으로 접근할 수 있다.

network는 가상 스위치, 브릿지를 의미한다.

CNM 은 도커 네트워크가 이런 요소들을 가져야 한다고 정의해둔 인터페이스이고,

CNM을 기반으로 구현한 libnetwork가 바로 docker network이다.

 

 

$ docker network ls

실제 사용가능한 모델들을 확인할 수 있다.

bridge 는 기본적으로 싱글 호스트를 지원하고 내부망으로 연결만 해 줄 뿐 다른 네트워크와 연결되지 않는다.

멀티호스트는 bridge to bridge 수행을 위한 overlay라는 것을 통해 지원한다.

특정 네트워크 방식은 언제든 교체나 활용할 수 있다.

 

컨테이너는 직접 bridge와 연결될 수 없기에 vethernet은 컨테이너와 1:1로 매칭되어 브릿지 사이에서 중개해주는 역할을 한다.

컨테이너 자체의 엔드포인트는 ifconfig, route, ip a, ip addr, ip add 등의 명령어를 통해 조회할 수 있다.

브릿지는 brctl show를 통해 조회 가능하다.

 

[브릿지 내부 확인]

$ sudo apt install bridge-utils

브릿지 유틸 설치

$ brctl show

브릿지 조회 // docker0 네트워크를 활용하는 컨테이너들을 interfaces에서 확인

 

$ docker run -it -d --name=network-14 ubuntu:14.04

더 자세히 살펴보기 위해 도구가 많이 있는 14버전 우분투 설치

 

brctl show를 다시 수행하여 인터페이스 개수 체크 

 

$ docker exec -it network-14 ip addr

ip addr 명령을 수행 // loopback과 실제로 vethernet이 가지는 주소 확인

 

$ docker exec -it network-14 route

어느 브릿지에 연결되었는지 확인 // docker0 확인

 

$ docker inspect network-14 | grep -i ipa

컨테이너의 네트워크 설정 함께 조회 // ip 정보 확인

 

$ docker inspect network-14 | grep -i mac

mac address 확인

 

컨테이너가 네트워크 통신을 위해 갖는 모든것들은 샌드박스에 의해 정의됨.

 

[브릿지 조회]

$ docker network inspect bridge

IPAM 내부에는 네트워크 전체 대역에 대한 내용, containers에는 할당된 컨테이너들에 관한 내용이 보임

 

Veth는 두 네트워크 네임스페이스 사이의 연결을 위해 동작하는 리눅스 네트워킹 인터페이스이다.

vethernet은 각 네임스페이스에 단일 인터페이스를 가지는 전이중 링크로 양방향 통신이 가능하다.

 

도커 네트워크 생성시 veth를 이용해 네임스페이스간 명시적 연결을 제공한다.

+ Container의 Eth는 veth보다 기본적으로 1 작은 값으로 연결된다.

 

 

docker0는 172.17.0.1 이라는 아이피를 기본적으로 사용하지만 외부에서는 172.17 대역을 쓰지 않으므로 이를 보완하기 위해 NAT이라는것을 활용한다.

결국 어떤 서버의 아이피주소를 다시 내부아이피로 변환해줘야 하는데

이 때 매핑되는 주소는 iptables라는 명령어로 조회가능하다.

$ sudo iptables -t nat -L -n

 

2. 내부망 host들 상호간 등록하기

현재처럼 host1과 host2 터미널을 오가는 것이나 scp 등으로 파일을 보낼 때 불편함이 있다.

아이피주소가 아닌 host이름으로 해당 작업을 수행할 수 있다면 좀 더 편할것이므로 

해당 작업 수행에 필요한 테이블 등록을 해보자.

 

$ sudo vi /etc/hosts

에서 자신의 주소를 192 대역으로  설정하고 , hostos2도 설정해준다.

 

$ ssh 계정명@host명

로 제어 가능하다.

 

이외 네트워크 관련해서 지정할 수 있는 옵션들

--expose=포트번호 → 방화벽 열기처럼 해당 포트로의 접속을 외부에 공개

--net=bridge 혹은 none 혹은 host → constainer의 네트워크 설정

-h, --hostname=”호스트이름” → host의 이름을 설정 pid가 디폴트값.

-P, --publish-all=true 혹은 false → 포트바인딩시 호스트측 접근포트를 랜덤지정

-p host포트:컨테이너포트, --publish published=host포트, target=타겟포트 → 지정포트바인딩

--link=컨테이너명:컨테이너아이디 → 동일 host의 다른 컨테이너에서 이름으로 연결가능하게 지정

 

3. 브릿지와 오버레이의 차이

 

bridge는 기본적으로 내부망 진입점으로 기능하지만 자기 호스트 내부망만을 담당한다.

따라서 브릿지 간 통신, 즉 외부 호스트끼리 연결을 하기위해서는 overlay가 추가로 필요하다.

이는 도커 스웜으로 구현 가능하다.