Container 정리


개발을 하다보면 아무래도 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: 컨테이너 환경 보안을 포괄적으로 관리

Author: Ruby Kim
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Ruby Kim !
Comments
  TOC