목차
- 리눅스 컨테이너란?
- 컨테이너와 VM의 차이
- 리눅스 컨테이너의 주요한 특징
- 컨테이너의 종류
- 컨테이너를 사용해야하는 이유
- 컨테이너 기반 서비스 운영 사례
- 컨테이너 런타임
- 컨테이너 오케스트레이션
- 컨테이너에서 사용하는 컨테이너 격리 기능
CHAPTER 01. 리눅스 컨테이너란?
리눅스 컨테이너는 운영체제 수준의 가상화 기술로 리눅스 커널을 공유하면서 프로세스를 격리된 환경에서 실행하는 기술입니다. 다시 말해, 컨테이너란 프로세스 격리 기술로, 사용자가 사용할 프로그램과 환경 설정들이 컨테이너에 담겨 격리되어 실행되는 것입니다. 컨테이너에는 코드, 런타임, 시스템 도구, 시스템 라이브러리 등 서버에 설치되는 무엇이든 포함될 수 있으며, 실행 중인 환경에 관계 없이 언제나 동일하게 실행될 것을 보증합니다.
컨테이너와 VM의 차이
VM : 무거운 운영체제(kernel)를 포함합니다. 호스트 운영체제와 게스트 운영체제의 기능 중복으로 인해 약 10 ~ 20% 의 오버헤드 (Overhead) 를 갖습니다.
컨테이너 : 운영체제를 포함하지 않고 HOST OS(기존 시스템)를 공유합니다. 운영체제 위에 또 다른 운영체제를 구동하지 않아도 되며, 리소스도 공유해서 사용하므로 오버헤드는 3 ~ 5% 이내입니다.
* 오버헤드 : 프로그램의 실행흐름에서 나타나는 현상중 하나로써, 추가적으로 시간,메모리,자원이 사용되는 현상
즉, 가상머신은 기존 운영체제 위에 하드웨어를 가상화하여 다른 운영체제를 포함하는 반면에, 컨테이너는 운영체제 수준에서 가상화하여 애플리케이션과 그 의존성을 격리합니다.
예시를 들면, 컨테이너는 이동할 수 있는 작은 방입니다. 이 방 안에는 애플리케이션을 실행하는 데 필요한 모든 의존성과 라이브러리가 들어 있으며, 이 방을 어떤 환경에서든지 옮겨 놓기만 하면 애플리케이션이 문제없이 실행될 수 있습니다.
반면, 가상머신은 집 전체를 통째로 복사해서 옮기는 것과 비슷합니다. 여기에는 벽, 가구, 심지어 전기와 수도 시스템까지 다 포함되어 있어서 무겁고, 옮기는데 시간이 오래 걸리며, 더 많은 자원이 필요합니다.
결론적으로, 컨테이너는 가벼운 이동식 작은 방을 사용하여 애플리케이션을 어디서나 쉽게 실행할 수 있게 해주는 기술입니다.
컨테이너의 단점은 없을까?
- HOST OS에 종속적이다. 리눅스 컨테이너는 리눅스 이외의 다른 os에서는 동작하지 않으며, 다른 os를 설치할 수 없습니다.
- 컨테이너별 커널 구성이 불가능하다. 커널에 관련된 작업은 가능하나, 컨테이너마다 다른 커널 작업을 수행할 수는 없다. 커널의 기능으로 구성되는 환경이기 때문에 전체 컨테이너에서 보이는 커널은 동일합니다.
그럼에도 불구하고 컨테이너를 사용해야하는 이유
기존의 서버 운영 | 컨테이너의 사용 |
애플리케이션을 실행하기 위해 서버 컴퓨터의 상태를 지속적으로 관리 |
애플리케이션 별로 독자적인 환경을 준비하고 관리하는 것이 가능 -> 서버 관리의 복잡성을 크게 줄여줌 |
컨테이너 기반 서비스 운영 사례
컨테이너를 프로덕션 레벨에서 사용한 가장 유명한 케이스는 구글입니다.
구글에서는 2014년에 이미 모든 서비스를 컨테이너에서 운영하고 있었으며 매주 20억 개 이상의 컨테이너를 실행했습니다.
CHAPTER 02. 컨테이너 런타임 / 컨테이너 오케스트레이션
컨테이너 런타임
컨테이너 런타임은 컨테이너를 실행하고 관리하는 도구입니다.
1. 도커(Docker)
도커는 리눅스의 응용 프로그램들을 프로세스 격리 기술들을 사용해 응용 프로그램을 컨테이너로 실행하고 관리하는 오픈 소스 프로젝트입니다. 즉, 도커는 독립된 환경을 만들어서 서버 자원을 효율적으로 활용하는 기술입니다.
도커를 이용하면 이미지를 실행시켜 컨테이너로 만들거나, 생성된 컨테이너를 관리하거나, 컨테이너를 다시 이미지로 만드는 작업을 쉽게 할 수 있습니다.
도커의 기본적인 사용법에 대해서 간략하게 소개하면 이렇습니다.
왜 도커를 쓰나요?
- 빠른 시작과 종료 속도
- 낮은 오버헤드
- 애플리케이션의 개발과 배포가 편해집니다. 애플리케이션과 그 의존성을 하나의 독립된 패키지로 묶어 배포하므로 특정 서버 환경에 대한 의존성을 줄여줍니다.
2. 도커 컴포즈(Docker Compose)
도커 컴포즈는 다수의 컨테이너를 쉽게 관리할 수 있도록 도와주는 도구입니다. 간단하게 말하면, 여러개의 컨테이너를 관리하는 큰 설계도입니다. 도커 컴포즈를 사용하면 YAML 형식으로 컨테이너들의 명세를 작성한 후에 컨테이너를 한꺼번에 실행하거나 종료할 수 있습니다.
3. LXC & LXD
LXC는 리눅스 컨테이너(Linux Containers)의 줄임말로, 컨테이너를 실행하고 관리하는 도구입니다.
하나의 리눅스 시스템에서 프로세스들을 격리시켜 독자적인 시스템 환경을 구축합니다.
초기 도커는 내부적으로 컨테이너를 실행하는 데 LXC를 사용했으나, 현재는 Docker가 LXC를 거치지 않고 커널의 container API를 직접 호출함으로써 효율성을 향상 시켰습니다.
4. CRI-O
크리-오(cri-o)는 쿠버네티스를 위한 경량 컨테이너 런타임 프로젝트로, 컨테이너의 실행을 목적으로 경량화 한 것입니다.
이 크리-오 덕분에 쿠버네티스는 컨테이너를 실행할 때 도커가 필요없게 되었으나, 컨테이너의 생성 및 이미지 빌드에서는 여전히 도커를 필요로 하고 있습니다.
5. 카타 컨테이너(Kata Container)
카타 컨테이너는 경량 VM기반으로 컨테이너를 실행하는 런타임입니다. 호스트 머신과 커널을 공유하는 컨테이너와 달리, 카타 컨테이너는 컨테이너 전용 가상 머신을 준비합니다. 경량 Vm을 사용하기 때문에 일반적인 가상 머신보다 훨씬 빠르며, 커널을 공유하는 컨테이너보다 훨씬 안전한 샌드박스를 구현하는 것이 가능합니다.
6. 하코니와(Haconiwa)
하코니와는 DSL로 리눅스 컨테이너들에서 사용되는 프로세스 격리 기능들을 조합해 자신만의 컨테이너를 만들어볼 수 있는 프로젝트입니다.
컨테이너 오케스트레이션
컨테이너 오케스트레이션은 다수의 컨테이너를 적절하게 분산하고 스케줄링하는 방법과 도구입니다.
1. 쿠버네티스(Kubernetes)
쿠버네티스란 컨테이너화된 애플리케이션의 배포, 확장 및 관리를 자동화하는 오픈 소스 시스템입니다.
예를 들어, 실행 중인 컨테이너가 다운된다면, 다른 컨테이너를 다시 시작하여 가동 중지 시간을 최소화하여야 합니다. 이때 애플리케이션을 실행하는 컨테이너를 관리하고 가동 중지 시간이 없는지 확인하는 동작을 시스템에 의해 처리하는 것이 쿠버네티스의 역할입니다.
쿠버네티스는 여러 개의 컨테이너가 분산되어 실행되는 환경에서 자동화된 배포, 스케일링, 로드 밸런싱, 자가 치유 등을 제공합니다. 복잡한 마이크로서비스 아키텍처를 운영하는 데 필수적입니다.
CHAPTER 03. 컨테이너에서 사용하는 프로세스 격리 기능 : 어떻게 프로세스를 격리하는가?
- 리눅스 네임스페이스(Linux namespace) : 특정 프로세스의 리눅스 리소스 접근을 제어하기 위해 사용되는 기능. 쉽게말해, Linux의 오브젝트에 이름을 붙혀 충돌 가능성을 줄이고, 쉽게 참조할 수 있게 하는 기능
- PID 네임스페이스 : 프로세스에 할당된 고유한 ID를 말하며, 이를 통해 프로세스를 격리할 수 있습니다.
- 네트워크 네임스페이스 : 네트워크 디바이스, IP 주소, port 번호 등의 네트워크 리소스를 namespace마다 격리시켜 독립적으로 가지게 합니다.
- UTS 네임스페이스 : 호스명이나 도메인 명을 namespace별로 격리시켜 독립적으로 가질 수 있게 합니다.
- UID 네임스페이스 : UID, GID를 namespace 마다 격리시켜 독립적으로 가질 수 있게 합니다.
- Mount 네임스페이스 : 호스트 OS와 namespace가 서로 다른 격리된 파일 시스템 트리를 가질 수 있도록 합니다.
- 루트 디렉터리 격리와 chroot : 프로세스의 루트 디렉터리를 특정한 디렉터리로 변경함. 특정 프로세스가 상위 디렉터리에 접근할 수 없도록 격리시킬 수 있습니다.
- 유니온 마운트(Union Mount) : 계층화된 파일 시스템을 구현하는 기능. 일종의 상속(inheritance)와 비슷한 개념이기도 함. 유니온 마운트를 사용해 효율적인 이미지 구현이 가능합니다.
격리된 프로세스를 생성하기 위한 기능 - 컨트롤 그룹 : 프로세스에서 사용 가능한 CPU, 메모리, 네트워크 대역폭, 디스크 I/O 등을 그룹 단위로 제어하는 리눅스 커널의 기능. 컨테이너 안의 프로세스에 대해 자원을 제한 함으로써 특정 컨테이너가 호스트 OS의 자원을 모두 사용하는 일을 막습니다.
- 리눅스 캐퍼빌리티 : 루트의 권한을 세분화해서 프로세스에 적용할 수 있도록 만든 기능. 루트 권한이 필요할 경우, 리눅스 캐퍼빌리티를 사용해 필요한 권한을 지정할 수 있습니다.
참고