Docker에 대해 알아보자(이론편)

아니!!!! 내가 README.md 보라고 slack에다가 refer. 걸어줬잖아! docker-compose -f docker-compose.dev.yml up --build -d 이게 어렵냐고!! 그리고 개발 프로그램 골치아프게 직접 설치하지말자. elk, oracle DB, tensorflow 기타 등등 설치난이도 환경구축 귀찮은거 5분 안에 끝내자.

Imagem de capa

이전 포스트입니다.

2017년 4월 2일에 작성된 문서를 재 가공한 포스트입니다. 해당 포스트를 작성했었을 때에는 자위용에 불과해서 자위용포스트는 전부 지워버렸습니다.

세상을 재미있게 만들기 위하여!!

주의

이 블로그의 내용은 대단히 주관적인 내용이 가득합니다. 그리고 양질의 글을 읽었지만 똥글이 나오는건 제 미숙함 때문입니다. 그럼에도 불구하고 피드백 많이 주신다면 자세히 조사하여 반영하도록 하겠습니다. 또한.. 가능한 링크로 올려놓은 자료들은 반드시 열어보시기 바랍니다. 분명 도움이 될 것입니다. (- -)(_ _)

Docker를 써야하는 이유

Docker는 반 가상화보다 경량화된 방식이고. 게스트 OS를 설치하지 않는다. 그리고 Docker에서는 분리된 공간을 이용해 서버 운영을 위한 프로그램과 라이브러리를 쉽게 설치할 수 있다. 하드웨어를 가상화하는 계층(Hyper-V)이 없으며, 호스트의 자원을 직접 이용하기 때문에 메모리 접근, 파일시스템, 네트워크 속도가 가상머신에 비해 월등히 빠르다. 그러므로, 메인 호스트와 Docker의 컨테이너 사이의 계층과 성능차이는 크게 발생하지 않는다.

라는 어려운말을 하는데, 나는 아직 경력도 없는 신입 나부랭이라서, 그런건 잘 모르겠다. 그냥 편하다. 정말 docker의 성능이 기존 Host에서의 운영과 비교했을때 0.925% 손실 있는지? 가상화, 반가상화, 컨테이너 정말 몸소 가상화와 반가상화의 차이점을.. 직접 체험 했었나..?

그냥 짧고 간단하게 경험에 의한 장점을 말해보자면…

  1. 개발 프로그램 설치와 삭제가 매우 쉽다. 5분이면 된다. (elk, reids, mongodb, oracleDB, mysql) 등등. 직접 패키지 인스톨(yum, apt-get, brew)과 소스코드 빌드 등등의 모든 일련의 작업들이 필요없게 된다.
  2. Docker의 컨테이너에 대한 개념은 network에 대한 지식 그리고 cloud platform(GCP, AWS, Azure)의 이론을 간접적으로 맛볼 수 있다.
  3. 극 초기의 각종 셋팅을 포함한 아키텍쳐를 만들때, 스크립트로 짜 놓기만하면 모두가 같은 환경을 이용할 수 있다. 그리고 이 환경을 모두와 공유도 할 수 있으며, 배포용으로도 사용할 수 있다. 실제 서비스 배포시에는 Docker환경에서 점진적 scale out 전략을 선택하는 방법도 고려해볼만 하다.

특히. 1번. 언제까지 elk, oracleDB, nginx 등등을 직접 설치하고 암에 걸릴것인가. 그리고 그 직접 설치한 프로그램의 데몬을 언제 직접 네이밍주면서 관리할것인가. 나도 신입이지만, 나의 소중한 친구들을 바라보자면 소중한 개발머신(개인 랩탑)에 눈뜨고 볼 수 없는 대 환장파티를 벌이고있는데, 마음의 병을 앓을뻔했다.(농담이다, 사랑한다.) 신입이어도 장비관리는 기본 소양, 개발 머신을 소중히 다루기위해서는 각종의 nvm, jenv, rvm 등등의 virtual management 프로그램 뿐만아니라 docker로 container 인스톨 프로그램에 대해서도 알아야할 필요가 있다. 복잡한 개발 프로그램을 쉽게 설치하고 삭제할 수 있는 시간을 단 5분도 안걸리게 만들어주는 진기명기한 그대의 이름은! docker!

Docker가 나오기 전 대부분의 서비스 운영환경

Docker에 대해 알기전에 알아야할 것들

가상화가 나오기 직전

컴퓨터 안에서 컴퓨터를 만들어내기 위한 시도에 의해 탄생한 기술이다. 1960년대에 가상화라는 개념이 처음 등장하였으며, 컴퓨터 성능이 좋아지면서 PC에서도 사용하게 되었다(Parallels, VMware, VirtualBox). 우리가 알고있는 오픈소스 Open Stack, 아마존의 EC2 또는 그 이외의 VPC 호스팅 서비스들이 가상화 서비스의 산물이다.

개인 컴퓨터가 발전하게되면서 서버컴퓨터도 점차 성능이 좋아지게 되었고, 서버컴퓨터의 자원을 효율적으로 관리하기위한 다양한 기법과 기술들이 나오게 되었다. 그렇다면, 효율적인 방법이란 무엇일까? 일례로 예를들면 EC2실제로 서비스를 운영하다보면, 트래픽이 몰릴때와 안몰릴때가 있다. 트래픽이 몰릴대에는 컴퓨팅 자원을 대부분 차지하지만 그렇지 않은경우 대부분 사용하지 않은체 방치되게 된다. 심지어 배치(스캐쥴링) 프로그래램이 작동하는 서버에는 아무리 내버려 두어도 자원을 다 못쓰고 남겨둔채 방치된 서버도 있게 된다.

가상화는 이러한 남는 자원에 대한 관리를 위해, 아니 정확히는 자원에 대한 관리를 효율적으로 관리하기위해 나온 기술이다.

1. 가상화란?

가상화

가상화는 컴퓨터 리소스의 물리적인 특징을 추상화하며, 사용자에게는 논리적 리소스를 제공한다. 그리고 이를 통하여 다양한 기술적/관리적 이점들을 제공하는 기술이 바로 가상화(Virtualize)이다. 가상화는 사용자와 물리적 리소스간의 Virtualize Layer 구현을 통하여, 컴퓨팅 리소스에 대한 접근 및 인프라 관리를 간소화하는 것을 목적으로 한다.

가상화의 기능은 다음과 같다.

1) 공유 : 다수의 많은 가상 자원들이 하나의 동일한 물리적 자원과 연결되어 있거나 가리키는 것을 말한다. 2) 단일화 : 가상 자원은 여러 개의 물리적 자원들에 걸쳐서 만들어질 수 있으며, 이를 통해 외견상 전체 용량을 증가시키고 전체적인 관점에서 활용과 관리를 단순화 시켜 줄 수 있다. 3) 에뮬레이션 : 가상 자원에서 어떤 기능들이나 특성들을 마치 처음부터 존재했던 것처럼 구성할 수 있다. 4) 절연 : 가상화된 자원들과 물리적 자원들간의 상호 매핑은 가상화 자원들 또는 가상화 자원들을 사용하는 사용자들에게 영향을 미치지 않으면서 물리적 자원들이 교체될 수 있게 되었다.

가상화가 나온 이후로, 서버 자원을 효율적으로 단순히 관리하는것 뿐만이 아니라 가상화 기술을 활용해서 물리적 서버를 대여해주는것이 아닌 가상화로 만들어낸 서버를 대여해주는 호스팅 서비스도 나오게 되었다. 사용자는 서비스를 하면서 물리적인 서버를 가지고 있는것이 아니기 때문에 트래픽이 몰리는 시기와 몰리지 않는시기에 맞춰서 가상화한 서버의 규모를 축소하거나 늘리기 시작했다 물리적 서버를 대여해서 쓰던 시절부터 존재했던 용어 Scale-In, Scale-Out이 비교적 효율적으로 할 수 있게 되었으며, 이에 맞춰 새로운 관리 전략이 나오기도 했다.

이건 교수님한테 들은이야기인데, 프로젝트를 매번 새로운 버전을 배포할때마다 서버 전체를 ISO로 뜨고, CD로 부팅 이미지로 만들어서 관리했다고 한다. 즉, 가상화로 새롭게 만든 컴퓨터에 서버 전체를 ISO로 뜬 이미지를 CD로 구워서 버전관리를 하였고, 이를 이용하여 scale out, scale in을 수행했다고 한다. 지금은 조금 더 발전되어 CD로 들고다닐 필요가 사라졌기에 물리적인 기억장치인 CD 없이도, 서버 컴퓨터에서는 남는자원을 활용해 가상화로 컴퓨팅 공간을 만들어 낼 수 있게 되었다. 당연한 이야기이지만, 환경에 의존하여 개발 프로그램들을 인스톨하는 과정자체가 사라지고, 이미지를 인스톨만하면 즉시 서비스에 이용할 수 있게 되었다.

2. 반가상화란?

반 가상화에 대해 더 자세히 알고 싶다면?

하지만 가상화에는 단점들이 존재한다. 가상화(전가상화)와 달리 하드웨어를 완전히 가상화 하지 않는다. 그렇기 때문에 게스트 OS가 직접 하드웨어를 제어하는게 아니라 게스트OS보다 심지어 호스트의 OS영역보다 하드웨어의 영역과 더 가까운 가상화 레이어의 Hypervisor에게 의뢰한다. 그러므로 물리적 제어에 있어서 Hypervisor가 제어를 하기에 높은 퍼포먼스를 유지할 수 있다

하지만, 역시 반 가상화에도 3가지 단점이 존재한다. 첫 번째는 반 가상화를 실현하기위해 게스트 OS의 커널 일부를 수정해야한다는 점이다. 게스트 OS는 오픈소스인 리눅스만 공개되어있기 때문에 리눅스만 게스트의 OS로 활용할 수 있다. 두 번째는, 운영체제의 설치를 요구하기 때문에 자원의 낭비를 불러온다. 애초에 가상화는 이미지 안에 OS가 포함되기 때문에 이미지 용량이 자연스레 커지게 되었었다. 그리고 마지막은, 가상화의 고질적인 문제인지 가상화보다는 높은 퍼포먼스를 준다고는 하지만 전가상화하지 않고 쓰는것보다 기본적으로… 느리다. 가상화는 기본적으로 느리다..

성능도 느리고, 이미지로 인한 자원이커져 이미지 송수신 시간도 많이 잡아먹고, 운영체제도 설치해야하는 시간도 필요하고, 그리고 가상화 하지 않은 서버보다 느린건 변함 없고….

3. 컨테이너란?

컨테이너가 나오기 이전까지의 상황 총 정리

가상화와 컨테이너 기술의 차이

가상 머신은 하드웨어 스택을 가상화 한다. 컨테이너는 이와 달리 운영체제 수준에서 가상화를 실시하여 다수의 컨테이너를 OS 커널에서 직접 구동된다. 하지만, 컨테이너는 훨씬 가볍고 운영체제 커널을 공유하며, 시동이 훨씬 빠르고 운영체제 전체 부팅보다 메모리를 훨씬 적게 차지한다. 그렇기 때문에 컨테이너는 애플리케이션을 실제 구동 환경으로부터 추상화할 수 있는 논리 패키징 메커니즘을 제공할 수 있다. 이러한 분리를 통해 사설 데이터 센터나 공용 클라우드 개발자, 심지어 개인 노트북 컴퓨터에서까지 대상 환경을 막론하고 컨테이너 기반 애플리케이션을 간단하고 균일하게 배포할 수 있다. 또한 컨테이너화를 통해 업무 영역을 깔끔하게 분리할 수 있다. 즉, 개발자는 애플리케이션의 로직과 종속 항목에 집중할 수 있고, IT 부서는 특정 소프트웨어 버전과 개별 앱 구성과 관련한 세부 업무에 시간을 낭비하지 않고 배포 및 관리에 집중할 수 있다.

항목 컨테이너의 이점 가상머신의 이점
일관성 있는 런타임 환경 O O
애플리케이션 샌드박스화 O O
디스크 용량 절감 O X
낮은 오버헤드 O X

주로 서버의 인프라스트럭쳐의 컨테이너라고 한다면… Docker가 주류를 이루기 때문에 Docker를 기본 전제로 포스트를 전개하겠다.(!차피! Docker 포스트기도 하고~!)

Docker의 컨테이너 기술은 리눅스의 컨테이너(LXC)(cgroups, namespaces) 를 활용한 기술이다. 리눅스의 컨테이너 기술을 이용한 Docker의 컨테이너는 가상화 보다 훨씬 빠르게 새로운 가상의 공간을 만들어낼 수 있다. 정확히 말하면 가상머신은 아니지만, 쨋든 독립적인 컴퓨팅 공간(가상공간)을 만들어 낸다. 하지만 만들어진 가상 공간안에 실행파일은 호스트(공간이 독립적인것이지 실행하는 주체는 docker를 실행시킨 사용자 자신이다.)에서 직접 실행한다.

컨테이너 기술은 가상화보다 단지 성능이 좋기만한게 아니라 또 다른 변화를 가져온 기술이기도 하다. 우선 전통적인 배포방식은 운영채제와 개발환경은 픽스(fix)한채로 소스코드만 변경해서 새로 빌딩하고 배포했었지만, Docker를 이용함으로써 새로 가상화 된 공간. 즉, 컨테이너를 활용하여 이미지 통째로 새로 빌드하고 새로운 버전이 나오면 이전에 쓰던 버전을 사용하지 않고 바로 버리는 형태로 배포하기 시작했다. AWS 서비스의 Beanstalk가 그러하다. 그리고 더 나아가, IO에서 데이터 처리, 렌더링에 이르기까지 애플리케이션의 모든 요소가 서로 얽혀 있는 모놀리식 아키텍처에서 진화하여 각각의 애플리케이션 요소를 기능별 또는 서비스 도메인 별로 분리한 형태로 배포할 수 있다. 그것이 바로 서비스 기반 아키텍처(SOA: Service Oriented Architecture)인데, Docker의 컨테이너는 이러한 서비스 기반 아키텍쳐(SOA)와 잘 어울린다. SOA의 장점이지만, 기능별 ‘분업’ 덕분에 다른 요소에 오류가 발생하더라도 서비스에 중단이 발생하지 않으며 애플리케이션 전체의 안정성이 향상을 도모할 수 있게 된다.

그럼 컨테이너하고 이미지는 무슨 차이?

즉, 운영체제 측면으로 본다면 이미지는 실행파일, 컨테이너는 프로세스. 즉 프로그램(데몬)이 켜져있다.

Docker

Docker는 LXC(LinuX Container)에서 사용하는 리눅스 커널 컨테이너 기술을 이용해 만든 컨테이터 관리 유틸리티이며, Build, Ship, Run Docker는 서비스 운영환경을 묶어서 손 쉽게 배포하고 실행하는 경량컨테이너 기술이다.

Docker의 로고

docker

Docker의 특징

  1. 컨테이너 이미지 생성 및 공유할 수 있다. 그러기 위해서 Docker에서는 github처럼 docker hub란것이 존재한다.
  2. docker-compose라는 여러 Docker 컨테이너를 통합적으로 관리하는 cli 프로그램으로써 docker를 설치하면 번들로써 제공한다. docker-compose.yml 파일을 이용하면 컨테이너들의 구성(아키텍쳐)을 공유할 수 있다.
  3. 컨테이너 기반을 이용하여 단순한 저장공간 컨테이너(볼륨)를 만들어 저장공간을 container끼리 연결할 수 있으며, 실행한 호스트의 저장공간에도 접근가능하다.
  4. Docker는 게스트 OS를 설치하지 않는다. 단지 이미지에 서버 운영을 위한 프로그램과 라이브러리만 격리해서 설치하기 때문에 이미지 용량이 크게 줄어든다.
  5. Docker의 컨테이너는 OS를 설치하지 않기 떄문에 호스트와 OS자원을 직접 사용한다.(공유…? 라기보다 사용임…)
  6. Docker는 하드웨어 가상화 계층이 존재하지 않기 때문에 메모리접근, 파일접근 등등 관련한 기능에서 직접 접근하기 때문에 가상화보다 빠른 성능을 보여준다
  7. Docker프로그램에서 다양한 API를 제공하기 때문에 원하는 만큼 자동화가 가능하다. 이 점은 개발과 서버운용에 매우 유용하다.

Docker에서 컨테이너(Container) 의 특징

Docker에서 컨테이너는 이미지를 실행한 상태이며, 이미지를 여러개의 컨테이너로 만들수있는 하나의 격리된 공간이다. Docker는 Dockerfile파일을 이용하여 컨테이너를 구성할 수 있다. 아무런 docker프로젝트에 들어가서 프로젝트안에 있는 Dockerfile를 아무 지식없이 열어보면 해당 이미지를 만들어내기 위한 인스톨 및 작업에 대한 명령어들이 모아져있는것을 알 수 있다. Docker는 컨테이너를 만들때 스크립트의 조합으로 만들 수 있다. Docker의 컨테이너는 스크립트로만 만들긴 하는데.. 그럼 그 스크립트를 구동시키는 기본적인 Guest OS는 script로 만들어지지 않는데… Docker의 컨테이너는 두 타입으로 나눌 수 있다. 베이스 컨테이너애플리케이션 컨테이너 이때 의문이었던 script를 구동시키는것이 바로 베이스 컨테이너이고, 여러 프로그램을 붙이고 구성해놓은것이 바로 애플리케이션 컨테이너이다.

운영체제로 보면 이미지는 실행파일, 컨테이너는 프로세스 즉, Docker는 특정 실행파일 또는 스크립트를 위한 실행 환경

컨테이너는 가상화보다 훨씬 가벼운 가상화 기술이다. 리눅스 안에 있는 컨테이너 기술을 이용하여 가상공간을 만든다. 하지만, 그 만들어진 공간안에 실행파일은 호스트에서 직접 실행한다. 어찌 보면 컨테이너는 가상화가 아닌 격리의 개념과도 같다. 이 컨테이너 기술은 리눅스의 LXC의 cgroups 와 namespaces가 제공하는 기술 컨테이너에 대한 내용은 아래 링크를 반드시 참조한다.

Docker 컨테이너의 원리

Docker의 컨테이너가 만들어지기 까지의 소비된 기술

1. chroot와 jail로 컨테이너에 대한 모티브가 되기 시작했다.

2. Docker 컨테이너에 사용된 커널의 라이브러리 리눅스 컨테이너 - 1 (LinuX Container compose of cgroups& namespaces)

libcontainer

3. Docker 컨테이너에 사용된 커널의 라이브러리 리눅스 컨테이너 - 2 (Add libcontainer)

냠냠

가상머신과 Docker의 특징

가상머신 vs Docker

가상머신의 특징

Docker의 특징

이미지의 구성(컨테이너 스크립트)

updated base image

Docker의 컨테이너 버전관리(이미지 처리 방식 = 컨테이너 생성 방식)

흑 Change and Update 이미지 의존성

사실 Docker의 버전관리? 그냥 Docker의 script모음집을 말하는거 아닌가? 그게 그렇게 커다란 특징이 있나? 싶겠지만, 이렇게 생각한사람은 ‘Docker의 컨테이너는 Dockerfile 이다’라는 오해를 가지고 있을것이다. 여기에서 말하는 컨테이너 버전관리는 scripts모음집에서 오래걸리는 패키지인스톨들(yum, brew, apt-get, wget, curl 등)들에 대한 변화감지에 따른 독립적인 공간의 환경구축 버전관리를 이야기한다. 정말 말 그대로 컨테이너(가상공간)의 버전관리를 말한다.

Immutable Infrastructure 패러다임

다스케테 이무타브루쨩!

등장배경

어떤가? 가상머신(독립적인 공간, 컨테이너)만들기가 매우 쉽고 간단하지 않은가? 개발 아키텍쳐를 간단하게 구성하고 싶을때에 docker를 써야겠다는 생각이 마구마구 들지 않는가? docker만 설치되어있다면, 어떤 프로그램 인스톨이라든지 전혀 격정이 안되지 않는가?!

이제 설명할 것은 Immutable Infrastructure이다. 이것은 가상화 기술이 있을때부터 계속 나왔던 용어이며, 어쩌면 패러다임으로도 불리는 용어이다. 컨테이너 생성과 공유 그리고 설치가 매우 간단해지게되면서, 소스코드 자체를 하나의 컨테이너 실행단위에 맏겨두어도 무리가 없을거라 생각하기 시작했다. 그도 그럴게 적은 리소스와 시간으로 새로운 운영체제를 만들어낼 수 있고 scale out에도 매우 용이하기 때문이다. 때문에 컨테이너의 개수는 증가하였고, 증가된 컨테이너의 대수를 어떻게 셋팅하고 배포는 어떻게 구성할것인가에 대해 고민하게 된다. 바로 이러한 곤란한 상황에서 전개할 수 있는 패터다임이 등장하게 되었다. 그 이름은 바로 Immutable Infrastructure이다.

그렇다면 많아진 서버 대수를 어떻게 셋팅하고 배포를 하게 될 것인가?

어쨋든 contaienr가 그렇게 좋고 편하다는것은 알 겠다. 그렇다면 정말 Immutable Structure란 무엇일까?

Immutable Infrastructure 란?

이미지 기반 어플리케이션 배포 패러다임이다. 즉, 한 번 설정하고 변경하지 않는 이미지 기반의 어플리케이션 배포 패러다임을 뜻한다. 다수의 서버를 동적으로 관리하는 클라우드를 기반으로 효과적이고 유연하게 배포할 수 있을까에 시작한 개념으로, 기존에 서버를 지속적으로 관리 하는것에 벗어나 어떻게 해야 서버를 잘 쓰고 버리는지가 관건인 패러다이다. 예를들어 Heroku, Travis에서 이 패러다임을 적극 채용하고 있으며 docker와 serf 같은 도구들은 이 패러다임의 적용을 돕는다.

Immutable Infrastructure는 호스트 OS와 서비스 운영 환경(서버 프로그램, 소스코드, 컴파일된 바이너리)들을 분리하여 한번 설정한 서버환경은 변경하지 않는다. 이는 Immutable개념을 따른것이다. 그러므로 서비스 운영환경을 이미지로 생성한 뒤 서버에 배포하여 실행하며, 서비스가 업데이트 되면 운영환경 자체를 변경하지 않고 이미지를 새로 생성하여 배포한다. 클라우드 플랫폼에서 서버를 쓰고 버리는것과 같이 Immutable Infrastructure도 서비스 운영환경 이미지를 한번 쓰고 버리는 패러다임이다.

Immutable Infrastructure의 장점

즉, Docker는 Immutable Infrastructure를 구현한 프로젝트로 볼 수 있다. (아주 주관적인 의견)

고생했습니다

여기까지 오셨다면…. 실습을 해봐야죠!? 다음 실습은 제가 실제로 즐겨사용하는 docker script예제로 …! 포스팅을 해보겠습니다!

참고 링크