도커 네트워크
도커 네트워크란, Docker 컨테이너 간의 통신을 관리하고 격리하기 위한 기능이다
예를 들어, A컨테이너와 B 컨테이너에서 MariaDB가 띄워져 있고 이 두개가 master/slave 관계를 맺고 싶다. 그 경우에 서로가 통신 가능하게끔 추가 설정을 해줘야할텐데 이를 도커 네트워크 기능으로 할 수 있는 것이다.
도커 네트워크의 구조
기존 컴퓨터는 서버와 통신 시 네트워크를 통해 이루어진다. 이에 따라 도커 네트워크도 컨테이너들이 서로 통신을 하기 위해 필요한 규칙과 구조를 만들어 준다.
그 전에 용어를 몇 개 알고가야 한다
사전용어
eth0 (Ethernet network card)
이더넷 네트워크 카드, 네트워크 인터페이스, 랜카드 등등으로 불리는데 쉽게 말하면 컴퓨터가 네트워크에 연결되려면 물리적 연결 장치가 필요하다. 이 장치를 운영체제가 관리하기 위해 이름을 붙이는데, 보통 첫 번째 네트워크 인터페이스를 eth0으로 부른다. 그러니 eth1, eht2는 추가 네트워크 장치로 두 번째, 세번째 LAN 포트를 나타낸다.
더 쉽게 보자면 집에 인터넷을 쓰기 위해 WIFI를 사용하거나 유선 LAN 케이블을 꽂을텐데, 컴퓨터 입장에서는 Wi-fi 모듈이나 LAN 포트가 네트워크 연결을 담당하는 장치로 본다. 그래서 이 장치를 Linux와 같은 OS가 eth0(첫번째 장치)라고 부른다.
lo(Loopback 인터페이스)
특별한 가상의 네트워크 인터페이스인데, 컴퓨터가 자신과 통신할 때 사용한다. 즉, 컴퓨터 본인이 본인에게 데이터를 주고받는 가상의 네트워크 연결로 주로 개발 환경에서 테스트용으로 볼 수 있다.
도커 컨테이너는 어떻게 네트워크를 구성할까
Veth에 대하여
기본적으로 Docker를 OS에서 설치하면 여러가지 Network Driver가 설치된다. 그리고 구동되는 컨테이너에 IP 주소를 순차적으로 할당하며 네트워크 구성시 원하는 네트워크 드라이버를 선택할 수 있게 된다.
컨테이너가 있다. 컨테이너는 저마다 가상 이더넷 인터페이스인 veth가 존재한다. 이 veth라는 인터페이스는 사용자가 직접 생성할 필요가 없고 도커 엔진이 자동으로 생성해주는 애다.
그림에서 봤을때, eth0은 컨테이너 내부에서 보이는 네트워크 인터페이스로, 컨테이너 내부에서 네트워크와 통신하는 출입구(문) 역할을 한다.
그리고 이제 veth는 가상의 네트워크 케이블로서, 컨테이너 내부의 eth0과 호스트(컴퓨터)의 네트워크 인터페이스를 연결한다. 그러니 veth는 항상 쌍(pair)로 동작하는데, 한쪽 끝은 컨테이너의 eth0에 연결되고 다른 쪽 끝은 호스트의 네트워크에 연결된다. 아직 그려진 그림에는 veth가 한 쪽에만 있으나 실제론 반대방향로도 연결된 곳이 따로 있는 것이다.
생략된 부분까지 표기하면 이런 꼴로 생각할 수 있는데, 여기서 Bridge가 나타난다.이는 호스트(도커가 실행되는 컴퓨터)의 브리지 네트워크로서, 각 컨테이너에서 나오는 veth를 모아다 외부 인터넷과 연결해준다. 비유하여 정리하면 이렇다.
- 컨테이너: 방
- eth0: 방에 연결된 인터넷 선
- veth: 방과 복도를 연결하는 인터넷 케이블
- bridge network: 각 방에서 나온 케이블을 모아 외부 인터넷과 연결해주는 복도
도커 컨테이너에 Network 할당 테스트
수동 설정이 되지 않았던 기존 컨테이너의 Network 확인
VScode의 확장도구로 podman이나 docker를 설치해주면 갖고 있는 컨테이너들을 살펴볼 수 있는데, NETWORK에 보면 지정해 준적이 따로 없어도 Bridge로 컨테이너들이 묶여있는 것을 볼 수 있다
그 중, Kafka는 Compose를 통해 Broker 3개가 엮어놓아져 있기에 Inspect 내부를 살펴보면, 각각의 브로커가 순차적으로 IP를 할당해놓은 것을 확인한다. 즉, 컨테이너를 실행할 때 별도의 네트워크를 지정하지 않는다면 기본적인 Host Bridge Network에서 동작하며 IP를 순차적으로 할당받게 되어있다.
직접 Docker-network를 만들어 ping 테스트해보기
ping으로 두 컨테이너간의 통신 연결을 확인하고 싶다면, 새로 네트워크를 생성하여 해당 네트워크로 설정해 주어야 한다. 기본 제공 브릿지 네트워크는 통신 지원은 하나 일부 제약이 있어, 컨테이너 이름으로 ping 작업이 안 되므로(DNS 설정부족) 직접 생성해본다.
현재 podman을 이용중이기에, 내 환경 기준으로 아래와 같이 삭제 후 네트워크를 설정해주는 커맨드를 수행시켰다
// 네트워크 생성
podman network create my-network
// 가진 컨테이너 전체 조회
podamn ps -a
// 특정 컨테이너 삭제
podman ps {컨테이너ID1}
podman ps {컨테이너ID2}
// 컨테이너 두 개를 같은 네트워크로 엮어서 실행
podman run -dit --name ubuntu-server1 --cap-add=NET_RAW --network my-network ubuntu:latest
podman run -dit --name ubuntu-server2 --cap-add=NET_RAW --network my-network ubuntu:latest
각 컨테이너 내부의 Inspect를 살펴보면 IP가 순차적으로 할당된 것을 확인해본다. network도 보면 설정해놓은 그룹으로 묶여있다.
네트워크를 엮어주었으니, 이제 한쪽 서버에서 다른 서버로 ping이 제대로 수신되는지 살펴보면 된다
// server1 접속
podman exec -it ubuntu-server1 sh
// ping 패키지 설치
apt update
apt install -y iputils-ping
// ping 테스트수행
ping ubuntu-server2
통신되는 것을 확인할 수 있다.