도커란 무엇인가 / Docker 컨테이너 / Docker 이미지 / LXC / 가상화

조영규의 블로그

2015. 3. 9. 20:13 from Develop




본 포스트는 개인적으로 가장 빨리 만나는 Docker(길벗 출판사 , 이재홍저)책을 공부하며 정리하는 포스트라는 것을 미리 밝힌다.


Docker란 무엇인가?

도커는 2013년 3월에 출시한 오픈소스 컨테이너 프로젝트다. 현재 2년정도 지난 시점에 세계적으로 엄청난 인기를 구사중인 대단한 프로젝트기도 하다.

서버시장이 클라우드 환경으로 옮겨가게 되면서 우리는 가상서버를 손쉽게 수백대를 구매하여 바로 사용할 수 있게 되었다. 그런데, 서버 갯수가 많아지면서 각각의 서버에 소프트웨어 설치와 설정이 큰 귀찮음으로 다가오게 됐다. 몇개 안됐다면 직접 할텐데 갯수가 엄청나니 이것을 처리할 무언가가 필요했다.

초기에 쉘 스크립트를 통해 해결하려는 시도도 있었다. 이 방법으로 필자도 오랜기간 서버 관리를 해왔다. 그러나 쉘 스크립트는 복잡한 기능 구현은 거의 불가능 할 뿐더러(사실은 잘 못해서 그런거겠지만… ㅋㅋ) 자동화의 한계가 있다. 이를 어떻게 해결 할 것인가.

이를 해결하기 위해 나온 아이디어가 바로 Immutable Infrastructure다. 그 서버에 깔린 OS(호스트 OS)와 서비스 운영을 위한 환경(서버 운영을 위해 필요한 프로그램들; node js, mysql, java등)을 분리해 이 서비스 운영환경을 패키징 해 배포한다는 아이디어이다. 이때 이/ 패키지를 데몬툴즈같은 가상 이미지 파일과 비슷하다해서 이미지라 부른다. 어쨋든 이런 생각을 구현한 것이 Docker다.

이것은 엄청난 확장성을 가져다 준다. 클라우드 플랫폼에 이것을 적용하면 자동 확장이 가능해지고 마치 공장에서 틀에 물건을 찍어내듯 마구마구 서비스를 확장할 수 있다!

가상머신과는 뭐가 다른거야?

언뜻 들으면 가상머신과 똑같다. 가상 머신에 리눅스를 설치하고 그 가상 머신을 이미지화 해 여러 서버에 복사하면 똑같은 것 같지 않은가. 그런데 좀 다르다.

가상머신

가상 머신은 편했다. 그러나 느렸다. 가상 머신 자체는 거의 완전한 컴퓨터다. 이게 무슨말이냐하면, 가상머신은 기본적으로 원래 컴퓨터 OS(호스트OS)위에서 돌아간다. 그리고 그 가상머신은 하이퍼바이저를 통해 그 위에서 수십개의 게스트 OS를 돌린다. 즉 게스트 OS가 독자적으로 돌아가는 가상 컴퓨터 인 것이다. 올리고 올라가고 올라가서 실행되니 느린건 당연지사.

OS를 자체적으로 가지고 있다는 것은 OS를 가상 머신 이미지에 포함해야 했고, 이렇게 되다보니 이미지 용량이 상당히 컷다. 그리고 이것은 상당히 배포와 관리를 힘들게 했다. 인터넷이 빨라도 엄청난 용량은 부담인건 똑같으니까.

Docker는 뭐가 달라.

도커는 이를 더 가볍게 만들었다. 게스트 OS를 없애버렸다. Docker는 호스트 OS를 사용해서 동작한다. 즉 호스트 OS의 시스템 콜을 직접 호출한다. 이것은 매우 빠른 속도로 작동할 수 있음을 의미한다(실제 빠른가는 별개의 문제기에).

도커는 도커 이미지에 서버 운영을 위한 프로그램과 라이브러리를 포함하고 있다. 이런 이미지들은 도커로 각각 격리되어 설치된다. 즉 도커 엔진이 도커 이미지를 설치할 때, 마치 가상 머신처럼 분리 시켜준다는 것이다. 그러나 호스트 OS는 공유한다. 그게 다다.

도커를 사용하면 호스트OS위에서 바로 돌리는 것과 비슷한 성능 수준을 얻을 수 있다. 99%정도까지 유사하다고 한다.

도커가 제공하는 Docker Hub

도커는 이미지 생성과 배포에 특화된 기능을 제공한다. 마치 깃처럼 이것을 이용하면 이미지를 push/pull할 수 있다. 뿐만 아니라 이것들을 공유할 수 있는 깃헙과 같은 도커허브를 제공한다.

리눅스 컨테이너 이야기부터 해보자.

chroot라는 명령어가 있다. 이것은 파일 시스템에서 루티 디렉토리(/)를 바꾸는 것이다. chroot로 특정 디렉토리를 루트 디렉토리로 설정하면 chroot jail이라 불리는 격리된 감옥이 생성된다. 이것을 활용하면 안에서 밖으로는 절대 나갈 수 없는 환경을 만들 수 있다. 이것으로 하이퍼바이저의 오버헤드를 피하면서 가벼운 가상화 비스므리한 환경을 조성할 수 있었다. 그러나 이것은 온갖 귀찮은 일을 해야 하게 만든다.

일단 실행 파일과 라이브러리등을 직접 준비해 넣어줘야한다. 바꿔야 하는 설정이 있다면 해당 설정또한 바꿔야 한다. 해당 공간이 사용하는 정보들을 제대로 제공받지도 못할 뿐더러 호스트의 다른 프로세스의 어떤 문제가 직접적으로 영향을 끼친다. 아무튼! 사용자가 해야할 일이 엄청나다. 이것을 해결하기 위해 이것을 시스템 레벨에서 좀 더 잘 제공하자는 리눅스계의 움직임이 있었고, LXC(LinuX Container)라는 기능이 탄생한다.

LXC는 기존 가상화와 달랐다. 이 공간에는 OS가 없기에 가상 머신이라 부르기도 좀 그랬다. 그래서 바구니/그릇(컨테이너)정도로 부르기로 결정했다. 한국인이면 바구니라 불렀을지도 모르겠는데, 외국인이라 컨테이너라 부른듯하다.

이 LXC기능에 완전히 격리된 가상 공간을 제공하고자 했다. 이를 위해 커널의 Control Group(cgroups) 기능을 통해 CPU도 메모리도, 디스크와 네트웍자원까지 할당할 수 있도록 했고, 커널의 Namespace isolation(혹은 namespaces)이란 기능으로 프로세스트리와 사용자계정, fs까지도 격리되도록 했다.

그러나 이렇게 생성된 LXC기능은 공간 외에 서버 운영에 필요한 기능을 필요한 수준으로 제공치 못했다. 이에 따라 Docker가 등장한다.

LXC와 도커

기존에 LXC에 기능을 얹기 위해 구현된 도커는 0.9버전부터 libcontainer를 사용해 LXC를 대체하기 시작한다. 직접 LXC의 기능을 하기 시작한 것이다. 그리고 이를 exec driver라 부른다.

실행옵션에 따라 LXC 또한 사용할 수 있다.

Docker 이미지 VS 컨테이너

도커에는 이미지와 컨테이너라는 2가지의 헷갈리는 단어가 존재한다. 또 이미지베이스 이미지도커 이미지로 구분된다.

베이스 이미지

베이스 이미지란, 리눅스 배포판의 커널 영역을 제외한 사용자 공간/영역(유저랜드)만을 이미지에 포함한 파일을 의미한다. 이때 사용자공간/영역(유저랜드)란, 커널 공간/영역과 관련된 것들을 제외한 부팅시 필요한 몇몇 실행파일과 라이브러리, 그리고 패키징 시스템(우분투의 apt같은)것들을 포괄해서 부르는 명칭이다. 이 유저랜드 혹은 사용자공간/영역에 Redis나 Nginx등을 설치해서 베이스 이미지로 배포하기도 한다.

유저랜드에는 각 리눅스 배포판의 특징이 고스란히 있어서 각 배포판 고유의 패키징 툴도 그대로 활용 할 수 있다. 이 베이스 이미지는 변형되거나 뭔가가 추가 설치될 수 있는데 이렇게 해서 변형된 이미지를 도커 이미지라 부른다.

도커 이미지

도커 이미지는 베이스 이미지에서 몇가지를 라이브러리, 프로그램, 소스 파일등을 추가/설치/저장한 이미지다. 도커 이미지는 베이스이미지부터 상속받듯이 만들어진다. 즉, 베이스이미지에서 추가되거나 변형되는 부분만 도커 이미지에 저장된다. 이렇게 만들어진 도커 이미지는 또 수정될 수 있는데, 이렇게 수정되면 또 그 변형된 부분만 다시 도커 이미지에 저장된다.

첫번째 변화후 저장된 도커 이미지를 A라 하고, 두번째 변화후 저장된 도커 이미지를 B라 하면,


베이스 이미지 + A + B


를 하여 도커 이미지 실행이 시작된다. 이 때 도커는 필요한 파일을 부모이미지부터 자식이미지까지 싹 받아서 합친다. 이렇게하여 실행된 이미지를 우리는 컨테이너라 부른다.

컨테이너

도커 컨테이너는 이미지가 실행된 상태를 뜻한다. 이미지 하나로는 수백개의 컨테이너를 생성할 수 있다. 마치 이 관계는 실행파일과 프로세스의 관계 같은 것이다.



“ 다음 시간에는 도커를 설치해보자! ”

comments powered by Disqus
태그, 트랙백, 검색 상자 토글