[MLOps] 컨테이너(Container)란?
컨테이너 인프라 환경
아마 IT 업계 개발 방법론 중 가장 많이 언급되는 것은 애자일(agile)일 것이다.
애자일과 폭포수(waterfall)는 목표를 달성하기 위한 접근법 두가지이다. 기존 개발 방법론인 폭포수 방법론은 계획 단계에서 설계와 환경을 완전히 구비한 후 예정된 목표를 달성해 나가지만, 애자일은 일정 주기별로 flexible하게 요구 사항을 만족하는 프로토타입을 만들고 개선해 나간다는 차이점이 있다.
이런 애자일한 개발 방식이 대세가 되면서 인프라 또한 변하고 있다. 사용자의 요구사항을 반영하는 주요 기능들은 유지하되, 사용자마다 독립적인 환경에서 개발해도 소프트웨어가 문제없이 돌아갈 수 있도록 하는 인프라 환경을 구축하는 쪽으로 말이다. 이를 가능할 수 있도록 하는 것이 컨테이너 인프라라고 할 수 있겠다!
본 포스팅을 쓰면서 VMware의 유튜브 강의를 많이 참고했다.
1. 컨테이너 (Container)
컨테이너는 하나의 운영체제 커널에서 다른 프로세스에 영향을 받지 않고 독립적으로 실행되는 프로세스 상태를 의미한다. Isolated process라고 할 수 있을 것이다. 말하자면 하나의 운영체제 안에서 커널은 공유하지만, CPU, 네트워크, 메모리와 같은 시스템 자원은 독자적으로 사용하도록 개별적인 실행환경을 제공하는 '격리된 공간'인 것이다. 따라서 실행되는 프로세스를 구분하는 ID도 컨테이너 안에 격리돼 관리된다. 그래서 각 컨테이너 내부에서 실행되는 어플리케이션들은 서로 영향을 미치지 않고 독립적으로 작동할 수 있는 것이다.
Here we have an operating system. Let's say that it's linux. Inside of that operating system, you can run any number of processes, and these processes share an address space, they share a process namespace, they share pretty much everything. You know in many cases you're going to be running all sorts of things inside one of these operating system, and it's designed to do that.
However, what if you actually want to isolate one of these processes from one of the other processes? What if you want some kind of sandbox for that process to run?
1-1. Architecture: Monolithic VS MSA
모놀리식 아키텍처(monolithic architecture)는 하나의 큰 목적이 있는 서비스 또는 어플리케이션에 여러 기능이 통합되어 있는 구조를 말한다. 모놀리식 아키텍처는 소프트웨어가 하나의 통합된 코드로 구성되기 때문에 초기 개발 단계에서 설계하기 유용하지만, 서비스 유지보수 단계에서 수정이 많아질 경우 해당 서비스와 연관된 다른 서비스에 영향을 미칠 가능성이 높아진다.
반면, 마이크로서비스 아키텍처(MSA, Microservices Architecture)는 시스템 전체가 하나의 목적을 지향한다는 점에서는 모놀리식과 동일하지만, 개별 기능을 하는 작은 서비스를 각각 개발해 연결하는 데서 차이가 있다. 각각의 서비스는 독립적으로 동작할 수 있는 완결된 구조이다. 이런 구조는 서비스를 재사용하기 쉽고, 향후 변경 사항이 있을 때 다른 서비스에 영향을 미칠 가능성이 줄어든다.
마이크로서비스 아키텍처의 external gateway를 살펴보면 다음과 같다.
하나의 어플리케이션 안에 존재하던 서비스들이 각 서비스와 관련된 기능, 그리고 데이터베이스를 독립적으로 가지는 구조로 표현된다. 각 서비스는 서버 최앞단에 위치하면서 모든 API 호출을 받는 API 게이트웨이와 REST API를 이용한 통신 방식으로 외부의 요청을 전달한다.
컨테이너 인프라 환경은 마이크로서비스 아키텍처로 구현하기에 적합하다. 컨테이너 인프라 환경에서는 컨테이너를 서비스 단위로 포장해 손쉽게 배포하고 확장할 수 있기 때문이다.
1-2. Virtual Machine VS Container
이 부분은 필자가 헷갈려했기 때문에 적었다(...) 가상머신과 컨테이너는 프로세스가 돌아가는 공간을 나눈다는 점에서 비슷해보이는데, 무엇이 다른 것일까?
일단 위의 그림에서 직관적으로 찾아볼 수 있는 부분이 있다. 바로 level of isolation이다.
Docker와 같은 컨테이너 런타임에서는 컨테이너가 제공하는 격리 기능(isolation feature를 어떻게 해석하면 좋을까...) 내부에 어플리케이션이 실행되지만, 동일한 호스트(host operating system)에서 다른 컨테이너와 동일한 커널을 공유한다. 따라서 권한만 부여된다면 컨테이너 내부에서 실행되는 모든 프로세스는 호스트 시스템에서 볼 수 있다. 여러 컨테이너가 동일한 커널을 공유하면 동일한 시스템에 있는 수많은 컨테이너들은 일반적으로 몇 초 이내에 즉각 시작될 수 있다. 또한 컨테이너가 전체 운영체제를 내장할 필요가 없기 때문에 매우 가볍다(일반적으로 5~100 MB 정도).
반대로 가상머신을 사용하면, 내부에서 실행되는 모든 것이 호스트 또는 하이퍼바이저(hypervisor)와 독립이다. 가상 시스템 플랫폼은 특정 가상머신의 가상화 프로세스를 관리하기 위해 VMM(Virtual Machine Monitor, 가상 시스템 모니터)이라는 프로세스를 시작하고, 호스트 시스템은 해당 하드웨어 리소스 일부를 가상머신에 할당한다. 가상머신의 가장 큰 차별점은 시작시 해당 가상머신 환경을 위한 새로운 전용 커널을 부팅하고 운영체제 시스템 프로세스를 지정한다는 것이다. 따라서 어플리케이션만 포함된 일반적인 컨테이너보다 가상머신의 크기가 훨씬 크다.
2. 지원 도구
Docker
도커(docker)는 컨테이너 환경에서 독립적으로 어플리케이션을 실행할 수 있도록 컨테이너를 만들고 관리하는 것을 도와주는 컨테이너 도구이다. 도커로 어플리케이션을 실행하면 어떤 운영체제 환경이든 상관없이 일관된 결과를 보장한다. 도커와 같은 컨테이너 도구로 Containerd, CRI-O, Podman 등이 있다.
Kubernetes
쿠버네티스(kubernetes)는 다수의 컨테이너 관리에 사용된다. 컨테이너의 자동 배포와 배포된 컨테이너에 대한 동작 보증, 부하에 따른 동적 확장 등의 기능을 제공한다. 지금은 컨테이너 관리뿐만 아니라, 컨테이너 인프라에 필요한 기능을 통합하고 관리하는 솔루션으로 발전했다. 이외에도 사용되는 컨테이너 관리 도구로 Docker Swarm, Mesos, Nomad 등을 꼽을 수 있다.
Jenkins
젠킨스(Jenkins)는 CI/CD를 지원하는 개발 환경 구성 및 배포 자동화 도구이다. CI(Continuous Integration, 지속적 통합)과 CD(Continuous Deployment, 지속적 배포)는 개발한 프로그램의 빌드, 테스트, 패키지화, 배포 단계를 모두 자동화한다. 이를 통해 개발 생산성을 높이고 개발된 코드를 빠르게 적용할 수 있도록 하는 데 초점이 맞춰져 있다. CI/CD를 위한 도구는 Bamboo, Github Action, Teamcity 등도 있다.
Prometheus & Grafana
프로메테우스(Prometheus)와 그라파나(Grafana)는 모니터링을 위한 도구이다. 프로메테우스가 상태 데이터를 수집하면, 그라파나가 프로메테우스로 수집한 데이터를 시각화한다. 프로메테우스와 그라파나의 조합은 컨테이너 인프라 환경에서 많은 종류의 소규모 기능을 종합해서 모니터링하기 위해 필요하다.