ㅍㅍㅋㄷ

Docker Network 구조(4) - container link 구조 본문

IT/Docker

Docker Network 구조(4) - container link 구조

클쏭 2016. 7. 11. 09:37

Docker Network 구조 (4) - Container link 구조






 web 서버 역할의 컨테이너와 DB 서버 역할의 컨테이너가 있다고 가정해 보자. 

 만약, 이 두 container 사이를 연동하고 싶을때는 어떻게 해야 할까. 

 이번 포스팅에는 container 사이 연동에 필요한 link 옵션에 대한 사용법과 동작 구조에 대해 알아보고자 한다. 




Container 연동시 link 를 사용해야 하는 이유


 사실 동일 host 상에 배포된 container 사이는 Private IP 를 이용해 통신이 가능하다. 

 아래는 host 상에 running 중인 두개의 container 이다.

 

CONTAINER ID      IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES

ca7f026ff0ad        httpd               "httpd-foreground"       55 minutes ago      Up 55 minutes       0.0.0.0:80->80/tcp       web01

17b6c5f037a9       mysql               "docker-entrypoint.sh"   About an hour ago   Up 50 minutes       0.0.0.0:3306->3306/tcp   mysql



두 컨테이너 mysql 과 web01 의 Private IP 는 아래와 같다.


root@~~# docker inspect -f "{{ .NetworkSettings.IPAddress }}" mysql

172.17.0.6

root@~~# docker inspect -f "{{ .NetworkSettings.IPAddress }}" web01

172.17.0.3



만약, web01 --> mysql (172.17.0.6) 로 IP를 기반으로 ping 을 보내면 아래와 같이 응답함을 볼 수 있다.


root@~~# docker exec -t web01 ping 172.17.0.6

PING 172.17.0.6 (172.17.0.6): 56 data bytes

64 bytes from 172.17.0.6: icmp_seq=0 ttl=64 time=0.103 ms

64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.117 ms

64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.111 ms

64 bytes from 172.17.0.6: icmp_seq=3 ttl=64 time=0.114 ms

64 bytes from 172.17.0.6: icmp_seq=4 ttl=64 time=0.111 ms

64 bytes from 172.17.0.6: icmp_seq=5 ttl=64 time=0.116 ms

...



하지만, Container 사이의 IP 기반 연동은 문제점을 안고 있다.

Container 의 IP 는 언제든 변할 수 있는 유동적인 성격을 띄고 있기 때문이다.


Container 는 일종의 Process 이므로, 언제든 생성/소멸 될 수 있음을 전제로 해야한다. 

만약 Container가 중지 되었다가 시작하면, Process가 kill 되었다가 다시 새롭게 생성되는 것과 같다. 

이때, Container 에게 부여되는 Private IP는 언제든 변할 수 있다. 


따라서, Container 사이 연동을 하려면, IP 기반의 설정은 권고되지 않는다.

그 해결 방법으로 권고 되고 있는 방법이 바로 link 옵션이다.






link를 이용한 container 연동



아래는 link 옵션을 이용해 mysql container 를 연동한 web02 container를 구동하는 명령이다.


root@~~# docker run -d --name web02 --link mysql httpd

14f6f2a16abc8660ba32004c8eff091e5a16f0ace57a3609d770f845485d103f


 docker run 을 이용해 webe02 container를 띄울때, --link 옵션을 이용해 mysql container 와 link를 맺을 것을 설정한다. 이렇게 설정하면, web02 container 는 mysql container 를 IP 가 아닌 container의 이름을 이용해 통신할 수 있다. 


root@~~# docker exec -t web02 ping mysql

PING mysql (172.17.0.6): 56 data bytes

64 bytes from 172.17.0.6: icmp_seq=0 ttl=64 time=0.096 ms

64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.091 ms

64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.104 ms

...


위와 같이 ping target을 IP가 아닌 container 이름으로 통신이 가능하다. 만약 link를 맺지 않으면, 아래와 같이 container 명으로는 통신이 불가하다.


root@~~# docker exec -t web03 ping mysql

ping: unknown host


  container 이름을 기반으로 통신을 하면, IP가 바뀐다고 해도 문제 없이 통신이 가능하겠다. 




link 연동 구조



container 가 구동되면, container 환경 중 일부는 docker daemon에 의해 자동으로 제어 된다. 

이 중 한가지가 container 내부의 domain name을 관리하는 hosts 파일이다.


link 연동이 걸린 web02 container의 hosts 파일을 살펴보자.


root@~~# docker exec -t web02 cat /etc/hosts

127.0.0.1       localhost

::1     localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.6      mysql 17b6c5f037a9

172.17.0.2      14f6f2a16abc


위와 같이 web02 container의 /etc/hosts 파일에 mysql container 의 IP 주소와 host명이 등록되어 있다. link를 걸지 않으면, 이 정보가 없다. 


만약, link가 걸린 상태에서 mysql container가 재 기동되어 IP가 바뀐다면 어떻게 될까.


root@~~# docker inspect -f "{{ .NetworkSettings.IPAddress }}" mysql        

172.17.0.6     # mysql 컨테이너의 IP가 172.17.0.6 임을 확인

root@~~# docker stop mysql          #mysql 컨테이너 중지

mysql

root@~~# docker start mysql          #mysql 컨테이너 기동

mysql

root@~~# docker inspect -f "{{ .NetworkSettings.IPAddress }}" mysql        

172.17.0.5      # mysql 컨테이너의  IP를 확인해 보니 5로 바뀌었다.

root@ip-10-10-2-240:/home/ubuntu# docker exec -t web02 cat /etc/hosts   

127.0.0.1       localhost

::1     localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.5      mysql 17b6c5f037a9            # web02의 hosts 파일 자동 갱신

172.17.0.2      14f6f2a16abc



mysql 컨테이너와 link 가 걸린 web02 컨테이너의 hosts 파일 정보가 자동으로 갱신됨을 볼 수 있다.

즉, link 옵션을 이용하면, container 의 IP 정보가 수시로 갱신될 수 있는 환경에서도 서로간 문제 없이 통신이 가능하겠다.



그렇다면, docker daemon은 어떻게 container의 hosts 파일을 자동으로 갱신할수 있을까. 

사실, container의 hosts 파일을 살펴보면 아래와 같이 dev/disk 에 의해 mount 되어 있는 것을 볼 수 있다.


root@~~# docker exec -t web02 df -h

Filesystem                                                                                        Size  Used Avail Use% Mounted on

/dev/mapper/docker-202:1-141101-af75af9f7a44dd66180fc6c1d74bd7a14a53bfe0a2aef77cbe66d41632295dec  9.8G  236M  9.0G   3% /

tmpfs                                                                                             497M     0  497M   0% /dev

tmpfs                                                                                             497M     0  497M   0% /sys/fs/cgroup

/dev/disk/by-uuid/736fad7a-387f-4420-b934-4ccbafa26d16                                            7.8G  2.1G  5.3G  28% /etc/hosts

shm                                                                                                64M     0   64M   0% /dev/shm


 이 /dev/disk/by-uuid/UUID 는 container 안에서는 확인이 되지 않는다. container 외부의 docker host 에서 연동된 것이기 때문이다. 그렇다면 docker host의 어떤 파일이 연동 된 것일까. 이것은 docker inspect 명령을 이용해 확인이 가능하다. 


root@~~# docker inspect -f "{{ .HostsPath }}" web02

/var/lib/docker/containers/14f6f2a16abc8660ba32004c8eff091e5a16f0ace57a3609d770f845485d103f/hosts



docker host 에서 실제 이 file을 열어보면 아래와 같이 container의 hosts 파일과 동일하다. 


root@~~# cat /var/lib/docker/containers/14f6f2a16abc8660ba32004c8eff091e5a16f0ace57a3609d770f845485d103f/hosts

127.0.0.1       localhost

::1     localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.5      mysql 17b6c5f037a9

172.17.0.2      14f6f2a16abc





link 방식의 한계



  container 사이에는 link 를 이용해 연동해야 동적 IP에 따른 이슈를 피할수 있다. 하지만 link 방식만으로는 여전히 한계가 있다. 

첫째로, link 옵션은 동일 docker host 에 존재하는 container 사이에서만 유효하다. 만약 다수의 docker host를 운영할 경우에 타 host에 상주하는 container 사이에는 link 옵션 이용이 불가하다. 컨테이너의 hosts 파일의 관리를 docker host가 직접 수행하기 때문이다. 


 이러한 경우, docker swarm 같은 orchestration 툴을 도입하거나 dynamic DNS 를 구축해 사용해야 한다.


 


Comments