Post

Docker - 도커 네트워크

시작하세요! 도커/쿠버네티스 책 정리글입니다.

📖 도커 네트워크

컨테이너 내부에서 ifconfig을 입력하면 eth0과 lo 네트워크를 가지고 있는 것을 확인할 수 있습니다.

도커는 컨테이너에 내부 IP를 순차적으로 할당하고, 이 IP는 컨테이너를 재시작 할 때마다 변경됩니다.

이 IP들은 내부 망에서만 쓸 수 있기에 외부와 연결을 허용할 수 있게끔 바꿔주는 방법이 필요합니다.

각 컨테이너는 시작될 때 도커 엔진이 veth라는 이름의 네트워크 인터페이스를 생성하고 이를 통해 외부와 통신할 수 있게 도와줍니다.

도커가 설치된 호스트에서 ipconfig이나 ifconfig으로 네트워크들을 확인할 수 있습니다.

그러면 veth로 시작하는 인터페이스들이 있는데 이것들은 각 컨테이너의 eth()와 연결되어있습니다.

veth 인터페이스 뿐만 아니라 docker0라는 브리지도 존재하는데 각 veth 인터페이스와 바인딩 되어 호스트의 eth0인터페이스와 이어주는 역할을 합니다.

그렇기에 다음과 같은 구조를 가집니다.

1
2
3
의존성
      
도커 컨테이너내부[eth0, lo] -> 도커 컨테이너 외부, 호스트의[veth0] -> 호스트의[docker0] -> 호스트의[eth0]

📖 도커 네트워크 기능

docker0 브리지를 통해 외부와 통신할 수 있지만, 사용자의 선택에 따라 여러 네트워크 드라이브를 쓸 수 있다고 합니다.

  • 브리지(bridge)
  • 호스트(host)
  • 논(none)
  • 컨테이너(container)
  • 오버레이(overlay)

가 있습니다.

```docker network ls`를 통해 도커에서 기본적으로 쓸 수 있는 네트워크를 확인할 수 있습니다.

1
2
3
4
5
# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
31a51219ee6e   bridge    bridge    local
9c37ea44edae   host      host      local
5db3d1df48b5   none      null      local

브리지 네트워크는 컨테이너를 생성할때 자동으로 연결되는 docker0 브리지를 활용하도록 설정되어 있습니다.

이 네트워크는 172.17.0.x IP대역을 순차적으로 할당합니다.

1
docker network inspect bridge

위 명령어를 통해 네트워크에 대한 정보를 확인할 수 있습니다.

그 결과 서브넷은 172.17.0.0/16, 게이트웨이는 172.17.0.1로 설정되어 있는것을 확인할 수 있습니다.

그리고 밑으로 내리다보면 Containers항목에서 해당 네트워크를 사용중인 컨테이너 목록을 확인할 수 있습니다.

브리지 네트워크

docker0의 브리지가 아닌 사용자 정의 브리지를 새로 생성해 컨테이너에 연결하는 네트워크 구조입니다.

컨테이너는 연결된 브리지를 통해 외부와 통신할 수 있습니다.

다음 명령어를 통해 새로운 브리지 네트워크를 생성할 수 있습니다.

1
2
# docker network create --driver bridge kmsbridge
537abe5b09fa282ab9becdb7c8140916be1ebe33906622e14a2b4e01ad4f5938

그 다음 docker run 또는 create 명령어에 --net 옵션의 값을 설정하여 컨테이너가 해당 네트워크를 사용할 수 있게 설정할 수 있습니다.

1
2
3
4
5
6
docker run -i -t --name network_bridge_container \
--net kmsbridge \
ubuntu:14.04

# 접속후
ifconfig

172.18대역의 내부 IP가 할당되었습니다.

이렇게 생성된 사용자 정의 네트워크는 유동적으로 붙였다, 떼었다 할 수 있다고 합니다.

1
2
docker network disconnect kmsbridge network_bridge_container
docker network connect kmsbridge network_bridge_container

논 네트워크, 호스트 네트워크 등과 같은 네트워크 모드에는 이렇게 붙였다 떼는 명령어를 쓸 수 없습니다. 브리지 네트워크 또는 오버레이 네트워크와 같이 특정 IP 대역을 갖는 네트워크 모드에만 사용할 수 있습니다.

만약 자동으로 설정된 네트워크가 아닌, 여러 정보를 임의로 설정하고 싶다면 다음과 같은 옵션을 설정할 수 있습니다.

1
2
3
4
5
docker network create --driver=bridge \
--subnet=172.72.0.0/16 \
--ip-range=172.72.0.0/24 \
--gateway=172.72.0.1 \
my_custom_network

호스트 네트워크

호스트 네트워크로 설정하면 말 그대로 호스트의 네트워크를 그대로 쓸 수 있습니다.

별도의 생성 없이 host라는 이름의 네트워크를 사용합니다.

1
2
3
4
5
6
docker run -i -t --name network_host \
--net host \
ubuntu:14.04

# 접속 후
ifconfig

접속 후 확인하면 호스트의 네트워크 환경과 같다는 것을 확인할 수 있습니다.

별도의 포트 포워드 없이 외부에서 바로 접근이 가능합니다.

예를 들어 호스트 모드를 쓰는 컨테이너에 tomcat를 구동한다면 호스트의 localhost:8080으로 접근이 가능합니다.

논 네트워크

말 그대로 아무런 네트워크를 사용하지 않습니다.

1
2
3
4
5
6
docker run -i -t --name none_network_container \
--net none \
ubuntu:14.04

# 접속 후
ifconfig

네트워크를 확인해보면 로컬호스트를 나타내는 lo 외에는 존재하지 않는 것을 확인할 수 있습니다.

컨테이너 네트워크

--net옵션으로 container를 입력하면 다른 컨테이너의 네트워크 환경을 공유할 수 있습니다.

대표적으로 내부IP, 네트워크 인터페이스의 맥(MAC) 주소 등입니다.

1
docker run -i -t -d --name network_container_1 ubuntu:14.04
1
2
3
docker run -i -t -d --name network_container_2 \
--net container:network_container_1 \
ubuntu:14.04

이렇게 network_container_2network_container_1와 같은 네트워크를 공유하게 됩니다.

내부 IP를 할당받지 않으며 호스트에 veth로 시작하는 가상 네트워크 인터페이스도 생성되지 않습니다.

다음 명령어를 통해 확인할 수 있습니다.

1
2
3
docker exec network_container_1 ifconfig
...
docker exec network_container_2 ifconfig

브리지 네트워크와 –net-alias

브리지 타입의 네트워크와 run 명령어의 --net-alias 옵션을 함께 쓰면 특정 호스트 이름으로 컨테이너 여러 개에 접근이 가능하다고 합니다.

무슨 말인지 알기 위해서 kmsbridge 네트워크를 사용한 컨테이너 3개를 만들어봅니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1
docker run -i -t -d --name network_alias_container1 \
--net kmsbridge \
--net-alias kms727 ubuntu:14.04

# 2
docker run -i -t -d --name network_alias_container2 \
--net kmsbridge \
--net-alias kms727 ubuntu:14.04

# 3
docker run -i -t -d --name network_alias_container3 \
--net kmsbridge \
--net-alias kms727 ubuntu:14.04

# inspect 명령어로 각 컨테이너의 IP를 확인
docker inspect network_alias_container1 | grep IPAddress
>
>            "SecondaryIPAddresses": null,
            "IPAddress": "",
            "IPAddress": "172.18.0.2",

첫 번째 container의 주소가 172.18.0.2이므로 나머지 두 개 컨테이너의 주소는 172.18.0.3, 172.18.0.4여야 합니다.

세 개의 컨테이너에 접근할 컨테이너를 생성한 뒤 kms727이라는 호스트 이름으로 ping요청을 전송해 보겠습니다.

1
2
3
docker run -i -t --name network_alias_ping \
--net kmsbridge \
ubuntu:14.04

컨테이너 3개의 IP로 ping이 전송되었습니다.

라운드 로빈 방식으로 보내는 IP를 결정합니다.

도커 엔진에 내장된 DNS가 kms727이라는 호스트 이름을 --net-alias에 의해 kms727로 설정한 컨테이너로 변환하기 때문입니다.

컨테이너 IP가 변경이 되어도 도커 내장 DNS는 이를 찾아 관리합니다.

도커는 사용자가 정의한 네트워크를 관리하는 127.0.0.11의 ip를 갖는 내장 DNS서버를 가지고, 컨테이너의 ID는 DNS 서버에 kms727(위의예제)로 등록됩니다.

그리고 kmsbridge(위의 예제)에 속한 컨테이너에 kms727에 접근하면 도커 DNS서버는 라운드 로빈을 통하여 컨테이너의 IP리스트를 반환합니다.

📖 MacVLAN 네트워크

호스트의 네트워크 인터페이스 카드를 가상화해 물리 네트워크 환경을 컨테이너에 동일하게 제공하는 기술이 있습니다.

따라서 컨테이너는 물리 네트워크상에서 가상의 맥(MAC)주소를 가집니다.

이렇게 연결된 컨테이너들은 기본적으로 네트워크 장비의 IP를 할당받기 때문입니다.

실제 테스트에는 물리적인 장비가 필요하기에 여기까지만 적겠습니다.

This post is licensed under CC BY 4.0 by the author.