🤔 가상화를 사용하는 이유가?
서버 관리자 입장에서 CPU 사용률이 현저히 낮은 서버들을 그대로 두면 리소스 낭비, 돈 낭비이다. 그렇다고 모든 서비스들을 한 서버 안에 올리면 안정성이 바닥을 칠 것이다.
그리하여 안정성을 높이며 리소스도 최대한 활용할 수 있는 깔쌈한 방법으로, 혜성처럼 등장한 것이 서버 가상화이다. 대표적인 가상화 플랫폼으로는 VM(Virtual Machine)이 있다. 그럼 컨테이너는 뭘까?
🚛 컨테이너는 또 뭔데?
현실 세계에서 컨테이너는 물자를 운송할 때 쓰는 물건이다. 컨테이너 내용물의 소유자는 컨테이너가 배송되는 방법에 신경 쓸 필요가 없다. 또한 배송사는 내용물을 알거나 관리할 필요 없이 컨테이너를 목적지까지 운송한다.
컨테이너는 가상화 기술 중 하나로, 기존 OS를 가상화시키던 것과 달리 OS 레벨의 가상화로 프로세스를 격리시켜 동작하는 방식이라고 한다. 그럼 여러 OS를 가상화하는 것과 프로세스를 격리시켜 동작한다는 것은 뭔 차이가 있을까?
VM 가상화 🆚 컨테이너 가상화
기존의 가상화나 클라우드 컴퓨팅을 설명할 때는 VMWare나 VirtualBox와 같은 VM이 언급되어졌다. 이러한 VM은 호스트 OS 위에 게스트 OS 전체를 가상화하여 사용하던 방식이다. 이 방식은 거의 완벽하에 게스트와 호스트가 분리된다는 장점이 있지만, 아무래도 OS 여러 개를 돌리다 보니 상대적으로 무겁고 느리다.
컨테이너는 이러한 VM의 성능적 단점을 보다 개선한 시스템이다. 컨테이너 기반 가상화는 Docker 엔진 위에 OS가 아닌 Application 실행에 필요한 바이너리만을 올린다. 또한 컨테이너 기반 가상화는 Host의 커널을 공유하기 때문에 성능의 효율을 더 높일 수 있다.
컨테이너를 사용하는 것은 가상 머신을 생성하는 것과는 다른 개념이다. 호스트 OS가 사용하는 자원을 분리하여 여러 운영 환경을 만들 수 있도록 하는 것이다.
이 사진을 보면, VM은 하이퍼바이저 위에 가상 머신마다 운영체제가 있고, 맨 위에 애플리케이션이 있다. 반면 컨테이너 구조에는 호스트 운영체제 위에 바로 컨테이너가 있고, 그 위에 애플리케이션이 위치한다. 딱 봐도 구조가 훨씬 간단하다. 이렇게 구조 레이어가 훨씬 간단한 컨테이너가 VM보다 성능을 높이기 쉽다.
🐳 도커 (docker)
컨테이너를 사용할 때 도커를 사용하면 간단한 명령으로 컨테이너 이미지를 만들고 저장할 수 있다. 또한 도커를 설치한 호스트에 컨테이너 이미지를 다운로드해서 컨테이너를 실행할 수 있다.
실제 화물 선박의 컨테이너처럼 규격화한 컨테이너를 만든 후, 호스트로 옮겨 그대로 사용할 수 있다.
🏞 컨테이너 이미지는 또 뭐야?
Container Image는 컨테이너를 실행할 수 있는 실행 파일, 설정값 등을 가지고 있는 것이다. 이미지는 상태값을 가지지 않고 변하지 않는다.(immutable) 아래 그림과 같이 Image를 컨테이너에 담고 실행시킨다면, 해당 프로세스들이 동작할 것이다.
에를 들어 ubuntu 이미지는 ubuntu를 실행하기 위한 모든 파일을 가지고 있으며, MySQL 이미지는 MySQL을 실행하는 데 필요한 파일과 실행 명령어, 포트 등을 가지고 있다. 말 그대로 이미지는 컨테이너를 실행하기 위한 모든 것을 가지고 있기 때문에, 더 이상 의존성 파일을 컴파일하고 새로운 환경에서 이것저것 설치할 필요가 없어진다.
이제 새로운 서버가 추가된다면, 미리 만들어놓은 이미지를 다운받고 컨테이너를 생성하기만 하면 된다. 물론 한 서버에 여러 컨테이너를 실행할 수 있다.
현재 공개된 도커 이미지는 50만 개가 넘고, Docker Hub의 이미지 다운로드 수는 80억 회에 이른다. 누구나 쉽게 이미지를 만들고 배포 쌉가능!
📜 초간단 도커 사용법
도커에서는 도커 이미지를 이용하여 컨테이너를 생성할 수 있다.
도커 이미지를 사용해 이미지에 설정해둔 대로 컨테이너의 구성 환경을 적용할 수 있다.
이미지 목록 보기
$ sudo docker images
이미지 검색
$ sudo docker search [이미지 이름]
이미지 받기
$ sudo docker pull [이미지 이름]:[버전]
이미지 삭제
$ sudo docker rmi [이미지 id]
컨테이너 목록 보기
$ sudo docker ps
컨테이너 실행
$ sudo docker run [options] image[:TAG|@DIGEST][COMMAND] [ARG...]
컨테이너 시작/재시작
$ sudo docker start [컨테이너 id 또는 name]
$ sudo docker restart [컨테이너 id 또는 name]
컨테이너 접속
$ sudo docker attach [컨테이너 id 또는 name]
컨테이너 정지
$ sudo docker stop [컨테이너 id 또는 name]
컨테이너 삭제
$ sudo docker rm [컨테이너 id 또는 name]
번외) 쿠버네티스도 알려주세요 🙋
원래는 이미지가 변경되면 기존의 컨테이너를 새로운 컨테이너로 어떻게 변경할지, 부하가 들어오면 어떻게 부하를 분산할지, 컨테이너가 예기치 못하게 중단될 경우 어떻게 대처할지 등을 개발자가 직접 설정해주고 수정해줘야 했다.
하지만 쿠버네티스(Kubernetes)는 일정한 상태를 입력해두면 내부적으로 Master Node의 관리 하에 다양한 컨테이너를 구동한다.
쿠버네티스를 사용할 경우 아래와 같은 기능이 있다.
무중단 배포
health checking
Reverse Proxy 감지
컨테이너 Scale-out
여러 node에서 컨테이너를 관리하며 ip 중복 방지
이렇게 컨테이너의 배포, 관리, 확장, 네트워킹 등을 자동화하는 것을 컨테이너 오케스트레이션이라고 한다.