Docker는 가상화 컨테이너에 Application 배포를 자동화시켜주는 오픈소스 엔진으로 마이크로서비스 아키텍처와 함께 각광받고 있는 엔진이다

서버 환경이 전통적인 온프레미스 환경에서 클라우드로 바뀌면서 가상서버를 손쉽게 늘리고 관리할 수 있게 되었지만 이에 따른 배포는 불편한 점이었다

Docker가 제공하는 경량화된 가상화 컨테이너 기술은 환경의 배포와 확장을 하는데 엄청난 이점을 제공해준다.


Docker 엔진은 다음과 같은 구성요소들로 이루어져 있다.


<출처 : https://docs.docker.com/engine/docker-overview/#docker-engine>


Docker 는 Container 와 Image 라는 개념으로 구성되며, Network 및 Data 와 같은 리소스들을 각 엔진별로 다룰 수 있고 이를 위한 인터페이스로 Docker 서버에서 REST API 를 제공한다.


 * Image

Docker의 이미지는 Docker 컨테이너를 만들기 위한 Read Only Layer이다. 각 Image 들은 Docker 엔진 위에서 다른 Image 들을 Base로 하는 Image Layer 를 구성하고 있기 때문에 여러 Image들을 재사용해서 새로운 Image를 빌드하는 것이 가능하다.


 * Container

컨테이너는 실행가능한 Docker 이미지를 말한다. 각 Container 들은 Host 및 다른 Container 들과 완전히 격리된 공간을 구성하며 Image 를 Base로 한 환경에서 격리된 공간의 리소스에 접근할 수 있게 구성되어 있다.


여기서 중요한 사실은, Container Hypervisor와 완전히 다른 개념이라는 것이다.


가상화를 목표한 다는점은 같지만, 하이퍼바이저가 OS 및 커널이 통째로 가상화되는 반면, Container FileSystem의 가상화만 이루어진다. Container Host PC의 커널을 공유하고, 따라서 init(1) 등의 프로세스가 떠있을 필요가 없으며, 가상화 프로그램과는 다르게 적은 메모리 사용량, 적은 Overhead를 보인다

많은 벤치마크 결과가 입증하듯 Container Host PC의 자원을 격리(Isolation)된 상태 그대로 활용하기 때문에 VM에 비해 성능 저하가 눈에 띄게 적다.



여기서 Docker 가상화를 위한 다음과 같은 기술들을 이해하는 것이 중요하다.


-  Namespace : 리눅스에서는 접속한 게스트 별로 독립적인 공간을 제공하고 서로가 충돌하지 않도록 리소스를 격리시키는 namespace 기능을 커널에 내장하고 있다. 일반적으로 Linux 커널에서 지원하는 6가지 namespace 는 다음과 같다.


(1)  Mnt(파일 시스템 마운트) : 호스트 파일시스템에 구애받지 않고 독립적으로 파일시스템을 마운트하거나 언마운트 가능


(2)  Pid(프로세스) : 독립적인 프로세스 공간을 할당


(3)  Net(네트워크) : namespace 간에 network 충돌을 방지 (중복 포트 바인딩 등을 방지)


(4)  Ipc(System IPC) : 프로세스 간의 독립적인 통신통로 할당


(5)  Uts(hostname) : 독립적인 hostname 할당


(6)  User(UID) : 독립적인 사용자 할당

 

namespace 를 지원하는 리눅스 커널을 사용한다면 다음 명령어를 통해 바로 namespace를 만들 수 있다.


> Sudo unshared –fork –pid –mount-proc bash


위와 같은 명령어를 통해 별도의 PID Namespace를 할당할 수 있고, bash pid 1로 할당할 수 있다. 독립된 공간을 할당한 뒤에는 nsenter 라는 명령어를 통해 접근할 수 있으며 Docker에서는 이 역할을 docker exec 라는 명령어가 대신한다.


 네트워크 관점의 namespace 에서 트래픽은 network namespace로 분산한 만큼 방화벽 룰셋이 줄어들며, 결과적으로 지연시간도 줄어든다. Network namespace에 해당하는 conntrack slab allocator를 통해 관리되는데 이 conntrack 도 줄어들게 되므로 자원의 효율이 보장된다.


- Cgroup(Control Groups) : Control Groups 는 자원에 대한 제어를 가능하게 해주는 리눅스 커널의 기능이다. Cgroup은 다음과 같은 리소스들을 제어할 수 있다.


(1)   메모리


(2)   CPU


(3)   I/O


(4)   네트워크


(5)   Device 노드(/dev/)


 만들어진 실행 프로세스들의 그룹은 계층구조를 가지며 시스템의 자원할당, 우선순위 지정, 거부, 관리, 모니터링 등의 제어기능을 수행하므로 자원의 효율성을 향상시킨다. 단순 그루핑을 제공하므로 실제 자원 분배를 위해서는 각 자원마다 해당하는 서브시스템이 필요하다.


- Union File System : Union FS 는 Docker 가 관리하는 각 Layer에서 각 컨테이너가 이용할 수 있는 독립된 파일 시스템 블록을 말한다. 이 FileSystem 은 리눅스 커널이 제공하는 것이 아니기 때문에 Linux 의 종류별로 다른 형태를 제공한다. 가령 Ubuntu 계열의 Linux 는 AUFS 라는 형태의 Storage Backend 를 제공하지만 Redhat 계열은 그렇지 않다.


- Container Format : Docker Engine 을 구성하는 핵심 기술 스택인 namespace, cgroup, UFS 는 컨테이너를 이용하기 위한 Container Wrapper 를 갖고 있으며 이를 맞추기 위한 Container Format 을 관리하게 된다. Default Container 는 libcontainer 를 이용한다.



+ Recent posts