Sunday 26 July 2020

Intro to Docker - 1

Background

최근 프로젝트를 진행하면서 backend system에서 필요한 다양한 component를 직접 설치해보고 있다. 서버의 지표들을 수집하고 시각화된 dashboard를 제공하는 Prometheus, Grafana, 로그를 수집하여 parsing 및 indexing을 하여 로그에 대한 분석을 제공하는 ELK (ElasticSearch, LogStash, Kibana), 그리고 지속적인 통합과 전달을 제공하는 Jenkins까지 하나씩 설치했다. 각 component의 official site 혹은 개인 blog에서 제공하는 문서를 따라 진행하는데 대부분 guide에서 Docker container 상에서 실행하는 것을 권장하여서 자연스레 Docker를 사용하게 되었다. 이전에 Python 관련 프로젝트를 진행하면서 간단하게 사용한 적은 있었지만 Docker가 성능적인 측면에서 거의 손실이 없다는 점, 분산 시스템에서 부하를 처리하기 위한 전략으로서 탄력적인 scale out을 제공하는 기반 기술이 된다는 점 이 두 측면에 대한 이해도가 이전보다 증가했다고 판단하여 이번 기회에 알아보기로 했다. 

Why Docker? 


Snowflake servers

다수의 서버를 manual하게 운영한다면 다음과 같은 문제들이 발생할 수 있다. application을 실행하는 서버 instance의 환경이 각기 달라서 이후 실행 환경 차이에 의해 application이 제대로 동작하지 않을 수 있다. 겪어본 사람은 알겠지만 서버 환경에 대한 문제를 해결하기 위해서는 어떤 software engineer든 어려움을 겪을 수 있다. 최근에는 cloud 환경에서 개발이 이루어지면서 서버 환경에 대한 차이는 어느 정도 극복하였다. 하지만 application의 상황에 맞추어 복수의 instance에 대해 여러 번 할당/해제한다면 각 instance 간 초기 실행 시점, 중간 종료 시점 등 운영 기록이 달라지게 된다. 즉 instance에 설치한 application의 동작이 다행히 같을지라도 서로 다른 snapshot을 가지게 되는 것이다. 서버 운영 기록을 일종의 암묵지여서 서로 간 공유가 쉽지 않고 개별적으로 관리하여 이 암묵지가 쌓인다면 잠재적 장애의 원인이 될 수도 있다. 각기 다른 서버들 간 눈송이처럼 다른 형상을 띠고 있는 현상을 들어 snowflake server라고 한다.

Infrastructure as a code

위 문제를 해결하기 위해서 infrastrcuture를 code화 하여 관리하기 위한 여러 tool이 도입되었다. Vagrant, Ansible 등이 바로 그것이다. 이 tool들을 활용하면 관리자 역할을 node에서 여러 node에 대해 일관된 서버 운영 (provisioning, configuration management, deployment) 명령을 내릴 수 있게 되고 통합 code로 관리할 수 있게 된다. 하지만 이 방법은 위에서 언급한 snapshot의 차이를 극복하지 못한다.

Docker



> Docker provides the ability to package and run an application in a loosely isolated environment called a container. The isolation and security allow you to run many containers simultaneously on a given host.

Docker는 container의 기반이 되는 기술 (namespace, cgroups)을 활용하여 process에 loosely isolated된 실행 환경을 제공해준다. 아래에서 언급하겠지만 Docker의 실행 단위인 container는 주어진 instance의 환경과 상관없이 Docker image를 기반으로만 실행 환경이 구성되기 때문에 위에서 여러 container들에게 같은 실행 시점을 가지게 할 수 있다. 따라서 software engineer는 Docker를 통해 각기 다른 서버 instance들에 대해서도 완전히 같은 실행 환경 속에서 application을 실행할 수 있다. 또한 기존의 VM과 다르게 host OS와 Docker 실행 환경 사이에 hypervisor, guest OS가 존재하는 것이 아니기 때문에 Linux kernel의 성능을 온전히 활용하기 때문에 성능적인 측면에서도 모자람이 없다.

https://docs.docker.com/get-started/overview/#the-underlying-technology


Image, Container


Image

An image is a read-only template with instructions for creating a Docker container. Often, an image is based on another image, with some additional customization. For example, you may build an image which is based on the ubuntu image, but installs the Apache web server and your application, as well as the configuration details needed to make your application run.

Docker image는 Docker container를 생성하기 위한 instruction (실행 환경, application code 등)을 담고있는 template이다. Dockerfile을 build 하여 생성할 수 있으며 read-only이기 때문에 고정된 실행 환경을 제공해줄 수 있다. 한 image는 다른 image를 생성하기 위한 base가 될 수 있으며 다른 image는 base가 되는 image, 새로이 추가될 binary 및 library, 실행해 필요한 metadata 및 file, 환경 변수 등으로 구성이 되어 새로운 image로 생성이 된다.

Container 

> A container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI. You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state.


Docker container는 image의 실행 가능한 instance이며 host OS에서 돌아가는 하나의 격리된 process이다. 위 그림이 나타내듯이 container는 read-only의 image layers과 read/write가 가능한 container layer로 구성되어 있다. 자체 network interface가 있어 host의 network interface와 연결되어 외부랑 통신하며 persistent data를 저장해야 하는 경우 host의 filesystem 위에서 volume 이나 bind mount을 통해서 저장할 수 있다.


Future Actions 

Docker가 제공하는 강점은 container orchestration 도구와 결합되었을 때 극대화된다. 집단의 container들을 대상으로 service 단위로 구분하여 관리하거나 주어진 traffic에 맞추어 container를 추가 투입하거나 회수하여 효율적으로 resource를 관리할 수 있다. Swarm Classic, Swarm Mode 등이 기존에 사용되었으나 최근에는 Google에서 개발한 Kubernetes가 사실상 orchestration의 표준으로 사용되어 AWS, GCP 등 여러 군데서 사용되고 있다. 다음 시간에는 orchestration의 개발 배경과 개념에 대해 알아보고 관련 tool들도 알아보도록 하겠다. 


References 

No comments:

Post a Comment