Project : RainMind 개발일지 - 8 [docker, kubernetes 배포 환경, 클라우드]
기능이 대략 완성되면 배포도 한번 생각해보고 있는데, docker와 kubernetes 관련해서 정리해보겠다.
Docker
개발한 애플리케이션과 이를 실행하는데 필요한 환경들을 컨테이너에 담아, 누구의 어떤 환경에서도 동일하게 실행할 수 있게 해주는 플랫폼이다.
사람마다 OS, 언어 버전 등 환경 설정이 모두 다르므로 이를 수동으로 애플리케이션에 맞추기 어렵다. 따라서, 애플리케이션과 이를 실행하는 데 필요한 것들을 하나의 패키지로 묶고, 이 패키지의 설계도를 docker image라고 한다.
docker-compose.yaml 파일에 image:….라고 적힌 것이 해당 도커 이미지를 가져와서 쓰겠다는 의미이다.
docker -compose up -d 명령어를 통해, image:… 라고 적힌 이미지들을 내려받고 복제하여 컨테이너를 생성하고(메모리 위에 올려 실행), 이렇게 실행한 이미지들의 인스턴스를 docker container라고 한다. 해당 컨테이너는 독립된 프로세스 공간에서 실행되는 것처럼 보인다.
근데 생각해보니 이러면 VM이랑 뭔 차이인가 싶은데.. 예를 들어 윈도우에서 리눅스 돌리려면 OS 전체를 메모리에 올려야 한다. 따라서 VM 방식이 보안 수준이 높지만 그만큼 부팅에 오래 걸리고 자원을 많이 소모한다. Docker의 경우 host의 OS 커널 자원을 공유하므로 가볍고 빠르게 실행할 수 있어 서비스 개발에 유리하다.
- 추가로 내 운영체제가 예를 들어 윈도우이고, 리눅스 환경에서 작동하는 이미지를 가져온다고 할때에도 docker가 이를 해결해준다. 즉 개념적으로는 독립된 실행 환경처럼 보이지만 실제로는 host의 OS 커널을 공유하여 동작한다.
여기에서 좀 더 생각해보자. 만약 컨테이너 띄워서 잘 돌리다가 새벽에 갑자기 죽는 경우, 그리고 사용자가 갑자기 많이 몰려서 컨테이너 개수와 리소스를 관리해야 하는 상황이 생긴다면, 사람이 일일이 확인하고 리소스를 분배할 수 없다.
따라서 Kubernetes의 컨테이너 오케스트레이션 개념을 사용한다.
컨테이너 오케스트레이션
여러대의 서버(node)를 하나의 클러스터로 묶어, 여러개의 docker 컨테이너를 자동으로 관리해주는 개념이다.
관리 방식은 다음과 같은 행위들이 자동화되어 수행된다 :
- 자동 복구 : 컨테이너 종료 시, 새로운 컨테이너 실행
- 자동 확장 : CPU 사용량 높을 시, pod 개수를 늘임(최소 배포단위가 pod)
- 로드 밸런싱 : 교통 정리 기능이며, 특정 컨테이너에 부하 집중되지 않도록 한다.
- 무중단 배포 : 서버를 끄지 않고, 새로운 버전으로 교체하는 기술(새 버전에 에러가 발생하면 즉시 이전 버전으로 돌아갈 수 있다. 구체적으로는, 점진적으로 새 pod를 띄우고 기존 pod를 삭제하는 과정을 반복한다)
여기서 계층 관계는 아래와 같다.
- 클러스터(Cluster) : 전체 시스템의 경계로, 여러대의 Node가 여기에 포함되어있다.
- 노드(Node) : 여러대의 Pod를 포함하며, 실제 여러 Pod들을 돌아가게 하는 컴퓨터이다.
- 파드(Pod) : 노드 안에서 돌아가는 최소 배포 단위이며, 여러대의 Container를 포함한다.
- 컨테이너(Container) : Pod 안에서 돌아가는 앱 프로세스(ex : MySQL 컨테이너…)
즉 내 컴퓨터(노드)에 여러 pod들을 띄울 수 있고, 각 pod마다 mysql/redis 등의 컨테이너를 포함하고 있다.
- 아무 조치도 취하지 않고 각 pod마다 mysql 컨테이너를 각각 띄워버리면 하나의 pod가 죽고 다시 실행되었을 때 이전 상태를 기억하지 못하며 서로 다른 pod의 mysql 컨테이너끼리는 데이터 공유가 불가능하다. 따라서, 영구 볼륨(Persistent Volume)이라는 외부 저장소를 연결해야 한다.
docker-compose에서는 이 외부 volume을 통해 외부에 데이터 유지가 가능하고, k8s에서는 pod를 관리할때 이 PV 구조를 통해 Pod가 삭제 후 재생성 되더라도 데이터를 보존할 수 있다.
services:
mysql:
// 기타등등....
volumes:
- hihihihi: /a/b/c
// 아래서 만든 hihihihi 영구 보관소를 해당 mysql 컨테이너 내부의 /a/b/c 경로에 연결해라. => mysql 컨테이너는 /a/b/c에 데이터를 쓴다고 생각하지만 실제로는 볼륨에 저장
volumes:
hihihihi: // hihihihi 라는 이름의 영구 보관소를 디스크 어딘가에 만들어라.
- 그렇다면 단일 pod도 설정을 해야하는가? 해야한다. 컨테이너가 죽고 다시 생성되는 과정에서 아무 조치가 없었다면 데이터가 영구적으로 삭제된다. 쿠버네티스는 어쨌든 컨테이너가 죽으면 다시 살리고, 트래픽이 많으면 여러개 만들고 트래픽이 적으면 몇개빼고 죽이고…. 이런 방식이므로 컨테이너는 언제든 삭제될 수 있다. 따라서 필수
Cloud / On-Premises
서비스를 배포하기 위해 아래와 같은 방식들을 생각할 수 있다.
(1) On-Premises : 자체적으로 서버 하드웨어 구매, 서버실 구축 등을 수행하여 시스템을 직접 관리하는 방식이다.
장점으로는 보안 수준이 높고(자체 서버실 구축) 서버 하드웨어 등을 원하는대로 입맞에 맞추어 사용할 수 있지만, 단점은 돈이 너무 많이 들고 유지보수를 위해 전문적인 IT 인력들이 반드시 필요하다.
따라서, 특정 기업들은 거대한 서버실을 구축해둔 후, 다른 사용자들에게 빌려주는 방식을 사용하여 수익을 내는데, 이를 Cloud라 한다.
(2) Cloud : 클라우드 서비스 제공자(AWS 등)가 만들어둔 거대한 서버실의 컴퓨팅 자원을 빌려 사용하는 방식
장점으로 비용이 (1)에 비해 훨씬 적고, 하드웨어 유지보수 등의 관리는 클라우드 서비스 사용자가 책임지지 않아도 된다. 단점으로는, 돈을 정기적으로 내야 하고(본인도 AWS 무료크레딧 다되어가는거 같다…) 특정 클라우드 서비스에 깊게 의존하다가 옮기려 하면 어려울 수 있다.
- 흔히들 AWS EC2라고 하는데, 이는 ‘클라우드 서비스 제공자에게 빌려쓰는 가상의 컴퓨터 하나’라고 생각하면 된다. 즉, EC2 인스턴스는 k8s에서 Node로 사용될 수 있는 가상의 컴퓨터이며, 차이점은 k8s에서의 Node 개념을 실제로 구현할 때 사용하는 것이 AWS EC2라고 보면 된다.
따라서 k8s, cloud, docker의 개념은 ‘내 컴에서는 되는데 왜 그쪽에서는 안되나요?’를 쉽게 해결하기 위해 등장하였으며, 결국 이들은 모두 별개의 개념이 아니다. EC2는 가상 컴퓨터, docker는 애플리케이션 실행에서의 사람 개입 최소화, k8s는 이러한 시스템들을 관리하기 위한 개념으로 등장한 것이다.
앞으로 배포 과정 또한 공부하게 될텐데, 오늘 정리한 내용을 바탕으로 단순히 도구를 사용하는 것이 아니라 현대 애플리케이션 개발 과정의 원리를 이해한 것을 바탕으로 한 단계 더 발전해나가야겠다.