도커(Docker)의 동작구조

Docker의 코어 기능이 어떤 구조로 동작하는지 알아보겠습니다. 🙂 

컨테이너를 구분하는 구조(namespace)


도커는 컨테이너라는 독립된 환경을 만들고 이를 나누어 애플리케이션 실행 환경을 만듭니다. 이처럼 컨테이너를 나눌 때 리눅스 커널의 namespace 기능을 사용합니다.
이름이 어떤 namespace에 속하느냐에 따라 달라지며 같은 이름이더라도 다른 namespace라면 다른 존재로 인식됩니다.

리눅스 커널의 namespace 기능은 리눅스 오브젝트에 이름 붙이는 것을 통하여
다음 6가지 독립된 환경을 구축할 수 있습니다.

  • PID namespace
    • 리눅스에서 각 프로세스에 할당된 고유한 ID를 의미
    • PID와 프로세스를 분리
  • Network namespace
    • 네트워크 디바이스, IP 주소, 포트번호, 라우팅 테이블, 필터링 테이블 등 네트워크 리소스를 namespace별로 할당 가능
    • 이 기능을 통해 호스트OS 위에서 사용 중인 포트가 있어도 컨테어너 안에서 같은 번호의 포트 사용 가능
  • UID namespace
    • UID(User), GID(Group)를 namespace별로 독립하여 가질 수 있음
    • namespace 안에서 호스트OS상의 UID 및 GID와 서로 연결되어 namespace 안과 밖에서 서로 다른 UID 및 GID를 가질 수 있음
  • MOUNT namespace
    • 리눅스에서 파일 시스템을 사용하기 위해서 마운트가 필요
    • 마운트란 컴퓨터에 접속한 기기와 기억장치를 OS에 인식시키는 것
    • MOUNT namespace는 마운트를 조작하여 namespace 내에 파일 시스템 트리를 만듦
  • UTS namespace
    • namespace별로 호스트명과 도메인명을 독자적으로 가질 수 있음
  • IPC namespace
    • 프로세스 간의 통신(IPC) 오브젝트를 namespac별로 가질 수 있음
    • IPC는 공유메모리와 세마포어 및 메세지 큐의 System V 프로세스 간 통신 오브젝트
    • 세마포어란 프로세스에 필요한 자원 관리에 이용되는 배타 제어방식이며, 메시지 큐는 여러 프로세스 사이에서 비동기 통신이 이루어질 때 사용하는 큐잉 방식

 

리소스 관리 구조(cgroup)


도커는 여러 컨테이너에서 물리 머신의 리소스를 공유하여 사용합니다.
이때 리눅스 커널 기능인 cgroup을 이용하여 리소스 할당 등의 관리를 수행합니다.
리눅스에서는 프로그램을 ‘프로세스’로 실행하며 이는 하나 이상의 thread 단위로 동작합니다. cgroup은 프로세스 및 thread를 그룹화하여 이를 관리하는 기능입니다.
이를 통해 호스트OS의 CPU, 메모리와 같은 리소스를 그룹별로 제한할 수 있습니다.
cgroup으로 컨테이너 내의 프로세스 리소스를 관리함으로써, 한 컨테이너가 같은 호스트OS상에서 동작하는 다른 컨테이너에 영향을 주는 일을 막을 수 있습니다.

네트워크 구성(가상 bridge 및 가상 NIC)


도커의 컨테이너는 서버의 물리 NIC과 별도로 컨테이너마다 가상 NIC가 할당되어 있습니다. 또한 이러한 가상 NIC는 docker0이라는 가상 bridge에 접속하여 컨테이너끼리 통신합니다.
docker0은 Docker 데몬을 기동한 후에 생성되며 172.17.42.1 주소가 할당됩니다.
도커에서 컨테이너를 구동하면 컨테이너에 172.17.0.0/16 subnet mask를 가진 private IP Address가 eth0에 자동으로 할당됩니다.
eth0에는 호스트OS에 생성된 가상NIC(vethxxx)가 페어로 할당됩니다.
veth는 OSI 7계층 Layer 2의 가상 네트워크 인터페이스로서 페어된 NIC끼리 터널링 통신을 수행합니다.

  • 도커 컨테이너 간의 통신
    • 동일한 호스트상의 도커 컨테이너는 구동 시 private Address가 자동으로 할당되므로 컨테이너끼리 통신하기 위해 ‘링크 기능’ 사용
    • 한 호스트 상에 여러 컨테이너가 동작하는 경우, alias명을 통해 서로 다른 컨테이너 접속 가능
  • 도커 컨테이너와 외부 네트워크 통신
    • 도커 컨테이너가 외부 네트워크와 통신할 때에는 가상 bridge docker0와 호스트OS의 물리 NIC에서 패킷을 전송해야 함(이 때 NAPT 기능 사용하여 접속)
    • NAPT(Network Address Port Translation)
      • 하나의 IP Address를 여러 컴퓨터에서 공유하는 기술로서 IP Address와 포트 번호를 변환하는 기능
      • private IP와 global IP Address를 상호 변환하는 기술로, TCP 및 UDP 포트 번호를 변환하기 때문에 여러 머신에서 한 global IP Address로 접속 가능
      • 도커에서는 리눅스의 iptables를 NAPT에 사용하고 있음

 

도커 이미지의 데이터 관리 구조


어떤 데이터를 복사해야 할 경우, 빈공간의 확보가 필요합니다. 하지만 복사한 데이터가 변경되면 무용지물이 되고 맙니다.
데이터를 바로 복사하지 않고 원본을 그대로 참조하여 원본 또는 복사본 데이터 중 하나가 변경 될 때 빈 공간을 확보하여 데이터를 복사하는 구조를 ‘Copy on Write’라 합니다. 도커에서는 이 방식으로 컨테이너 이미지의 변경을 관리합니다.
도커 이미지는 OS와 미들웨어의 디렉터리를 포함하기 때문에 용량이 매우 큽니다.
때문에 용량이 한정된 물리 스토리지 영역을 효율적으로 사용하기 위하여 Copy on Write로 이미지 변경을 관리합니다.

  • Btrfs
    • 오라클에서 2007년 발표한 리눅스용 Copy on Write 파일 시스템
  • AUFS
    • 서로 다른 파일 시스템의 파일과 디렉터리를 중첩하여 하나의 파일트리를 구성할 수 있는 파일 시스템
  • Device Mapper
    • 리눅스 커널 2.6에 탑재된 리눅스 블록 디바이스 드라이버와 이를 지원하는 라이브러리
    • 파일 시스템의 블록 I/O와 디바이스 매핑을 관리
  • overlay
    • Union filesystem의 하나로 파일 시스템에 또 다른 파일 시스템을 합치는 구조

 

About the author

bogn

View all posts

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다