Build once, run anywhere.

Build once, run anywhere.

maninzoo


Docker 는 Container 단위로 어플리케이션을 패키징, 배포, 실행시키는 도구이다.

이는 어플리케이션과 그것의 종속성(system binary 와 library 들)을 self-contained 단위로 격리시킴으로서 가능하다.


Virtual Machine 의 역할과 동일한 것처럼 보이는데 그렇다면 Container 와 VM 의 차이점은 무엇인가?

Docker 를 더 알아보기 전에 Virtual Machine 과 Container 를 살펴보자.


* Virtual Machine

VM은 실제 컴퓨터를 흉내낸(emulate) 것으로 hypervisor 위에서 동작한다.

하이퍼바이저는 다시 흔히 host machine 이라고 하는 실제 물리적 컴퓨터 위에서 동작한다.

host machine 의 상대 개념으로 VM 을 guest machine 이라고 부른다.


host machine 은 VM 에게 RAM, CPU, Network Adapter, Storage 등의 리소스를 제공하고 VM 은 이것을 이용하여 가상의 Kernel(OS) 과 하드웨어를 전용으로(dedicated) 구성한다.

hypervisor 는 이 가상 OS(Guest)를 실행하고 관리하는 플랫폼으로서 동작한다.


Virtual machine


하이퍼바이저가 host machine 위에서 동작한다고 했는데 정확히는 host machine 의 OS 위에서 동작한다.

따라서 VM 은 실제 물리적인 하드웨어에 직접 접근할 수 없으며 host OS 를 통해 I/O, 프로세싱 등이 수행된다.

그렇기 때문에 하드웨어 호환성이 높고( 예 : Mac 에서 Windows VM 을 실행 ) 반대로 하이퍼바이저와 하드웨어 사이에 host OS 가 존재함으로써 overhead 가 발생하고 VM 의 성능을 떨어뜨린다.


위와 같은 방식을 보통 hosted hypervisor ( 전가상화 - 예 : KVM( 이견이 있다. ), VMware Workstation, VMware Player, VirtualBox ) 라고 하고, 위 성능 이슈를 해결하기 위해 bare-metal hypervisor( 예 : XEN, Citrix Xenserver, Hyper-V, VMware ESX/ESXi ) 라는 방식이 있다.

bare-metal - 원래는 운영체제가 설치 돼 있지 않는 컴퓨터 하드웨어 를 의미.


bare-metal 이 hosted 와 다른 점은 hypervisor 가 host OS 의 개입없이 host machine 의 하드웨어와 직접 인터페이스한다는 것이다.

이를 위해 hypervisor 가 자체 device driver 를 가진다.

이는 성능과 안정성을 얻지만 하드웨어 호환성의 제약을 갖게 된다.


* Container

Container 는 VM 과 달리 자체 Kernel 을 가지거나 하드웨어 가상화를 하지 않고 operating-system-level virtualization 를 통해 각 컨테이너들이 격리된 user space 에서 host system 의 Kernel 을 공유(share)한다.

Container 는 자체 Kernel 과 하드웨어 가상화가 없기 때문에 VM 에 비해 가볍고 빠르다.


Container


다시 Docker..

Docker 는 Linux Container 기반의 오픈 소스 프로젝트이다.

하지만 Docker Hub 에 private repository 를 2개 이상( 1개는 무료 ) 생성하기 위해서는 비용을 지불해야 한다.

Docker Hub 는 Docker Image Store 이다.


* Docker 구성 요소

** Docker Client

Docker CLI(Command-line interface) 이다.

```sh

docker build 이미지명

```

** Docker Daemon

host machine 위에서 동작하며 Docker Client 가 보낸 명령을 실제 실행한다.

이미지를 빌드, 관리하고 컨테이너를 생성, 실행/중지, 배포, 관리한다.

정확히는 runtime(runc) 에 의해 컨테이너가 실행된다.

runc 는 OCI( Open Container Initiative ) 규약의 runtime 구현물이다.

OCI 는 Linux Foundation의 후원으로 Docker, CoreOS, AWS, CISCO, Facebook, Google, IBM 등이 참여하고 있는 Container format과 runtime 산업 표준을 위한 컨소시엄이다.


** Docker Engine

Docker Engine = Docker Daemon + Docker Client + Docker Daemon 과 원격에서 communicate 할 수 있는 REST API


** Dockerfile

Docker 이미지를 빌드하기 위한 실행 명령 Set 이다.

이미지의 패키징된 어플리케이션과 그 종속성이 시작될 때 실행할 프로세스와 환경 및 구조를 정의한다.


*** 작업 예

스크립트 또는 명령을 실행 - 예 : 어플리케이션 실행에 필요한 패키지나 라이브러리를 설치하고 업데이트

Port 를 expose

환경변수를 설정

파일을 복사

```docker

FROM inswave/websquare-min

LABEL maintainer="maninzoo@inswave.com"


RUN apk add --update gcc g++ make python py-pip openssh

RUN pip install Flask

RUN npm install --global node-gyp grunt-cli


RUN mkdir /app

WORKDIR /app


COPY package.json /app/

RUN yarn


COPY . /app

```

** Docker Image

Dockerfile 을 기반으로 빌드된 읽기 전용 템플릿이다.

Dockerfile 의 각 명령은 이미지에 layer 를 추가한다.

레이어는 하위 레이어에 추가되거나 대체하여 이미지 파일 시스템을 구성한다.

이 레이어가 기존에 존재하던 리눅스 기술들을 조합하여 Docker 를 가볍고 강력한 구조를 갖게 한다.

이러한 Stackable 파일 시스템을 Union File Systems 이라고 한다.


** Union File Systems

분리된 파일 시스템( 보통 branch 라고 함 )의 파일과 디렉토리들을 투명하게(transparently) 겹쳐서 만든 하나의 파일 시스템.


transparently 하다는 의미는 겹쳐진 브랜치들 안에서 동일한 경로를 갖는 디렉토리의 컨텐츠들은 merge 되어 하나의 디렉토리로 보여진다.

다시 말해 각 레이어는 개별 copy 본을 생성하지 않고 동일한 리소스에 대한 포인터를 제공한다.


특정 레이어를 수정해야 하는 경우 원본을 변경하지 않고 복사하여 해당 local 복사본을 수정한다.

이를 'copy-on-write' system 라고 하며 실제 쓰기를 허용하지 않으면서도 쓰기가 가능한 것처럼 보이고 변경된 정보를 별도로 저장하는 파일 시스템이다.


이렇기 때문에 Repository( Docker Hub )에서 pull 을 받을 때도 변경된 부분만 내려받아 최신 이미지를 유지할 수 있다.


** Data Volume

Union File System 의 단점은 원본과 변경된 정보를 합쳐서 하나의 파일 시스템으로 제공하기 때문에 브랜치의 양과 갯수가 많아질수록 성능 저하가 온다.

이를 해결하기 위해 데이터를 유니온 파일 시스템이 아닌 외부( Host 파일 시스템 )에 저장하고 이를 데이터 볼륨이라고 한다.


프로그램에 비유하자면 Docker 의 이미지는 Class, 컨테이너는 Instance 에 해당한다고 볼 수 있다.

인스턴스가 데이터를 DB 나 파일, 네트워크를 통해 외부에 저장하는 것처럼 컨테이너도 실행 관련 파일을 제외한 데이타 파일을 위해 외부 저장소를 이용한다.


이는 다수의 컨테이너가 데이타를 공유하거나( 예 : 로드밸런싱 )

여러 컨테이너가 조합되어 서비스(MicroService)를 할 수 있는 아키텍처를 제공하고

컨테이너의 삭제, 업데이트, 이동 등을 자유롭게 한다.


** Docker Container

Docker Image 로부터 Docker Container 가 빌드된다.

이미지의 읽기 전용 파일 시스템 위에 읽기/쓰기 파일 시스템을 추가해서 컨테이너를 생성한다.

이 때 OS, 어플리케이션 코드, runtime, 시스템 도구/라이브러리 등 어플리케이션 실행에 필요한 모든 것을 invisible box 로 감싼다.


컨테이너가 생성되면 네트워크 인터페이스( Veth - Virtual Ethernet device )를 생성하여 리눅스 브릿지에 연결하고 사용 가능한 IP Address 를 할당하여 컨테이너가 local host 와 통신할 수 있게 된다.


리눅스 브릿지는 리눅스 운영체제에서 지원하는 L2 스위치 를 소프트웨어적으로 구현한 네트워크 브릿지 인터페이스이다.


Docker


위에 나온 invisible box 에서 invisible 은 실제 Container가 Linux Kernel 의 namespaces, control groups 같은 기능을 조합해서 동작하는 방식을 설명하기 위한 추상적인 개념이란 의미이다.


컨테이너가 사용하는 기술들은 다음과 같다.

*** namespaces(namespace isolation)

Namespace 는 컨테이너에게 하부의 Linux system 에 대한 제한된 참조(see) 및 접근 View 를 제공한다.

컨테이너는 host system 을 공유하면서 namespace 를 통해 컨테이너 상호 간 격리된다.


아래와 같은 네임스페이스 유형이 있다.

각 컨테이너에 개별적으로 적용된다.


**** NET

시스템 네트워크 자원( Network devices, IP addresses, IP routing tables, port number 등 )에 대한 View 를 제공한다.


**** PID( Process ID )

모든 프로세스의 조상인 init(PID 1) 프로세스를 독립적으로 갖는다.

컨테이너가 참조하고 interact 할 수 있는 프로세스들의 Scoped View 를 제공한다.


**** MNT

시스템의 'mounts' 에 대한 격리된 view 를 제공한다.


**** UTS( UNIX Timesharing System )

컨테이너가 다른 컨테이너와 host system 과 독립적인 시스템 identifier( hostname, domainname 등 ) 가져서 프로세스가 이를 식별하게 한다.


**** IPC( InterProcess Communication )

각 컨테이너 내부에서 실행되는 프로세스 간 IPC 리소스를 격리한다.


**** USER

각 컨테이너 내의 사용자를 격리한다.

컨테이너에게 host system 과 다른 uid (user ID) 와 gid (group ID) 범위의 View 를 제공한다.

따라서 프로세스의 uid 와 gid 가 USER Namespace 안과 밖이 다를 수 있고 host system 의 일반 사용자가 컨테이너 내에서는 root 권한을 가질 수 있다.


*** cgroups( control groups )

Google 에서 개발, 리눅스 커널 2.6.24 부터 지원.

namespaces 가 System 에 대한 Scoped View 제공한다면 cgroups 는 프로세스의 Resource( CPU, Memory, Disk I/O, network 등 ) 사용에 대한 분리, 제한과 우선순위, 모니터링 등을 담당한다.


다음과 같은 기능을 제공한다.

**** Resource limiting

프로세스 그룹이 사용할 메모리와 파일 시스템 캐시 등에 대한 제한.


**** Prioritization

프로세스 그룹 간 디스크 입출력과 CPU 이용에 대한 우선순위를 설정.


**** Accounting

프로세스 그룹의 자원 사용량을 측정.


**** Control

프로세스에 대한 checkpoint 를 설정하고 리스타트 할 수 있다.


jeonbyungjin's profile image

jeonbyungjin

2018-03-12 17:10

Read more posts by this author