article thumbnail image
Published 2022. 12. 18. 15:33

가상화(Virtualization)란?

도커를 이해하려면 가상화에 대해 먼저 알아야 한다. 가상화란 하나의 물리적 머신에서 독립된 가상 머신(VM)을 만드는 프로세스이다. 가상화 구현 방식에는 여러가지 방식이 있는데 크게 하이퍼바이저 가상화와 운영체제 수준 가상화가 있다.

가상화의 필요성

머신 리소스의 효율적인 사용

어떤 서버 대여 회사가 100대의 서버를 가지고 있다고 해보자. 만약 가상화 기술이 없다면 서버의 성능이 전부 필요하지 않아도 서버를 대여하려는 한 고객에만 서버를 빌려주어야 할 것이다. 따라서 가능한 최대 고객의 수는 100명이다. 하지만 서버를 소프트웨어를 통해 독립적으로 분할 할 수 있다면 서버의 가용성을 최대로 높여 서버의 리소스 낭비를 줄이고 100명보다 더 많은 고객에게 서버를 빌려줌으로써 더 많은 이윤을 창출 할 수 있을 것이다.

머신의 안정성

하나의 물리 머신에서 A, B, C 세 개의 프로세스가 돌아가고 있다고 해보자. 이 때 A에서 머신을 멈추게 하는 치명적인 버그를 발생시킨다면 B와 C는 문제가 없지만 사용할 수 없게 된다. 하지만 물리 머신 위에서 독립된 여러개의 가상 머신으로 만들어 실행시킨다면 문제가 생긴 가상 머신이 종료되는 선에서 끝나게 되므로 물리 머신도 안전하고 다른 가상 머신에서 돌아가는 B,C는 문제없이 사용할 수 있다

가상화 방식

하이퍼바이저 가상화

일반적으로 가상화라 하면 하이퍼바이저 Type2 방식을 뜻한다. 호스트 운영체제 위에 가상 머신 실행을 위한 하이퍼바이저 소프트웨어(Virtual Box, VMware 등)가 실행되고 하이퍼바이저 위에서 가상 머신이 동작한다. 손쉽게 가상 머신을 만들고 관리하기 쉽다는 장점이 있으나 메모리 사용량이 많고 호스트 운영체제-하이퍼바이저-가상 머신 사이에서 에뮬레이팅 하는 작업이 필요하기에 성능 오버헤드가 크다는 단점이 있다.

운영체제 수준 가상화

운영체제의 커널 수준에서 완전한 파일시스템과 하드웨어 자원의 독립을 지원하는 격리된 공간을 구축할 수 있도록 하는 가상화 방식이며 이를 통해 생성된 인스턴스를 컨테이너, 가상화 엔진 등으로 부른다. 각각의 컨테이너는 호스트의 커널을 공유하여 사용하기 때문에 호스트 커널에 문제가 생기면 영향을 받을 수 있다는 보안적 문제가 존재하지만, 단일 커널을 공유하여 사용하기에 리소스 사용이 적다는 점과 자원 요청에 대한 응답에 하이퍼바이저를 통하지 않고 커널을 직접 사용하므로 네이티브 환경과 거의 동일한 성능을 낼 수 있다는 장점이 있다.

도커란?

도커는 리눅스에서 운영체제 수준 가상화 기술을 활용한 컨테이너 기반의 오픈소스 가상화 플랫폼이다. 도커는 다양한 프로그램, 실행환경을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하고 편리하게 한다. 백엔드 프로그램, 데이터베이스 서버, 메시지 큐등 어떤 프로그램도 컨테이너로 추상화할 수 있고 조립PC, AWS, Azure, Google cloud등 어디에서든 동일하게 동작하고 실행함을 보장할 수 있다.

도커의 구조

Docker Client & Daemon

도커는 클라이언트-서버 구조의 애플리케이션이다. 도커를 사용하려면 GUI로 된 Docker Desktop 또는 Docker cli가 클라이언트의 역할을 하고 Daemon(dockerd)이 서버역할을 한다. 클라이언트가 명령어를 실행하면 유닉스 소켓을 통해 로컬 데몬에 요청을 전달하거나 TCP를 사용해 외부에 있는 도커 데몬에 요청을 전달한다. 요청을 받은 데몬은 이미지, 컨테이너, 네트워크 및 볼륨과 같은 Docker 객체를 요청 내용에 따라 관리한다.

Image

도커 이미지는 도커 컨테이너를 생성하기 위한 파일과 명령어들을 담고 있는 읽기 전용 템플릿이다. 이미지는 컨테이너를 생성하기 위한 모든 정보를 담고 있기 때문에 보통 용량이 수백MB이다. 새로운 이미지를 만들거나 인터넷에서 이미지를 내려받을 때 매번 수백MB의 이미지를 처음부터 빌드하거나 내려받는 것은 매우 비효율적이기 때문에 레이어(Layer)라는 개념을사용하여 도커 이미지를 여러 개의 레이어의 집합으로 구성함으로써 이러한 문제를 해결한다. 이미지 간에 레이어를 공유하고 빌드 시 변경된 레이어만 바꾸어 빌드하는 방식을 통해 다른 가상화 소프트웨어와 다르게 도커는 작고, 가볍고, 빠르게 작동할 수 있다. 이 도커 이미지를 저장하는 외부 저장소를 도커 레지스트리라 하고 이미지를 업로드하거나 다운로드할 수 있다. 대표적인 레지스트리로 Docker Hub가 있다

Container

도커 컨테이너는 이미지를 실행시킨 가상화 인스턴스, 즉 가상 머신으로 볼 수 있다. 컨테이너는 호스트 OS는 물론 다른 컨테이너와도 완전히 격리되어 가상화를 구현하지만 필요에 따라 외부 네트워크, 저장 공간, 하위 시스템을 연동하여 유연하게 확장할 수 있다.

Volume

도커 컨테이너는 외부 환경과 독립된 객체로써 호스트와 독립된 파일 시스템을 가진다. 문제는 컨테이너가 사라진다면 컨테이너 내의 모든 파일도 같이 사라진다는 것이다. 예를들어 데이터베이스와 같이 데이터의 영속성을 관리하는 컨테이너를 제거하고 다시 이미지로 컨테이너를 생성하면 데이터는 모두 사라진 상태로 데이터가 영속되지 않는다.

이러한 문제를 통해 호스트 파일시스템에 Volume을 만들고 도커 컨테이너와 볼륨을 연결하면 호스트 파일시스템을 도커 컨테이너가 공유한다. 즉 호스트에 파일이 저장된다는 것이다. 하나의 볼륨을 여러 컨테이너가 공유하는 것도 가능하며 컨테이너 간 통신을 볼륨을 통해 할 수도 있다

볼륨은 도커과 관리하는 볼륨과 호스트에 직접 연결하는 바인드 마운트로 나뉜다. 볼륨에 대한 더 자세한 내용은 Docker 컨테이너에 데이터 저장 (볼륨/바인드 마운트) 포스트 참조

Network

도커는 컨테이너의 통신을 위해 네트워킹 서브 시스템을 제공한다. 기본적으로 3가지 Bridge, Host, None이라는 드라이버가 기본적으로 제공되며 이중 설정이 없으면 디폴트인 Bridge(docker0)로 설정된다.

Bridge는 일종의 내부 인터넷이다. 브릿지 내의 컨테이너는 할당된 Private IP를 통해 서로 통신할 수 있으며 브릿지 외부의 호스트를 통해 통신하기 위해서는 컨테이너의 포트를 개방해야만 한다. 그렇지 않으면 외부와의 통신은 불가능하다. 포트를 개방할 경우

$ docker run -p <포워딩(연결)할 호스트 포트>:<개방할 컨테이너 포트> ...

네트워크의 자세한 설명은 아래 참조

컨테이너의 IP는 컨테이너가 생성될때 할당되고 재시작하면 재할당 될수 있다. 따라서 컨테이너 사이에 IP를 통해 통신하면 문제가 생길 수 있다. 이러한 경우를 방지하고자 컨테이너 사이의 통신을 컨테이너 이름을 통해 가능하게 하는 링크를 사용한다.

$ docker run --link <연결할 컨테이너 이름> ...
$ docker run --link <연결할 컨테이너 이름>:<링크의 별칭> ...

예를들어 A, B 두개의 컨테이너가 있고 A를 생성할때 링크로 B를 연결할 경우 컨테이너 내에서 Private IP 대신 B의 이름 또는 링크 별칭으로 통신할 수 있다. 링크는 단방향이기 때문에 B에서 A로의 접근은 Private IP로만 가능하다.

 

링크를 통한 컨테이너 통신은 현재 레거시로 분류되어 사용이 불가능해 질 수 있다. 커스텀 네트워크를 통한 새로운 컨테이너 통신 방식은 여기를 참조

 

 

복사했습니다!