Docker 키노트

Apr 20, 2016



Daou Tech에서 진행한 Docker 세미나에 대한 발표 텍스트입니다. 프리젠테이션 내 회사 자료가 포함되어있어 프리젠테이션은 공개하지 않으며, 다음 텍스트 또한 일부 내용이 제외되어 있습니다.

목차

  • 오늘날의 가상화 기술들
  • Docker란?
  • Docker가 추구하는 Build / Ship / Run, Any App, Any Where
  • Docker 플랫폼을 사용하는 소프트웨어의 특징
  • Docker를 어떻게 쓸 것인가

오늘날의 가상화 기술들

가상화라고 하면 먼저 VMware나 VirtualBox와 같은 가상 머신이 먼저 떠오르게 된다. PC 한대에 여러개의 가상 머신을 만들어서 윈도우/리눅스 프로그램을 동시에 돌릴 수도 있고, 무엇보다 리소스는 조금 먹는데 서비스 개수만큼 머신이 필요할 때 가상 머신으로서 PC 한대에 몰아서 돌릴 수 있기 때문에 효율적이다.

Hypervisor는 이러한 가상 머신 환경을 제공하는 플랫폼으로서 Type1(Bare-metal)과 Type2(Hosted)로 나뉜다. Bare-metal은 Hypervisor가 곧 OS로서 기능하고 가상 머신과 물리 머신을 직접 제어한다. 반면 Hosted는 상용 OS 위에 설치하는 Hypervisor로 실제 리소스를 쓰기 위해서는 OS를 한번 더 거쳐서 쓰게된다. 때문에 Bare-metal이 성능면에서는 유리하나 요즘 OS들은 커널 레벨에서 가상화를 지원하기 때문에 서로의 차이점이 모호해지고 있다.

가상화 기술은 가상 머신만 있는게 아니라 컨테이너에 대한 가상화도 있다. 여기서 컨테이너란 애플리케이션과 애플리케이션을 위한 환경(ex. RPM 등)만이 담겨있는 박스라 할 수 있다. 가상 머신과 컨테이너의 가장 큰 차이점은 가상화의 범위라 할 수 있는데, 가상 머신은 정말 머신 단위이기 때문에 머신을 돌리기 위한 추가적인 OS가 필요하다. 반면 컨테이너는 애플리케이션만을 위한 단위이기 때문에 머신은 물론이고 OS 또한 범위에 포함되지 않는다.

그림으로 봤을 때 Hypervisor와 레이어 형태가 유사하나 컨테이너에는 OS가 포함되어있지 않다는 것을 볼 수 있다. 즉, 컨테이너 내부에서는 OS가 어떻든 신경쓰지 않고 애플리케이션과 그 환경만이 가상화의 대상인 것이다. Docker도 이러한 컨테이너 가상화의 일종으로 LXC나 OpenVZ와 다를 바는 없다. 그러나 Docker는 컨테이너 가상화 외에 빌드와 배포와 관련된 기능을 제공하는데 이 이야기는 추후에 다시 살펴보자.

앞서 컨테이너가 OS에 신경을 쓰지 않는다고 했는데, 그렇다고 정말 컨테이너가 OS와 관련이 없는 것은 아니고.. 애플리케이션이 OS 콜을 할 때는 결국 호스트 OS를 사용하게 된다. 때문에 리눅스 OS 위에서는 리눅스용 애플리케이션이 담긴 컨테이너만 돌릴 수 있다.

Docker란?

앞서 Docker는 컨테이너 가상화 기술을 제공하는 플랫폼이라 했는데, 공식 홈페이지에 있는 고래 위에 박스들을 올려놓은 그림이 Docker를 잘 설명하고 있다. 박스는 서비스에 필요한 것만 모아둔 애플리케이션과 그 환경들이 담긴 컨테이너라 할 수 있고, 그 박스를 Docker(고래) 위에 올려두면 박스 안의 서비스를 제공할 수 있다. 여기서 박스는 가볍기 때문에 고래 위에 올려두기 쉬우며 Docker 플랫폼은 이와 더불어 원격으로 박스를 올리고 내리는 것까지 지원해준다. 따라서 Docker는 컨테이너 가상화만을 제공하는 플랫폼이 아니라, 격리된 실행 환경과 포장 및 전달까지 제공하는 플랫폼과 API의 집합이다.

컨테이너는 애플리케이션만을 위한 격리된 공간이며 각각의 컨테이너는 서로 독립적인 환경을 가진다. 예를 들어 A 컨테이너에 openssl RPM이 설치된다 하더라도 다른 컨테이너나 호스트 OS가 A 컨테이너에 있는 openssl을 쓸 수 없다. 바꿔 말하면 각 컨테이너는 다른 컨테이너에 영향을 주지도 않고 받지도 않는다. 또한 컨테이너는 가상 머신과 달리 게스트 OS를 포함하고 있지 않기 때문에 그만큼 가볍다고 할 수 있다.

컨테이너는 컨테이너가 담고 있는 애플리케이션과 환경, 상태값들을 이미지화 할 수 있다. VirtualBox의 스냅샷 기능에 비유할 수 있는데 어떤 애플리케이션이 시작하고 돌아가고 있는 도중의 상태를 스냅샷으로 생성하고, 생성한 스냅샷 상태로 얼마든지 돌아가고 복제할 수 있다. Docker도 컨테이너의 이미지화를 지원함으로서 그와 같은 기능을 지원해준다. 즉, 컨테이너로부터 이미지를 만들 수 있고 이미지로부터 컨테이너를 생성할 수 있다.

VirtualBox의 스냅샷 기능은 현재 상태를 남김으로서 과거로의 롤백 밖에 지원하지 못한다. 업데이트를 위해서는 어딘가에서 새로운 상태를 받아야 하는데 스냅샷은 그런 공유 기능이 없다. 반면 Docker는 중앙 Repository(Registy)를 지원함으로서 새로운 상태가 담긴 이미지를 공유할 수 있으므로 서비스의 업데이트까지 가능하게 된다.

Docker가 추구하는 Build / Ship / Run, Any App, Any Where

어떤 서비스를 개발하고 고객에게 Delivery까지의 과정을 생각해보자. 버그가 발생해서 패치가 필요할 때 종종 일부 파일만을 교체할 때가 있다. 그렇게 하는게 쉽고 편할 수 있겠지만 만약 패치 내용이 잘못되서 롤백을 해야한다면 편해지지 못하는 상황이 발생할 수 있다. 당장 시간이 없기 때문에 패치만 생각하고 롤백에 대해서는 무심해지기 때문이다. QA에서 QA 장비에서 테스트할 때 버그가 있다고 레포팅이 왔다. 그런데 개발 장비에서는 그런 현상을 재현하기 힘들거나 재현이 안될 수 있다. 알고보니 어떤 RPM이 추가로 설치되면 그럴 수도 있다는게 밝혀지기까지는 많은 시간이 소요될 것이다. 난감한 것은 특정 OS에서 애플리케이션이 필요로하는 RPM이 더 이상 제공되지 않을 때이다. 애플리케이션은 업그레이드가 가능할 지라도 OS를 업데이트 하기는 쉽지 않다. 만약 하나의 OS에 다른 회사의 서비스도 돌아가고 있는 상황이라면 불가능에 가깝다.

Docker 플랫폼에서는 컨테이너 가상화와 이미지, Repository를 지원함으로서 기존의 문제점들을 개선할 수 있다. 우선 개발자가 git이나 svn에 수정된 소스를 커밋하면 Jenkins와 같은 CI 플랫폼이 빌드를 하고 컨테이너로 이미지화하여 Registy에 올려둔다. 이 이미지를 서로 다른 장비에서 받는다한들 모두 동일한 서비스와 환경을 가진 컨테이너가 만들어진다. 때문에 개발자든 QA든 동일한 컨테이너, 동일한 서비스를 대상으로 개발을 하고 QA를 수행할 수 있다. 배포에 있어서는 컨테이너에 대한 이미지가 Registry에 있기 때문에 어디서든 이 이미지를 받아서 컨테이너로 생성시킨 뒤 바로 서비스를 제공할 수 있다.

이 모든 과정은 자동화가 가능하다는 것이 가장 큰 매력인데, 물론 소스 수정이나 QA는 사람의 손이 필요로 하겠지만 그 외의 배포나 이미지화를 통한 서비스의 형상 관리들이 Docker가 제공하는 Remote API를 통해 자동화가 가능하므로 그만큼의 비용을 줄일 수 있다.

Docker 플랫폼을 사용하는 소프트웨어의 특징

흔히 Docker 플랫폼을 사용하여 컨테이너화된 애플리케이션을 Dockernized 되어있다고 한다. 이런 Dockernized 애플리케이션은 컨테이너로서의 특성을 사용하게 되는데, 우선은 컨테이너를 생성하고 실행하는 것만으로 바로 서비스가 가능하다는 것이다. 컨테이너는 애플리케이션이 필요로하는 환경까지 담고 있기 때문에 굳이 컨테이너 내에서 인스톨을 할 필요가 없다. 즉, 컨테이너 내의 원하는 위치에 실행 파일을 두고 RPM 등을 설치해둔 상태의 컨테이너를 이미지화하면 되는 것이다.

VM은 게스트 OS를 품고 있으므로 시작/정지 상태를 전환하는데 시간이 많이 걸리고 오버헤드도 크다. 만약 VM 이미지로부터 VM 인스턴스 여러개를 생성한다 했을 때, 하나의 서비스가 제공하는 양이 작다면 여러개의 VM 인스턴스를 생성해야 한다. 이 경우 게스트 OS의 오버헤드가 서비스가 소모하는 리소스를 상회하게 되면 배보다 배꼽이 더 큰 겪이 된다. 그렇다고 하나의 인스턴스에 많은 서비스를 담을 경우 서비스들간의 환경이 독립적이지 못하게 된다. 예를들어 VM 이미지에 담긴 모듈 하나만 교체하고 싶은데 VM 인스턴스에 담긴 모든 모듈들의 서비스가 재시작된다. 반면 컨테이너는 게스트 OS를 포함하지 않기 때문에 시작/정지 상태로의 전환이 월등히 빠르고, 게스트 OS로 인한 추가 리소스 낭비가 없다. 때문에 컨테이너에 하나의 작은 서비스만 담는데에 부담이 없다. 때문에 어떤 서비스에 문제가 발생했을 때, 해당 서비스만 교체가 가능하다.

컨테이너에 담긴 애플리케이션은 기본적으로 컨테이너 내의 데이터 볼륨에 상태와 데이터를 담아둔다. 만약 컨테이너를 지우게 되면 애플리케이션이 가지고있던 상태와 데이터 또한 사라진다. 필연적으로 Persistence(영속성)이 필요한 상태와 데이터가 있기 마련인데 Docker는 이를 위해 2가지 방안을 제공해준다. 우선은 호스트 OS가 마운트하고 있는 디렉토리를 컨테이너의 데이터 볼륨으로서 마운트 시킬 수 있다. 이를 통해 컨테이너 내의 애플리케이션은 직접 호스트 디렉토리에 데이터를 기록할 수 있다. 호스트에서 직접 디렉토리를 지우지 않는 한, 컨테이너를 삭제한다해도 호스트에 있는 데이터는 지워지지 않는다. 이 방법은 정통적인 반면, 호스트 디렉토리의 상태에 컨테이너가 영향을 받게 된다. 또한 호스트 디렉토리는 컨테이너의 범위가 아니므로 Docker 플랫폼의 기능을 전혀 사용할 수 없다. 또 한가지로는 동일한 이미지로부터 생성된 다른 컨테이너를 데이터 볼륨으로서 사용하는 것이다. 즉, A 컨테이너에서 서비스를 수행하고 데이터는 B 컨테이너에 쌓는 방식이다. B 컨테이너를 삭제하지 않는 한 데이터는 날라가지 않는다. 이 방법은 데이터를 쌓아놓은 곳이 컨테이너이기 때문에 Docker 플랫폼을 사용할 수가 있다.

Docker를 어떻게 쓸 것인가

Docker는 아직 2년 정도의 역사만 가지고 있지만 빠른 속도로 대중화되고 있다. AWS(Amazon Web Service)는 EC2 Container Service에서 Docker를 지원하기 시작하였고 마이크로소프트 또한 Docker 플랫폼을 지원하는 Windows Container Server 제품과 Azuer에서도 준비 중이다. 이로 인해 많은 오픈소스 애플리케이션들이 Dockernized 되어있어 개발자는 복잡한 설정이나 설치없이 간편히 즉각적으로 오픈소스를 사용할 수 있다.

앞서 언급했듯이 Docker는 빌드와 배포, 런타임에 이르기까지의 플랫폼을 제공해주기 때문에 동일한 환경의 애플리케이션 구축은 물론 표준화된 개발, 배포 프로세스를 제공해준다. 이로인해 애플리케이션의 배포 주기를 빠르게 가져갈 수 있으므로 유동적인 서비스를 제공할 수 있다. 혹자는 이제는 DevOps를 넘어 NoOps를 바라볼 수 있는 것 아니냐라고 말하는데..