땃쥐네

[Docker] 도커 소개, 도커의 필요성 본문

DevOps/Docker

[Docker] 도커 소개, 도커의 필요성

ttasjwi 2022. 12. 2. 13:52

서버 구축에 있어서 빼놓을 수 없는 키워드하면 역시 도커, 쿠버네티스, AWS인 것 같다.

이들이 중요하다 중요하다 말은 여럿 들었지만 실제로 이를 제대로 학습한 경험은 별로 없어서 학습을 시작했다.

 


1. 시스템 구성 방식의 변화

'서버'를 구축하는 방식은 시대가 변화함에 따라 지속적으로 변화해왔다.

우선 도커와 같은 컨테이너 기반 서비스가 발달한 배경을 확인해보자.

 

1.1 초창기

 

- 초창기에는 안정적인 하드웨어의 서버가 중요했고, 하드웨어의 사양/성격에 맞춰 서비스를 구축했다.

- 하드웨어 자체가 매우 비용이 높고 서비스 운영 도중 한 대 한 대 중단시키기에는 큰 리스크가 있던 만큼 기능을 수정, 변경하기 힘들었다.

- 하드웨어 성능의 성장폭이 가파른 시기였던 만큼 이 시기에는 장비의 수직적인 확장이 중요했다.

 

1.2 시스템의 분산화, 수평 확장

하드웨어의 성능이 어느 정도 안정화 됐다.

 

하지만 시대가 흐를 수록 사용자들의 요구는 더욱 다양화, 복잡화되었고 이에 맞게 서비스 시스템의 복잡도도 증가하게 되었다. 하나의 거대한 시스템(모놀리스 시스템)에 여러 서비스가 강하게 결합되어 있을 경우 한 기능에 장애가 발생하면 시스템 전체에 장애가 발생하는 위험성이 크다.

 

이 단계에서 시스템을 분산화하기 시작했다. 특정 기능에 대한 요청이 특별히 많다거나, 서비스의 복잡도가 높아지면 서비스 단위로 서버를 분리한다. 요청 부하가 많아져 시스템이 견딜 수 없어지면 해당 서비스의 서버 댓수를 늘리는 식으로 수평확장을 하면 된다.

 

하드웨어적으로 깨지기 쉬웠던 초창기와 비교했을 때 어느 정도 하드웨어적으로도 안정화가 이루어졌다고 볼 수 있다.

1.3 마이크로서비스 아키텍처, 클라우드 네이티브 서비스

시스템의 사용자 수가 급증하고, 사용자의 요구는 더욱 다양해지고 이런 요구에 발빠르게 대응할 수 있는 역량이 중요해졌다.

 

고객의 요구 사항을 기반으로 신속하게 변화를 반영하여 시스템을 업데이트할 수 있는 유연성.

고객의 부하가 폭발적으로 증가, 감소하는 상황에서는 이에 발맞춰 탄력적으로 서버를 확장/축소할 수 있는 확장성.

시스템이 죽었을 경우 빠르게 복원할 수 있는 시스템 전체 차원의 내구성/복원력...

 

기존 방식대로라면 부하에 따라 수동으로 서버 댓수를 늘리고(한 번 늘리면 사용자 량이 줄어들었을 때 줄이기 힘들어서 서버 확장을 결정, 추진하는 것도 비용), 서버를 내렸다가 변경된 서버 파일을 서버에 수동으로 올려서 다시 구동시켜야하고, 서버를 증가시킬 때마다 매번 환경을 만들어줘야하는 등... 사용자의 요구사항에 발빠르게 대응할 수 없다.

 

이러한 문제 상황을 많은 기업들에서 인식하게 되고, 그 솔루션 중 하나인 DevOps 문화가 확산되고 이를 실천하기 위한 기반 기술 중 하나인 클라우드 컴퓨팅 기술이 중요해졌다. 클라우드 서비스 제공자(AWS, Microsoft Azure, Google Cloud 클라우드 플랫폼)들은 위와 같은 공통적인 문제상황, 관심사를 해결할 수 있도록 다양한 기능들을 제공한다.

 

물리적으로 서버를 증설하고 시스템을 구축하려면 시간/공간 비용도 필요하고 이를 관리하는 비용이 드는데 이에 대한 책임을 클라우드 서비스에게 금전적 대가를 지불하고 위임하면 된다. 단지 버튼 몇 번 누르면 서버 인스턴스를 만들어 제공해주고, 물리적으로 분산된 환경에 서버를 다중화 시킬 수 있으며, 데이터베이스 서비스, 모니터링 서비스 등등 풍부하고 다양한 기능을 제공해준다. 클라우드 기반 환경에서 제공되는 서비스를 '클라우드 네이티브 서비스'라고 한다.

 

개발자는 코드를 커밋하고, CI/CD 파이프라인(github action, jenkins, ...)을 통해 코드베이스에 통합하고, 이를 기반으로 '컨테이너 이미지'로 변환한다. 그 후 이러한 컨테이너 이미지들을 클라우드 서버에 배포하여 컨테이너로서 실행하고, 여러 대의 컨테이너를 관리하는 기술로는 쿠버네티스와 같은 컨테이너 관리 기술을 사용한다.

 

 

* 클라우드 네이티브 서비스는 항상 정답이 아니다. 클라우드 네이티브 서비스는 장기적으로 비용이 매우 비싸다. 클라우드, 하드웨어 장비에 대한 이해가 충분하지 않을 경우 비효율적인 비용을 지불하면서 클라우드를 사용하게 될 것이다. 어느 쪽이 좋은 지에 대해서는 사업팀, 개발팀 차원에서 트레이드 오프를 거쳐 부분 시스템은 온프레미스 환경에서 구축하고, 필요한 부분만 클라우드에 위임하는 것을 고려하면 될 것 같다.


2. 하드웨어 가상화 vs 컨테이너화

2.1 하드웨어 가상화

 

- 운영체제, 각종 의존성 요소(라이브러리, 바이너리 파일,...), 애플리케이션을 묶어서 하나의 '이미지'로 만든다.

- 호스트 OS 위에 '하이퍼바이저'라는 가상화 계층을 두고 이미지를 실행시키도록 한다.

- 이를 지원하는 제품으로는 '버추얼 박스', 'VMware', '패러렐즈' 등이 있다.

 

2.2 하드웨어 가상화의 단점

2.2.1. 성능 문제

하드웨어 가상화 방식은 컴퓨터의 전체 아키텍처를 모방했기 때문에 한번 실행할 때마다 그 기반이 되는 게스트 OS를 실행해야한다. Virtual Box를 사용해보면, 우분투 리눅스 하나 설치하고, 키려면 시간이 정말 오래 걸린다...

 

2.2.2 애플리케이션 하나를 구동하기 위해 많은 하드웨어 자원을 소모해야한다.

애플리케이션마다 실행할 때 메모리에 게스트 운영체제 자원, 라이브러리 자원 등을 추가적으로 할당해줘야하다보니... 하나의 컴퓨팅 머신에서 실행할 수 있는 애플리케이션의 갯수도 제한적일 수 밖에 없다.

 

2.2.3 엄청난 파일 크기

애플리케이션 마다 OS가 포함되는데 이를 서버에 배포할 때마다 그 엄청난 크기의 데이터를 보내고 저장하는 작업을 거쳐야한다. 내가 가진 ubuntu20.04 이미지 용량 하나만 2.86 GiB 인데, 배포할 때마다 그 이상의 용량을 보내야한다면 그 시간 비용, 공간 비용 등을 무시할 수 없을 것이다.

 

2.3 컨테이너 화

여기서 발전된 형태가 컨테이너화 기술을 사용하는 방식이다.

컨테이너화 방식의 주요 특징은 다음과 같다.

 

- 각 애플리케이션에 운영체제가 아닌 의존성 요소만 포함한다.

- 호스트 운영체제의 커널을 사용한다. 예를 들어 ubuntu 이미지는 ubuntu의 기능을 제공할 뿐, 커널은 호스트 os의 것을 사용한다.

- 각각의 인터페이스는 호스트 OS와 직접 연결되며, 하이퍼바이저/게스트 OS와 같은 추가적인 레이어가 없다. 

- 성능이 향상되고, 리소스 낭비가 적다. 도커 이미지는 파일 크기도 매우 작다

- 호스트 OS 프로세스 수준에서 격리(Isolation)되고 컨테이너들의 의존성 요소를 공유하지 않는다. 만약 한 컨테이너의 라이브러리가 하나 업데이트 되더라도, 다른 라이브러리에 영향을 끼치지 않는다.

 


3. 도커의 필요성

 

3.1 실행 환경

 

- 어떤 서버를 구축할 때 그 위에 필요한 실행환경을 준비하고, 애플리케이션을 설치하는 일련의 과정은 간단하지 않다.

- 운영체제, 리소스, 라이브러리, 서비스, 사용 권한, 관련 소프트웨어 등 애플리케이션이 사용하는 모든 사항을 결정해야 함

- 설치 과정에서, 여러 애플리케이션을 설치/실행하는 과정에서 의존성 충돌이 발생할 수 있다.

- 애플리케이션 별로 분류해서, 각 애플리케이션 마다 전용 서버를 할당하는 식으로 해결하는 방식도 있으나 이 방식은 다양한 프로덕션/테스트 서버 관리하는데 많은 운영 팀 인력을 필요로 하고, 인력 운영 측면에서 좋지 않음

- 실행 환경이 복잡해지므로 애플리케이션을 실행하는 데 별도의 전문성을 가진 담당자가 필요해짐. 담당자의 기술력이 부족할 경우 관리 난이도가 더 높아짐

3.2 격리

- 실행 환경은 깔끔하게 격리되어 유지되어야한다.

- 실행 환경이 격리되지 않았을 경우 한 애플리케이션이 다른 애플리케이션의 실행에 영향을 주게 된다.

- 애플리케이션 하나가, 잘못된 소프트웨어를 실행하면 다른 애플리케이션도 손상시킬 수 있는 등 보안 측면의 문제도 있다.

- 애플리케이션의 손상을 예방할 수 있도록 분리된 샌드박스에서 실행하는 것이 더 안전하다.

3.3 애플리케이션 구성

- 한 서버에서 여러 애플리케이션을 실행하면 왜 실행되는지 모르는 애플리케이션이 많아짐

- 각각의 애플리케이션이 무엇인지, 이들 간의 의존성은 어떤 것인지 알기 힘들어짐.

- 도커에서는 각 애플리케이션을 개별 컨테이너로 구성하므로(격리) 실행 목록을 보고 검색하고 모니터링하는 작업을 깔끔하게 수행할 수 있다.

- Dockerfile을 사용해서, 하나의 이미지를 구성하는 방법(기반 이미지 설정, 필요 명령어 입력...)을 코드로서 문서화할 수 있으므로 애플리케이션 구성 과정을 여럿이 공유하고 효율적으로 유지보수할 수 있다.

 

3.4 이식성

- 도커 버전만 호환되면 그 안에 포함된 모든 소프트웨어들은 프로그래밍 언어, OS, 환경 구성이든 관계 없이 호환된다.

- 도커를 통해 코드 뿐 아니라, 실행 환경을 통째로 제공


4) 고양이와 가축

- 목장에서 가축은 고기를 얻을 목적으로 직접적으로 키운다. 고유의 이름도 없고, 개별적으로 취급하지도 않는다. 냉정하게 들릴 이야기긴 한데, 도중에 가축이 죽으면 목장주 입장에선 가축이 죽은걸 슬퍼하지 않는다.

- 도커 기반으로 한 배포 방식은 가축을 다루는 것과 같다.

- 각각의 서버(컨테이너)들을 집단적으로 다루고, 각 서버는 고유의 이름도 없고, 개별적으로 취급하지도 않음

- 각각의 서버는 개별적인 개체이긴 하지만 그건 중요하지 않다. 집단적으로 다룰 뿐이다.

 


5) 도커 말고 다른 컨테이너화 기술은?

  • 리눅스 컨테이너, 윈도우 서버 컨테이너, OpenVZ, 리눅스 서버 등, ...
  • 하지만 도커는 간결성과 효율적인 마케팅, 스타트업의 성공 방식을 활용해 다른 모든 솔루션들을 넘어섬.
  • 도커는 컨테이너화 기술의 표준 그 자체.

참고 자료


 

Comments