티스토리 뷰

출처: http://blog.neonkid.xyz/87

Docker 네트워크

리눅스 컨테이너에서 네트워크를 어떻게 사용할 수 있을까요? 여러분들은 서버를 구축할 때, 서비스하기 전, 사전 조사를 진행하는 것 중에 하나는 네트워크 구성이 어떻게 되어 있는지부터 확인합니다. 사설 IP로 구성이 되어 있는지 외부로 어떻게 빠져나가는 지 등.


만약, 방화벽이 설정되어 있고, 관리자가 나라면, 방화벽에서 서비스할 포트 번호를 열어주면 되고, 그것이 아니라면, 그냥 바로 서비스할 수도 있습니다. 일반 가정의 공유기를 사용한다면, 포트 포워딩을 사용하거나 UPnP 기능을 사용하여 서비스 할 수도 있습니다.


그렇다면 Docker에서는 어떻게 네트워크를 구성할까요?


Bash

$ ifconfig docker0



처음 Docker를 설치한 후, 명령어를 입력하면, docker0에 인터페이스에 대한 IP 주소와 서브넷 마스크 값이 출력하게 됩니다. 지금 현재는 제가 원하는 값으로 입력되어 있는 상태입니다. 여기서 docker0 인터페이스는 여러분 서버에 실제로 있는 이더넷 카드가 아닌 가상의 인터페이스입니다.


VMware를 설치하여 사용할 때도 vmnet0이라는 가상의 인터페이스가 생깁니다. 이처럼 Docker에도 가상의 네트워크 인터페이스를 생성하며 서로가 통신을 할 수 있도록 네트워크 인프라를 구축할 수 있습니다.


참고로, 이 IP는 docker0라는 인터페이스나 다른 컨테이너에서 DHCP 데몬을 통해 자동으로 IP를 구성하는 것이 아닌, Docker 내부 로직에 의해 할당이 내려진s IP 주소입니다. 


그런데, 의문인 것은 내가 아직 컨테이너를 생성하지 않았음에도 불구하고, 이 인터페이스가 자동으로 생성된다는 것입니다. 물론, VMware 등의 가상 머신도 가상 머신을 생성하지 않았는데, 인터페이스가 생성이 되는데 왜 그런 것일까요?


docker0 인터페이스의 경우, IP 주소까지 이미 할당이 된 상태입니다. docker0 인터페이스는 현재 브릿지 인터페이스입니다.




docker0 interface

브릿지 상태인 docker0 인터페이스는 어떻게 통신하도록 한 것일까요?


Bash

$ brctl show



brctl 명령어를 사용하여, 확인해보면, docker0 인터페이스는 브릿지 인터페이스라는 것을 확인할 수 있습니다. 브릿지 인터페이스는 말그대로 이어주는 다리입니다. Docker 컨테이너와 나의 실제 서버를 이어주는 끈이라고 할 수 있죠.


bridge는 네트워크 인터페이스 특성상 L2에 속합니다. 그래서, 만약 컨테이너가 하나 생성되면, 이 bridge의 interface에 container의 interface가 하나씩 binding 되는 형태입니다. 그림으로 한 번 보도록 하겠습니다.


우리가 일반적으로 볼 수 있는 스위치의 모습입니다. 여기에 만약 실제 서버를 연결하려면 어떻게 해야할까요? 여러분들이 직접 UTP 선을 따서, 서버의 NIC 인터페이스 카드에 연결해야 합니다. bridge 인터페이스가 바로 이런 구조입니다. 스위치가 docker0의 bridge 인터페이스라 가정하고, 새로운 컨테이너가 생성되면, 그 컨테이너 인터페이스랑 bridge 인터페이스랑 물려지는 것입니다.


그럼 brctl 명령어로 봤을 때, 저의 서버에는 지금 컨테이너가 2대 운영 중에 있으며 현재 2 컨테이너가 활성화 되고 있음을 알려주고 있습니다.




docker0 interface 주무르기

그럼 이제 인터페이스를 여러분들이 한 번 주물러보도록 하죠. bridge 인터페이스가 스위치라고 봤을 때, Docker는 각각, bridge interface와 container interface들이 IP를 가지고 있고, 이를 가지고 옹신 할 것입니다.


그런데, docker0 인터페이스에 물려 있는 네트워크 주소는 어떻게 관리할까요?


아마 여러분들이 기본적으로 docker를 설치하자마자 받는 네트워크 주소 범위는 172.17.42.1/16으로 되어 있을 것입니다. 만약 여러분들이 직접 서브넷팅하여, 주소 범위를 바꾸고 싶다면, 아래와 같은 절차를 밟으시면 됩니다.


Bash

# service docker status


만약 Docker 서비스가 실행 중이면, Docker 데몬을 종료하도록 합시다.


Bash

# service stop docker


Active 상태가 inactive 상태이면, Docker 데몬이 종료된 것입니다.


Docker 데몬이 종료되었으면, 이제 인터페이스를 내려보도록 합시다.


Bash

# ip link set dev docker0 down

Bash

# ip link


docker0 인터페이스가 아무런 상태도 나타나지 않으면 DOWN 상태입니다.


Bash

# ip addr


ip addr 명령어를 이용해, 현재 docker0 인터페이스에 있는 IP 정보를 조회합니다. IP가 없다면, 위와 같이 아무것도 뜨지 않을 것이고, 만약 IP가 있다면 IP 주소와 정보가 나타날 것입니다. IP 주소 정보가 있는 경우, ip addr del 명령어를 이용해 삭제하시면 됩니다.


Bash

# ip addr add 192.168.225.0/24 dev docker0

여러분들이 원하는 주소 범위를 적어주시면 됩니다. 저는 IP가 그렇게 많이 필요하지 않고, 예비로 쓸 IP도 적기 떄문에, 적당히 0~255까지만 할당하도록 하겠습니다. 만약 1000개 이상의 컨테이너를 생성해 쓰시려고 한다면, 이보다 더 큰 IP 주소 범위를 사용하셔야 합니다.


Bash

# ip addr 


ip addr 명령어를 통해 확인해보면, 제가 입력한 IP가 들어간 것을 알 수 있습니다.



이제 남은 일은 다시 인터페이스를 UP 상태로 돌려놓고, docker 데몬을 띄우는 것입니다.


Bash

# ip link set dev docker0 up


docker0 인터페이스 상태가 다시 UP 되었습니다.


마지막으로, 설정해야 할 파일이 한 가지 남았습니다. 그건 바로, docker 자체 설정인데요. 이 설정값이 바뀌지 않으면, 서버가 재부팅되거나 Docker 데몬이 재시작됐을 때, 해당 설정값을 다시 불러오게 되므로, 여태까지 우리가 설정했던 네트워크 주소값들이 전부 다시 Reset 되기 때문에, 이 파일도 마지막으로 수정해주셔야 합니다.


Bash

# vim /etc/default/docker


정확히 21번째 줄에서 자신이 설정했던 네트워크 주소 범위를 입력해주면 됩니다.


이제 Docker 서비스를 다시 시작하면 됩니다.


Bash

# service docker start
Bash

# ifconfig docker0


그럼 위와 같이 Bridge interface IP 주소가 내가 설정한 범위 내로 바뀐 것을 확인할 수 있습니다. 추가로, 컨테이너에 있는 IP 변경 사항도 확인하실 수 있습니다.


Bash

# docker exec [Container ID] ifconfig


위와 같이 주소 범위가 바뀐 것을 확인하실 수 있습니다. 




Docker container의 외부 네트워크 사용

자 IP 주소를 새로 구성하였는데, 어라? 레포지터리에 도커 컨테이너가 리눅스 업데이트를 하지 못하고 있습니다. 왜 그럴까요?


Docker 컨테이너는 NAT 기술을 사용하여, 외부 네트워크로 통신합니다. 여러분들이 사용하는 실제 서버에 물려 있는 인터넷 선은 하나 밖에 제공되어 있지 않고, 그 선 한 개를 통해서 나가야 하기 때문에, 우리는 Linux의 iptables를 이용하여, 해당 브릿지 인터페이스에 MASQUERADE 기능을 부여하거나 SNAT 값을 줘야합니다.


MASQUERADE는 NAT 기술의 한 종류로, 내부 네트워크에서 외부 네트워크로 패킷을 수신/전송하는 데 사용하는 네트워크 기술입니다. 자세한 기술의 내용을 보시려면 아래 버튼을 눌러 참고하세요.


IP MASQUERADE


먼저 iptables를 사용하여, 현재 네트워크 상태를 확인해봅시다.


Bash

# iptables -t nat -L


테이블에 어떤 정보도 없습니다. 이처럼 테이블에 NAT 정보가 없으면, 내부 네트워크에서 외부 네트워크로 통신할 수 없으므로, 우리는 이 테이블에 값을 입력해야 합니다.

하나씩 테이블에 값을 넣어보도록 하겠습니다.


Bash

# iptables -t nat -A PREROUTING -d 0.0.0.0/0 -m addrtype --dst-type LOCAL -j DOCKER
Bash

# iptables -t nat -A OUTPUT -m addrtype --dst-type LOCAL -j DOCKER
Bash

# iptables -t nat -A POSTROUTING -s 192.168.225.0/24 -j MASQUERADE



사실, 단순히 Repository의 프로그램을 다운로드 받기 위해서 ,사용하는 것이라면 MASQUERADE만 줘도, 가능은 하지만, 여러분들이 만약에라도 Docker 컨테이너에서 웹 서비스 등의 서비스를 할 수도 있끼 때문에 이를 먼저 다루고, 다음에 Docker 컨테이너에서 어떻게 서비스를 하는지에 대해 자세히 다루도록 하겠습니다.


일단 첫 번째부터 보면, 첫 번째는 PREROUTING CHAIN입니다. 이 테이블은 Docker 컨테이너에 들어오는 패킷이 PREROUTING CHAIN을 통해 Docker CHAIN으로 전달하게 됩니다. 한 마디로 여기서 걸러지는 것이죠.


반대로 Docker 컨테이너에서 외부로 나갈 떄는 MASQUERADE를 통해 나가게 됩니다.



여기까지 Docker 네트워크 구성과 설정을 모두 다뤄봤습니다. iptables나 NAT에 대한 지식이 부족하다면, 이 내용이 전혀 이해가 안되실 수 있습니다. 서버의 네트워크 구성은 반드시 기본적인 네트워크 개념을 숙지하신 후, 다루시는 것을 추천합니다.



댓글
공지사항
최근에 올라온 글
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함