도커 아키텍쳐

By | 2016/02/01

서버의 소스를 배포하려고 하는 중인데, 내가 알고 있는 방식은 파일을 동기화 시키는 방식이었다. docker를 사용하면, 여러개의 파일을 동기화 안하고 그냥 이미지로 구워서 할 수 있는 것 같아서, 소스 배포할 때 편할것 같은 느낌이 들었기 때문에 조사해보기로 했다. 아무래도 잘 모르는 기술을 잘 파악하기 위해서는 아키텍쳐를 알면 좋기 때문에 시간을 내서 아래의 페이지를 요약 번역 해보았다.

https://docs.docker.com/engine/introduction/understanding-docker/

마음대로 번역한거라 혹시 틀린내용이 있을 수 있는데,  잘못된 것을 발견하게 되면 바로 수정하겠음.

Why docker?

공홈에 보면 주저리주저리 많은데 내가 이해한 바는 아래 3가지이다.

  • 어플리케이션의 빠른 배포
    • 리눅스이기만 하다면 서버환경에 의존성이 없음
    • 우분투에서 센트OS환경의 이미지를 돌릴 수 있음. 당연히 반대로도 가능
  • 배포와 스케일아웃을 쉽게 해줌
  • 머신의 성능을 최대치 까지 뽑아낼 수 있음. (고밀도 -> 고성능)

도커의 아키텍쳐는 어째 되나?

도커는 클라이언트-서버 아키텍쳐를 사용한다.
클라이언트와 서버는 호스트 머신에 설치된 Docker daemon으로 빌드와 실행, 배포등을 할 수 있도록 통신한다.

docker architecture

 

도커 데몬

도커 데몬은 호스트 머신에서 실행되고, 유저는 Docker client를 통해서 데몬과 상호작용한다.

도커 클라이언트

도커 데몬에 명령을 내릴 수 있도록 만든 도커의 주된 유저 인터페이스이다.

도커 인사이드

내부를 이해하려면 다음의 3가지 Docker Images, Docker registries, Docker containers 를 알아야한다.

Docker images

도커 이미지는 읽기전용 템플릿이다. 예를들면, 우분투에 아파치 웹서버를 설치한 것을 하나의 이미지라고 볼 수 있다.
도커 이미지는 도커 컨테이너를 만드는데 사용되고, 도커는 새로운 이미지를 빌드할 수 있는 심플한 방법을 제공한다. 혹은 다른 사람이 만든것을 다운받을 수도 있다. 이미지는 도커의 빌드 컴포넌트이다.

Docker registries

도커 레지스트리는 이미지들을 보관하는 곳이다. 이미지를 업로드/다운로드 할 수 있는 공개 저장소와 사설 저장소가 있다. 공개 저장소는 Docker hub에서 제공되고 있다.
도커 레지스트리는 도커의 배포 컴포넌트이다.

Docker containers

도커 컨테이너는 디렉토리와 비슷하다. 도커 컨테이너는 어플리케이션을 실행하기 위한 모든것을 가지고 있다. 각각의 컨테이너는 하나의 도커 이미지로 만들어 진다.
도커 컨테이너는 실행될수 있고, 시작 시킬 수 있고, 중지 시킬 수 있고, 이동 시킬 수 있고, 삭제 할 수 있다. 각각의 컨테이너는 고립되어 있어며 안전한 어플리케이션 플랫폼이다.
도커 컨테이너는 도커의 실행 컴포넌트이다.

그래서 도커는 어떻게 동작하나?

  1. 어플리케이션을 담기 위해 도커이미지를 빌드 할 수 있다.
  2. 도커 이미지로 부터 어플리케이션을 실행하기 위한 도커 컨테이너를 만들수 있다.
  3. 도커 이미지는 공개/사설 저장소에 공유할 수 있다.

도커 이미지는 어떻게 동작하나?

도커 이미지는 읽기전용 템플릿이고, 이것으로 부터 도커 컨테이너들을 작동시키는 것은 위에서 알게되었다.
각각의 이미지는 연속된 레이어들로 구성되어 있다. 도커는 union file systems를 사용해서 레이어들을 하나의 이미지로 합친다.
Union file systems는 분리되어 있는 여러 파일시스템을 투명하게 덮어서 하나의 파일 시스템 형태로 만들어준다.
여러개의 레이어가 있다는 것은 도커가 가벼운 이유 중 하나이다.
예를 들어서 어플리케이션을 새로운 버전으로 변경하기 위해 도커의 이미지를 다시 빌드한다고 해보자.
그런경우에 이미지 전체를 새로 빌드하는 것이 아니라, 새로 추가된 부분 또는 업데이트 된 부분만 변경하면 된다.
그리고 배포할 경우에도 변경된 부분만 배포하면 되기 때문에 도커 이미지는 더 빠르고 더 심플하다.
모든 이미지는 우분투나 페도라 같은 베이스 이미지로 부터 시작된다. 그리고 베이스 이미지는 보통 Docker hub에서 가져오게된다.
도커 이미지는 베이스 이미지에서 인스트럭션 셋을 작성하여 만들어지게 되는데, 각각의 인스트럭션은 이미지의 새로운 레이어를 생성하게 된다.
인스트럭션은 다음과 같은 액션들을 포함한다.

  • Run 커맨드
  • 파일또는 디렉토리의 추가
  • 환경변수 설정
  • 이미지에서 컨테이너를 런칭할때 어떤 프로세스가 실행되는지

도커 레지스트리는 어떻게 동작하나?

도커 레지스트리는 도커 이미지들을 위한 스토어이다. Docker hub 같은 퍼블릭 레지스트리를 사용하거나, 자체구축을 해서 사용해도 된다.
도커클라이언트로 업로드한 이미지들을 검색할 수 있고, 땡겨 받을 수도 있다.
Docker hub에도 사설 스토리지 서비스를 해주는데, 1개는 무료이지만 그 이상은 비용이 든다. 자세한건 https://hub.docker.com/plans 링크 참고

컨테이너는 어떻게 동작하나?

컨테이너는 운영체제, 유저가 추가한 파일들 그리고 메타데이터로 구성되어 있다. 이미 봤지만, 각각의 컨테이너는 이미지로 부터 빌드된다.
이미지는 컨테이너가 올라가려면, 어떤 프로세스를 실행해야하는지 그에 따른 이런 저런 설정파일을 컨테이너에 알려준다.
컨테이너가 이미지로 부터 실행이 되어서 올라갈 때에, 이미지의 최상단에 읽기-쓰기가 되는 레이어를 더하게 된다.

당신이 컨테이너를 실행할때 무슨일이 일어나나?

docker 바이너리를 사용하건 API를 사용하건 Docker 클라이언트는 Docker 데몬에게 컨테이너를 실행시키라고 요청을 보낸다.

$ docker run -i -t ubuntu /bin/bash

위의 커맨드를 한번 쪼개보자.
docker 커맨드로 도커 바이너리를 실행시키고, 새로운 컨테이너를 올리기위해 run 서브커맨드를 사용한다. 도커 클라이언트가 도커 데몬에게 요청을 보내기위한 최소한의 내용은 다음과 같다.

  • 컨테이너로 빌드할 도커 이미지가 무엇인가, 여기서는 ubuntu 베이스 이미지이다.
  • 컨테이너가 올라간 후 실행하고 싶은 커맨드는 무엇인가, 여기서는 /bin/bash 라는 명령어를 사용한다.

그러면 위의 명령어가 실행되면 어떤 일이 일어날까?

  • ubuntu 이미지를 밀어올린다.(Pull)
  • 새로운 컨테이너를 만든다.
  • 읽기-쓰기레이어에 파일 시스템을 할당하고 마운트한다.
  • 네트웍과 브릿지 인터페이스를 할당한다
  • 아이피를 세팅한다.
  • 당신이 지정한 프로세스를 실행한다.
  • 어플리케이션의 로그를 캡쳐한다.

도커를 지탱하는 기술(Underlying technology)

도커는 Go 언어를 사용하여 작성되었고, 몇가지 커널의 기능을 사용했다.

Namespaces

도커는 namespaces라는 워크스페이스(우리가 컨테이너라고 부르는) 격리화 기술의 이점을 차용했다. 컨테이너를 실행하게 되면, 도커는 해당컨테이너를 위한 namespaces의 셋을 생성한다.
Namespaces는 레이어의 격리를 제공한다 : 각각의 컨테이너는 그들 자신의 namespace를 가지게 되고 외부로는 접속할 수 없다.
리눅스에서 도커가 사용하는 몇가지 namespaces는 아래와 같다.

  • pid namespace : 프로세스 격리에 사용
  • net namespace : 네트워크인터페이스 관리에 사용
  • ipc namespace : IPC리소스 접근에 대한 관리에 사용 (IPC : InterProcess Communication)
  • mnt namespace : 마운트포인트의 관리에 사용
  • uts namespace : 커널격리와 버전 인식에 사용 (UTS : Unix Timesharing System)

Control groups

도커는 cgroup 또는 control groups라는 리눅스의 또다른 기술을 사용한다.
컨트롤 그룹은 도커가 CPU, 메모리, 디스크 같은 하드웨어리소스를 쉐어 할 수 있게 제어한다.

Union file systems

Union file systems또는 UnionFS라고도 하는 파일시스템은 레이어를 생성하는데 사용되고, 매우 가볍고 빠르다. 도커는 컨테이너를 위한 빌딩 블록을 제공하는데에 union file systems를 사용한다. 도커는 AUFS, btrfs, vfs, DeviceMapper 같은 Union file systems를 사용할 수 있다.

Container format

도커는 이러한 컴포넌트들을 조합하여 감싸는데 이걸 컨테이너 포맷이라고 한다. 디폴트 컨테이너 포맷은 libcontainer라고 부른다.
또한 도커는 LXC라는 전통적인 리눅스 컨테이너도 지원한다.
추후에는 BSD Jails또는 Solaris Zones를 통합해서 다른 컨테이너 포맷도 지원할 예정이다.