개인적으로 가상화 공부를 위해 정리한 내용들입니다.
함께 공부하자는 취지로 내용을 공유합니다.
1. 도커란?
도커는 컨테이너 기반의 오픈소스 가상화 플랫폼입니다.
컨테이너라 하면 배에 실는 네모난 화물 수송용 박스를 생각할 수 있는데 각각의 컨테이너 안에는 옷, 신발, 전자제품, 술, 과일등 다양한 화물을 넣을 수 있고 규격화되어 컨테이너선이나 트레일러등 다양한 운송수단으로 쉽게 옮길 수 있습니다.
서버에서 이야기하는 컨테이너도 이와 비슷한데 다양한 프로그램, 실행환경을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 해줍니다. 백엔드 프로그램, 데이터베이스 서버, 메시지 큐 등 어떤 프로그램도 컨테이너로 추상화할 수 있고 조립PC, AWS, Azure, Google cloud등 어디에서든 실행할 수 있습니다.
컨테이너를 가장 잘 사용하고 있는 기업은 구글인데 2014년 발표 에 따르면 구글은 모든 서비스들이 컨테이너로 동작하고 매주 20억 개의 컨테이너를 구동 한다고 합니다.
(1) 컨테이너
컨테이너는 격리된 공간에서 프로세스가 동작하는 기술입니다.
가상화 기술의 하나지만 기존방식과는 차이가 있습니다.
기존의 가상화 방식은 주로 OS를 가상화하였습니다.
우리에게 익숙한 VMware나 VirtualBox같은 가상머신은 호스트 OS위에 게스트 OS 전체를 가상화하여 사용하는 방식입니다. 이 방식은 여러가지 OS를 가상화(리눅스에서 윈도우를 돌린다던가) 할 수 있고 비교적 사용법이 간단하지만 무겁고 느려서 운영환경에선 사용할 수 없었습니다.
이러한 상황을 개선하기 위해 CPU의 가상화 기술(HVM)을 이용한 KVM(Kernel-based Virtual Machine)과 반가상화(Paravirtualization)방식의 Xen이 등장합니다. 이러한 방식은 게스트 OS가 필요하긴 하지만 전체OS를 가상화하는 방식이 아니였기 때문에 호스트형 가상화 방식에 비해 성능이 향상되었습니다. 이러한 기술들은 OpenStack이나 AWS, Rackspace같은 클라우드 서비스에서 가상 컴퓨팅 기술의 기반이 되었습니다.
전가상화든 반가상화든 추가적인 OS를 설치하여 가상화하는 방법은 어쨋든 성능문제가 있었고 이를 개선하기 위해 프로세스를 격리 하는 방식이 등장합니다.
리눅스에서는 이 방식을 리눅스 컨테이너라고 하고 단순히 프로세스를 격리시키기 때문에 가볍고 빠르게 동작합니다. CPU나 메모리는 딱 프로세스가 필요한 만큼만 추가로 사용하고 성능적으로도 거어의 손실이 없습니다.
하나의 서버에 여러개의 컨테이너를 실행하면 서로 영향을 미치지 않고 독립적으로 실행되어 마치 가벼운 VM(Virtual Machine)을 사용하는 느낌을 줍니다. 실행중인 컨테이너에 접속하여 명령어를 입력할 수 있고 apt-get이나 yum으로 패키지를 설치할 수 있으며 사용자도 추가하고 여러개의 프로세스를 백그라운드로 실행할 수도 있습니다. CPU나 메모리 사용량을 제한할 수 있고 호스트의 특정 포트와 연결하거나 호스트의 특정 디렉토리를 내부 디렉토리인 것처럼 사용할 수도 있습니다.
새로운 컨터이너를 만드는데 걸리는 시간은 겨우 1-2초로 가상머신과 비교도 할 수 없이 빠릅니다.
이러한 컨테이너라는 개념은 도커가 처음 만든 것이 아닙니다.
도커가 등장하기 이전에, 프로세스를 격리하는 방법으로 리눅스에서는 cgroups(control groups)와 namespace를 이용한 LXC(Linux Container)가 있었고 FreeBSD에선 Jail, Solaris에서는 Solaris Zones이라는 기술이 있었습니다.
구글에서는 고급 기술자들이 직접 컨테이너 기술을 만들어 사용하였고 lmctfy(Let Me Contain That For You)라는 오픈소스 컨테이너 기술을 공개했지만 성공하진 못했습니다.
도커는 LXC를 기반으로 시작해서 0.9버전에서는 자체적인 libcontainer 기술을 사용하였고 추후 runC기술에 합쳐졌습니다.
(2) 도커 이미지
도커에서 가장 중요한 개념은 컨테이너와 함께 이미지라는 개념입니다.
이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있는 것으로 상태값을 가지지 않고 변하지 않습니다(Immutable). 컨테이너는 이미지를 실행한 상태라고 볼 수 있고 추가되거나 변하는 값은 컨테이너에 저장됩니다. 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 컨테이너가 삭제되더라도 이미지는 변하지 않고 그대로 남아있습니다.
ubuntu이미지는 ubuntu를 실행하기 위한 모든 파일을 가지고 있고 MySQL이미지는 debian을 기반으로 MySQL을 실행하는데 필요한 파일과 실행 명령어, 포트 정보등을 가지고 있습니다. 좀 더 복잡한 예로 Gitlab 이미지는 centos를 기반으로 ruby, go, database, redis, gitlab source, nginx등을 가지고 있습니다.
말그대로 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 더 이상 의존성 파일을 컴파일하고 이것저것 설치할 필요가 없습니다. 이제 새로운 서버가 추가되면 미리 만들어 놓은 이미지를 다운받고 컨테이너를 생성만 하면 됩니다. 한 서버에 여러개의 컨테이너를 실행할 수 있고, 수십, 수백, 수천대의 서버도 문제없습니다.
도커 이미지는 Docker hub에 등록하거나 Docker Registry 저장소를 직접 만들어 관리할 수 있습니다.
현재 공개된 도커 이미지는 50만개가 넘고 Docker hub의 이미지 다운로드 수는 80억회에 이릅니다.
누구나 쉽게 이미지를 만들고 배포할 수 있습니다.
(3) 도커 레이어 저장방식
도커 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 보통 용량이 수백 MB에 이릅니다.
처음 이미지를 다운받을 땐 크게 부담이 안되지만 기존 이미지에 파일 하나 추가했다고 수백 MB를 다시 다운받는다면 매우 비효율적일 수 밖에 없습니다.
도커는 이런 문제를 해결하기 위해 레이어(layer)라는 개념을 사용하고 유니온 파일 시스템을 이용하여 여러개의 레이어를 하나의 파일시스템으로 사용할 수 있게 해줍니다. 이미지는 여러개의 읽기 전용(read only) 레이어로 구성되고 파일이 추가되거나 수정되면 새로운 레이어가 생성됩니다.
ubuntu 이미지가 A + B + C의 집합이라면, ubuntu 이미지를 베이스로 만든 nginx 이미지는 A + B + C + nginx가 됩니다. webapp 이미지를 nginx 이미지 기반으로 만들었다면 예상대로 A + B + C + nginx + source 레이어로 구성됩니다. webapp 소스를 수정하면 A, B, C, nginx 레이어를 제외한 새로운 source(v2) 레이어만 다운받으면 되기 때문에 굉장히 효율적으로 이미지를 관리할 수 있습니다.
컨테이너를 생성할 때도 레이어 방식을 사용하는데 기존의 이미지 레이어 위에 읽기/쓰기(read-write) 레이어를 추가합니다. 이미지 레이어를 그대로 사용하면서 컨테이너가 실행중에 생성하는 파일이나 변경된 내용은 읽기/쓰기 레이어에 저장되므로 여러개의 컨테이너를 생성해도 최소한의 용량만 사용합니다.
가상화의 특성상 이미지 용량이 크고 여러대의 서버에 배포하는걸 감안하면 단순하지만 엄청나게 영리한 설계입니다.
(4) 도커 이미지 경로
이미지는 url 방식으로 관리하며 태그를 붙일 수 있습니다.
ubuntu 14.04 이미지는 docker.io/library/ubuntu:14.04 또는 docker.io/library/ubuntu:trusty 이고 docker.io/library는 생략가능하여 ubuntu:14.04 로 사용할 수 있습니다.
이러한 방식은 이해하기 쉽고 편리하게 사용할 수 있으며 태그 기능을 잘 이용하면 테스트나 롤백도 쉽게 할 수 있습니다.
(5) 도커 파일
# vertx/vertx3 debian version
FROM subicura/vertx3:3.3.1
MAINTAINER chungsub.kim@purpleworks.co.kr
ADD build/distributions/app-3.3.1.tar /
ADD config.template.json /app-3.3.1/bin/config.json
ADD docker/script/start.sh /usr/local/bin/
RUN ln -s /usr/local/bin/start.sh /start.sh
EXPOSE 8080
EXPOSE 7000
CMD ["start.sh"]
도커는 이미지를 만들기 위해 Dockerfile이라는 파일에 자체 DSL(Domain-specific language)언어를 이용하여 이미지 생성 과정을 적습니다.
이것은 굉장히 간단하지만 유용한 아이디어인데, 서버에 어떤 프로그램을 설치하려고 이것저것 의존성 패키지를 설치하고 설정파일을 만들었던 경험이 있다면 더 이상 그 과정을 블로깅 하거나 메모장에 적지 말고 Dockerfile로 관리하면 됩니다. 이 파일은 소스와 함께 버전 관리 되고 원한다면 누구나 이미지 생성과정을 보고 수정할 수 있습니다.
(6) 도커 허브
도커 이미지의 용량은 보통 수백MB로 수GB가 넘는 경우도 흔합니다.
이렇게 큰 용량의 이미지를 서버에 저장하고 관리하는 것은 쉽지 않은데 도커는 Docker hub를 통해 공개 이미지를 무료로 관리해 줍니다. 하루에도 엄청난 용량의 이미지가 전세계에서 다운로드 되고 트래픽 비용만 해도 어마어마 할 것 같은데 그것이 다 무료!입니다.
(7) 도커 Command와 API
도커 클라이언트의 커맨드 명령어는 정말 자아아알 만들어져 있습니다.
대부분의 명령어는 직관적이고 사용하기 쉬우며 컨테이너의 복잡한 시스템 구성을 이해하지 못하더라도 편하게 사용할 수 있습니다. 또한 http기반의 Rest API도 지원하여 확장성이 굉장히 좋고 훌륭한 3rd party 툴이 나오기 좋은 환경입니다.
2. 도커의 동작원리 및 구성요소
(1) 도커의 동작원리
- 도커 엔진 컨테이너는 APP과 필요 바이너리/라이브러리만 갖추고 있어 운영체제의 사용자 공간에 격리된 프로세스로 구동되기 때문에 가상머신의 이점을 누리면서 이동성 높음
(2) 도커 구성요소
구분 | 구성요소 | 설명 |
Ship | Tarred Image | – 저장된 Image Tar 형태 |
Docker file | – Image 생성 환경 파일 | |
Repository | – Docker Image 저장소 | |
Build | Images | – 응용프로그램 및 상태 패키지 |
Run | Container | – 도커 Image 인스턴스 실행 공간 |
Networks | – Host 내부 컨테이너 간 연결 | |
Volumes | – 컨테이너 수명주기와 독립적 – 데이터 유지관리 공간 |
- 컨테이너 기술 자체는 리눅스가 이전부터 제공하고 있으며, 도커는 리눅스 커널이 탑재된 컨테이너 기술인 LXC(Linux Container) 기능 이용
3. 도커 기반 기술
기반기술 | 내용 |
cgroups | 프로세스 그룹 리소스 제한, 격리, 모니터링 |
Namespace | 프로세스, 네트워크 등 운영 환경 고립 |
Libvirt | container에 공통으로 API 제공하는 라이브러리 |
container | 어플리케이션 수행되는 독립적인 공간 |
(1) cgroups
- Control Groups의 약자로 프로세스들이 사용할 수 있는 컴퓨팅 자원들을 제한하고 격리시킬 수 있는 리눅스 커널의 기능이다. namespace와 더불어 도커 컨테이너에서 완벽한 격리 환경을 만드는 데에 쓰이는 중요한 기능이다.
- cgroup를 이용하면 다음 자원들을 제한할 수 있다
- 메모리
- CPU
- Network
- Device
- I/O
- 아래의 그림을 보자. cgroup 은 컴퓨터의 자원(CPU, 메모리, network, storage I/O)가 각 프로세스 별로 독립적으로 격리되어 할당한다.
즉, 도커는 프로세스를 격리하고, 프로세스에 필요한 컴퓨팅 자원을 독립적으로 할당/격리하여 완벽히 격리된 가상 환경을 구축하게 해준다.
(2) namespace
- 프로세스 별로 리소스 사용을 분리한다.
- VM에서는 각 게스트 별로 독립적인 공간을 제공하고 충돌하지 않도록 Hardware Resource 자체를 가상화한다.
- 하지만 namespace의 경우, Hardware Resource 자체를 가상화하는 것이 아니라, Linux 내의 자원을 가상화한다.
- pid name spaces : 프로세스 격리 처리 (독립된 프로세스 공간 할당)
- net name spaces : 네트워크 인터페이스
- ipc name spaces : IPC 자원에 대한 엑세스 관리
- mnt name spaces : 파일 시스템 포인트 관리
- uts name spaces : host name 할당
- 도커에서 cenetos:latest 이미지를 컨테이너로 실행하고, ps 상태를 확인해보자. ps 명령어는 현재 시스템에서 돌고 있는 프로세스를 보여주는 가장 기본적인 명령어이며, 아래처럼 현재 실행중인 프로세스의 목록을 출력해준다. ps 상태를 보면 1번에 /bin/bash와 같이 쉘이 PID1번으로 설정되어있다.
$ docker run -it --name study centos:latest
$ [root@4e1d03de5820 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:42 pts/0 00:00:00 /bin/bash
root 15 1 0 07:42 pts/0 00:00:00 ps -ef
4. 정보 출처
https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html
https://subicura.com/2017/01/19/docker-guide-for-beginners-2.html
https://subicura.com/2017/02/10/docker-guide-for-beginners-create-image-and-deploy.html
http://blog.skby.net/%eb%8f%84%ec%bb%a4docker/
'IT 이야기 > 가상화 기술' 카테고리의 다른 글
가상화 기술(서버 가상화, 컨테이너 가상화) (2) | 2023.06.15 |
---|---|
가상화, 하이퍼바이저, VM(가상머신) (0) | 2023.06.15 |
댓글