들어가며
인프라에 대해서 공부하다보면 docker라는 기술을 많이 사용하는 것을 알 수 있는데, 과연 어떠한 이점이 있기에 도커를 사용하는 것일까? 다양한 장점이 있지만 어떤 프로그램을 다운로드하는 과정을 간단하게 만들기 위해서라고 생각한다. 물론 이 외에도 굉장히 많은 장점이 있다.
docker가 어떻게 다운로드 하는 과정을 간단하게 만들어 줘요?
도커가 없다면 우리는 프로그램을 어떻게 다운로드할까? redis를 다운로드한다고 생각해보자.
- redis 인스톨러 다운로드
- 인스톨러 실행
- 프로그램 설치 완료 및 구동
이러한 방식을 통해서 프로그램의 설치가 이루어진다. 실제로 redis를 설치하려고 한다면, redis.io 사이트 방문을 통해 인스톨러를 다운로드 하거나, homebrew라는 CLI 패키지 매니저를 사용해서 redis를 설치한 후, 터미널에서 redis-server 명령어를 통해 레디스 서버를 구동시켜야한다.
이렇게 생각하면 크게 어려운 과정은 아니지만 이 과정에 수많은 위험요소들이 숨어 있다. Mac은 .dmg 파일 Window는 .exe 파일 확장자를 가진 인스톨러를 다운로드하게 되어 운영체제마다 인스톨러가 다른 것은 물론이고, Mac에서 .dmg 파일을 실행시키게 되면, wget를 필요로 하게 되는데, 일반적으로 wget이 없기 때문에 인스톨 과정에서 에러가 발생하게 된다.
위와 같은 과정은 번거롭고 에러가 발생할 확률이 많다. 하지만 도커를 사용하면 다운로드 과정이 어떻게 바뀌는 것인가?
docker run -it redis
해당 명령어를 한 줄을 통해 손쉽게 redis를 설치 및 실행할 수 있다. 이러한 이점 덕분에 도커를 사용하고, 이 외에도 컨테이너라는 독특하고 서버 환경을 손쉽게 구성할 수 있기 때문에 도커를 사용하곤 한다.
docker의 컨테이너가 뭐죠?
docker docs에 따른 정의는 다음과 같다.
docker는 컨테이너를 사용하여 응용 프로그램을 더 쉽게 만들고 배포하고 실행할 수 있도록 설계된 도구이며, 컨테이너 기반의 오픈소스 가상화 플랫폼이며 생태계입니다.
컨테이너 안에 다양한 프로그램, 실행 환경을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 해주는 것이 컨테이너이다. 이런 식으로 컨테이너 환경을 구성하여 AWS, Azure, Google Cloud 등 다양한 클라우드 서비스에서 작동하기 쉽게 만들어 준다.
위 사진은 백엔드 아키텍쳐를 node, redis, mongoDB를 사용하여 구성한 것을 보여주는데, 도커를 통해 해당 패키지들의 버전을 명시하고, 각 프로그램들이 돌아가는 환경을 할당함으로서 좀 더 효율적으로 서버 환경을 구성할 수 있게 한다.
위와 같은 구조는 컨테이너 안에 모든 프로그램을 다 담아서, 좋은 컨테이너 구조라고 할 수 없다. 컨테이너 안에 다양한 프로그램들이 실행되고 있기에, 어떤 한 프로그램에 문제가 생겨서 컨테이너가 다운되었을 때, 어떤 프로그램에서 문제가 생긴 지 찾기 힘들고, node 서버를 재실행하게 되면 redis 및 mongoDB 서버도 다시 실행되는 등의 문제점이 있어 좋은 컨테이너 환경 아키텍처라고 보기 어렵다.
다음은 컨테이너 환경의 장점을 살린 컨테이너 환경 아키텍처이다. 컨테이너 안에서 하나의 프로그램이 실행되고 있기 때문에, 컨테이너의 관리가 훨씬 편해지고, 컨테이너를 관리하는 툴을 사용한다면 아주 강력한 운영 시스템을 구축할 수 있다. ( Kubernetes .. )
컨테이너의 장점을 극한으로 살린다면 다음과 같은 아키텍처를 구현할 수 있다. 셀 수도 없는 트래픽의 요청에서도 서버가 죽지 않는 구조를 컨테이너 환경을 통해서 구현할 수 있다.
docker의 이미지
컨테이너 환경은 굉장하다. 억명에 가까운 사용자를 받아내기 위한 아키텍처를 만들 수 있고, 서비스의 에러를 감지하기 쉽고, 서비스의 배포도 굉장히 간략해진다. 이러한 컨테이너를 만들기 위해서는 이미지가 필요한데, 이미지는 무엇일까?
컨테이너 image는 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하고 가볍고 독립적이며 실행 가는한 소프트웨어 패키지입니다.
도커 이미지는 프로그램을 실행하는 데 필요한 설정이나 종속성을 갖고 있다. 따라서 도커 컨테이너는 이미지의 인스턴스다. 도커 이미지에 쓰여있는 내용대로 실행하면 컨테이너가 만들어지게 된다. 맨 처음에 도커를 통해서 레디스를 손쉽게 실행시키는 것의 원리는 레디스의 이미지를 통해 컨테이너를 만드는 것이다.
docker run -it redis
redis의 이미지를 run하는 명령어.
이렇게 redis, mongoDB 와 같은 프로그램들을 이미지로 만들고, 컨테이너 환경에서 배포하려는 개발자들은 이미지를 다운받아 사용할 수 있다. dockerhub라는 docker image를 모아두는 사이트도 있고, AWS ECR과 같은 서비스에서도 docker image들을 모아두는 기능을 제공한다.
redis, mongoDB, postgres, mysql .. 등등 굉장히 많은 잘 알려진 ( well-known ) 프로그램들은 이미 dockerhub에 올라와있기 때문에 이미지를 그대로 가져다 쓰면 되고, 직접 만든 서버는 직접 docker image로 만드는 스크립트(Dockerfile)를 써서 도커 이미지로 만들어야 한다. 이를 도커라이징이라고 한다. 그렇다면 이번에는 도커라이징을 통해 컨테이너 환경에서 서비스를 운영하면 어떤 이점이 있는 지 알아보자.
기존의 가상화 기술, 하이퍼바이저(VM)
가상 머신 모니터라고도 하는 하이퍼바이저는 가상 머신을(VM)을 생성하고 실행하는 프로세스를 뜻한다. 위 그림과 같이 하이퍼 바이저를 구현하는 방법은 두 가지로 나뉜다. 이는 전통적으로 과거에 많이 사용했던 방식이다.
예시를 들어보자, 윈도우 위에서 간단한 API 서버를 개발했다. node 런타임을 사용하는 Nest.js를 사용해서 3000번 포트에서 API 서버가 돌아가고 있다. 이러한 node 서버가 윈도우 환경에서는 다양한 이유로 실행시키기 힘들다. 따라서 VMware(가상 환경을 만들어주는 윈도우 프로그램)을 통해서 Window 위에 하이퍼바이저를 깔고, 하이퍼바이저 위에 서비스 운영에 필요한 OS를 설치한다. 이렇게 하면 node 서버도 윈도우 위에 까는 것보다 편하게 설치 및 운영된다. 또한 API 서버를 개발하는 도중 데이터베이스도 필요하게 됐다. 그러면 그대로 하이퍼바이저 위에 DB 서버도 설치하여 운영하면 된다. 그러면 하이퍼바이저 위에 API 서버와 DB 서버가 실행되게 된다.
자, 하이퍼바이저 기반의 VM 구조는 위 사진과 같은데, 그림과 같이 하드웨어의 일부분을 각 VM에다 할당해주는데, 이때 게스트 OS까지 할당해주게 된다. 하이퍼바이저를 사용하여 개발하는 경우 이러한 구조로 인프라 환경이 갖추어진다.
다시 예시 상황으로 돌아와 API 서버, DB 서버를 가동하고 있다고 치자. 어떠한 이유로 API 서버에 과도한 트래픽이 몰릴 것으로 예상된다. ( 선착순 이벤트 등등.. ) 그렇다면 어떻게 이를 대비할 수 있을까? API 서버에 하드웨어 리소스(CPU, 메모리, 디스크)를 더욱 할당하여, 트래픽이 몰려도 버틸 수 있게 한다. 하이퍼바이저를 사용하여 인프라를 구성한 경우에는 이러한 방식을 사용하며, 이 경우 하이퍼바이저 구조에서는 API 서버에 하드웨어 리소스를 추가하고, 서버를 재가동하여 게스트 OS부터 다시 재시작이 된다.
이러한 전통적인 방식에 단점만 있는 것은 아니지만 다음과 같은 단점이 존재한다.
- 리소스 오버헤드 : 하드웨어와 VM에 중간 계층이 존재하여 리소스가 다른 부분에 쓰이게 된다.
- 부팅 시간 : 가상 머신을 시작하는 데 시간이 걸릴 수 있으며, 일반적으로 컨테이너 환경보다 길다.
- 리소스 관리 복잡성 : 컨테이너 환경에 비해 하드웨어 차원으로 접근해야하기 때문에 리소스 관리가 어렵다.
- 스케일링의 어려움 : VM은 일반적으로 컨테이너보다 무겁고 느리기 때문에 스케일링이 어렵다.
이 외에도 다양한 것들이 있지만 몇개만 적어두었다. 하이퍼바이저를 사용하는 전통적인 구조에서는 서버를 확장시킬 때, 하드웨어 자원을 더 추가하는 방식으로 수직적으로 확장하기 때문에 버티컬 스케일링(Vertical Scaling)이라고 부른다.
docker 컨테이너 기반의 가상화 기술
위 사진을 보면 오른쪽은 하이퍼바이저를 사용하는 구조, 왼쪽은 컨테이너를 사용하는 구조이다. 하이퍼바이저를 사용하는 구조와 비교했을 때, 컨테이너는 가상화보다 가볍고 빠르며, 애플리케이션을 패키지화하고 실행하기에 효율적이다.
하이퍼바이저에서는 하드웨어 리소스를 좀 더 추가하고, 서버를 재가동시키는 방법을 통해 서버를 확장했다. 컨테이너 환경에서는 어떻게 서버를 확장할 수 있을까? 앞서 설명했던 개념과 연결지어 설명하면 Container는 Image의 인스턴스이다. 도커 이미지를 통해 컨테이너의 갯수를 늘리며, 많은 트래픽을 여러개의 컨테이너에 분산시키는 방식을 사용한다. 이렇게 서버를 수평적으로 확장하는 방식이기 때문에 호라이즌탈 스케일링(Horizontal Scaling)이라고 부른다.
마치며
이렇게 서비스 운영의 다양한 강점을 바탕으로 docker라는 기술은 인프라 분야에서 굉장히 많은 점유율을 차지하고 있다. docker 기반의 컨테이너 환경을 더욱 확장하여 엄청난 이점이 많은 인프라 기술을 사용할 수 있으니, 관심이 있는 사람이라면 docker를 공부해보는 것을 추천한다.
참조
- docker docs : https://docs.docker.com/
- multi containers picture : medium
'DevOps > docker' 카테고리의 다른 글
[Jenkins] DinD vs DooD 그리고 DooD 설정법 (1) | 2024.10.30 |
---|---|
docker의 경량화 버전인 enroot (0) | 2024.07.13 |
dockerfile 스크립트를 작성하는 방법 (0) | 2023.09.01 |