개발을 하다보면 아무래도 docker를 많이 쓰게 될텐데, 그 때 컨테이너 어쩔저쩔~~ 이라는 개념이 나오면서 사람들의 머리가 아파지기 시작한다.
따라서 컨테이너에 대해 개념을 잡고 싶은 사람이라면 이 글을 잘 읽어보길 추천한다. 배포 세팅(특히 devops, cloud native)에서 많이 언급되는 개념이기 때문이다.
1. Container란
컨테이너는 애플리케이션과 필요한 라이브러리, 종속성을 하나로 묶어 어디서나 실행할 수 있는 일종의 가벼운 실행 환경이다.
따라서 특정 OS나 환경에 의존하지 않고 동일하게 실행된다는 의미다.
쉽게 풀어보자면, 프로젝트를 진행하는데 A는 Windows에서, B는 MacOS에서 진행한다고 쳐보자.
따라서 각 환경마다 세팅이 다르기 때문에 각자 라이브러리 및 종속성을 같은 세팅으로 다운받더라도 오류가 날 수 있다는 의미다.
이 때 컨테이너를 사용하면 OS가 다름에도 불구하고 동일하게 프로그램이 실행된다.
2. Container에서 사용하는 중요 개념
말로만 적으면 이해가 어렵기 때문에 시나리오를 하나 정의해서 설명을 해보도록 하겠다.
상황
- A: Windows 사용자, B: Macbook 사용자
- 이 둘은 팀플로 Python Flask 웹 애플리케이션을 개발 중
- A는 로컬 Windows에서, B는 로컬 Macbook에서 작업 중임 = 프로젝트 실행 환경이 다름
- A는 컨테이너 기술을 사용하여 동일한 환경에서 실행될 수 있도록 설정하고 이를 B에게 공유하려고 함
개념 | 설명 | 예시 |
---|---|---|
Container | 애플리케이션 실행 환경 | - A는 Python Flask 애플리케이션을 실행하기 위해 컨테이너를 사용함 - B는 A가 만든 컨테이너를 그대로 실행하면 동일한 환경에서 앱이 실행됨 |
Container Image | 실행 환경을 템플릿으로 저장 | - A는 컨테이너 실행을 위한 환경(Python, Flask, 그 외 기타 requirements.txt 의존성 모듈)을 이미지로 저장 |
Container Runtime | 컨테이너를 실행 및 관리 | - A와 B 모두 컨테이너 런타임을 사용하여 컨테이너를 실행 |
Container Orchestration | 여러 컨테이너의 배포, 스케일링, 관리 등을 자동화 | - A와 B의 프로젝트가 성장하며 트래픽이 증가하면, 오케스트레이션 도구로 컨테이너를 확장 |
Namespaces | 컨테이너의 리소스(CPU, 메모리 등) 격리 | - Flask 웹 컨테이너 / PostgreSQL 데이터베이스 컨테이너 / Redis 캐시 컨테이너 (각각 분리) - 컨테이너별로 독립된 네트워크 스택(IP주소, 포트, 라우팅 테이블 등)을 가짐 - A의 로컬 시스템에서 실행 중인 프로세스를 확인할 때, 컨테이너의 내부 프로세스를 검색할 수 없음 |
CGroups(Control Groups) | 리소스 사용량 제한 | - Flask 웹 컨테이너 / PostgreSQL 데이터베이스 컨테이너 / Redis 캐시 컨테이너 (각각 분리) - A가 컨테이너를 생성할 때 한 쪽 컨테이너로만 너무 많이 리소스를 사용하지 않도록 제어 |
Networking | 컨테이너 간 외부 통신 | - Flask 웹 컨테이너 / PostgreSQL 데이터베이스 컨테이너 / Redis 캐시 컨테이너 (각각 분리) - A와 B는 웹 컨테이너와 데이터베이스 컨테이너를 연결하여 사용 |
Registry | 컨테이너 이미지를 저장 및 배포 | - A는 컨테이너 이미지를 Hub에 업로드하여 B와 공유 - B는 Hub에서 이미지를 다운받아 사용 |
3. Container VS VM(Virtual Machine)
Container | Virtual Machine |
---|---|
Kernal 공유 | Hypervisor 기반 |
빠른 속도, 가벼움, 이식성 | 높은 격리성, 완전한 OS 제공 |
Kernal (커널): 서로 사이좋게 양보하며 컴퓨터 자원 공유
- OS의 핵심 부분으로, HW와 SW간의 다리 역할
- 애플리케이션이 하드웨어 자원(CPU, 메모리, 디스크, 네트워크 등)을 사용할 수 있도록 중개
상황
- C, D, E는 각각 Flask, PostgreSQL, Redis로 실행 중
- CPU는 4코어, 메모리는 8GB로 설정
예시
- C가 러닝 중일 때 (D와 E는 유휴 상태):
- C(Flask) 가 모든 CPU와 메모리를 사용
- 다른 컨테이너(D, E)가 비활성 상태이므로 커널은 자원을 C에 최대한 배분
- D(PostgreSQL) 러닝 시작: 커널이 자원을 동적으로 조정
- C(Flask)** 가 CPU 2코어, 메모리 4GB를 사용하도록 줄임
- D(PostgreSQL)*에게 CPU 2코어, 메모리 4GB를 배분
- 자원이 부족할 경우 cgroups(Control Groups) 설정에 따라 특정 컨테이너(C 또는 D)의 자원을 제한
- D와 E가 동시에 러닝 시작: 자원이 더 많이 나눠짐
- C(Flask): CPU 1코어, 메모리 3GB
- D(PostgreSQL): CPU 2코어, 메모리 3GB
- E(Redis): CPU 1코어, 메모리 2GB
Hypervisor (하이퍼바이저): 사이가 안좋아서 자원을 빌리되 서로 공유하지 않음
- 가상화를 위한 소프트웨어
- 물리적 하드웨어(= 실제 컴퓨터)에서 여러 개의 VM을 실행할 수 있게함
상황
- C, D, E는 각각 Windows, Ubuntu, CentOS로 실행 중
CPU는 8코어, 메모리는 16GB로 설정
예시
- C가 실행 중일 때 (D와 E는 비활성 상태):
- C(Windows)가 CPU 8코어, 메모리 16GB를 사용
- 다른 VM(D, E)이 비활성 상태이므로 하이퍼바이저는 모든 자원을 C에 배분
- D(Ubuntu)가 실행을 시작하면: 하이퍼바이저가 자원을 동적으로 조정
- C(Windows): CPU 4코어, 메모리 8GB
- D(Ubuntu): CPU 4코어, 메모리 8GB
- 각 VM은 독립된 OS와 애플리케이션을 실행하며 서로 영향을 주지 않음
- D와 E(CentOS)가 동시에 실행을 시작하면: 자원이 세 VM으로 나눠짐
- C(Windows): CPU 3코어, 메모리 6GB
- D(Ubuntu): CPU 3코어, 메모리 6GB
- E(CentOS): CPU 2코어, 메모리 4GB
- 각 VM은 독립된 OS와 애플리케이션을 실행하며 서로 영향을 주지 않음
=> 많아지면 컴퓨터 속도 저하 원인
4. Container 도구들
(하나씩 글 작성 ing. 작성할 때마다 링크 추가 예정)
Container Runtime
- Docker: 컨테이너 생태계를 주도한 대표적인 런타임
- Containerd: Docker의 핵심 런타임으로 분리되어 Kubernetes에서 직접 사용 가능
- Podman: 데몬리스 컨테이너 실행환경으로 Docker의 대체제
- CRI-O: Kubernetes와 호환되는 경량 런타임
Container Ochestration
- Kubernetes: 가장 널리 사용되는 컨테이너 오케스트레이션 도구. 자동 스케일링, 복구, 배포 지원
- Docker Swarm: 간단한 오케스트레이션에 적합한 Docker 내장 도구
- Nomad: HashiCorp에서 개발한 경량 오케스트레이션 도구
Container Image
- Buildah: Docker 없이 이미지를 빌드 가능
- Kaniko: 클라우드 환경에서 안전하게 이미지 빌드
컨테이너 보안 도구
- Falco: 실시간 컨테이너 보안 이벤트 감지
- Aqua Security: 컨테이너 환경 보안을 포괄적으로 관리