컨테이너 톺아보기: chroot부터 쿠버네티스까지
요약
기사 전체 정리
컨테이너 톺아보기: chroot부터 쿠버네티스까지
Runtime Arguments 팟캐스트 에피소드 23 "Containers – What's in the Box?" 내용을 정리함.
컨테이너라는 단어, 개발자라면 매일 듣고 매일 씀. 근데 "컨테이너가 정확히 뭐야?"라고 물으면 막상 깔끔하게 설명하기 어려운 사람이 많음. Wolf과 Jim이 진행하는 Runtime Arguments 팟캐스트에서 컨테이너의 역사부터 동작 원리, 실무 활용까지 싹 다 훑어줬는데, 그 내용을 정리해봄.
컨테이너의 역사: 1979년부터 시작된 이야기
컨테이너 기술이 Docker랑 같이 갑자기 튀어나온 줄 아는 사람 많은데, 실제로는 뿌리가 꽤 깊음.
- chroot (1979): 유닉스에서 프로세스의 루트 디렉토리를 바꿔주는 기능. 파일시스템 수준에서 격리를 제공한 최초의 시도였음. "이 프로세스는 여기부터가 루트야"라고 속이는 거임.
- FreeBSD Jails (2000): chroot의 개념을 확장해서 네트워크, 프로세스까지 격리함. 진짜 "감옥"처럼 프로세스를 가둬놓는 방식이었음.
- Linux 네임스페이스와 cgroups: 리눅스 커널에 격리 기능이 본격적으로 들어감. 네임스페이스로 "뭘 볼 수 있는지"를 제한하고, cgroups로 "얼마나 쓸 수 있는지"를 제한함.
- LXC (Linux Containers): 네임스페이스와 cgroups를 조합해서 만든 컨테이너 구현체. Docker 이전에 리눅스 컨테이너의 표준이었음.
- Docker (2013): LXC 위에 사용하기 쉬운 인터페이스를 얹어서 컨테이너를 대중화함.
docker run한 줄이면 컨테이너가 뜨는 세상을 만들어줌.
컨테이너 vs VM: 뭐가 다른 거임?
이 부분이 핵심임. 둘 다 "격리된 환경"을 제공하지만 방식이 완전히 다름.
**가상 머신(VM)**은 하이퍼바이저라는 소프트웨어 위에서 돌아감. VMware, VirtualBox, XCPNG 같은 게 하이퍼바이저임. VM은 각각 완전한 OS를 포함하고 있어서 무거움. 하드웨어를 가상화해서 그 위에 통째로 운영체제를 올리는 구조임.
컨테이너는 호스트의 커널을 공유함. OS를 따로 올리지 않으니까 훨씬 가벼움. VM이 "집을 통째로 짓는 거"라면, 컨테이너는 "칸막이로 공간을 나누는 거"에 가까움. 그래서 컨테이너는 초 단위로 뜨고, VM은 분 단위로 뜸.
다만 커널을 공유한다는 건 격리 수준이 VM보다 낮다는 뜻이기도 함. 보안이 극도로 중요한 환경에서는 VM이 여전히 유리한 경우도 있음.
Linux 네임스페이스: "뭘 볼 수 있는지" 제한하기
컨테이너 격리의 핵심 메커니즘임. 리눅스 커널이 제공하는 네임스페이스 종류를 보면:
- PID 네임스페이스: 컨테이너 안에서는 자기 프로세스만 보임. 호스트의 다른 프로세스는 존재 자체를 모름. 컨테이너 안의 첫 번째 프로세스가 PID 1번을 받음.
- 네트워크 네임스페이스: 컨테이너마다 독립적인 네트워크 스택을 가짐. 각자 자기만의 IP, 포트, 라우팅 테이블이 있음.
- 마운트 네임스페이스: 파일시스템을 격리함. 컨테이너마다 다른 파일시스템 뷰를 가질 수 있음.
- 유저 네임스페이스: 컨테이너 안의 root가 호스트에서는 일반 사용자로 매핑됨. 보안에 중요한 부분임.
이렇게 네임스페이스를 조합하면 프로세스가 "나만의 독립된 리눅스 시스템에서 돌아가고 있다"고 착각하게 만들 수 있음.
cgroups: "얼마나 쓸 수 있는지" 제한하기
네임스페이스가 "보이는 범위"를 제한한다면, cgroups(Control Groups)는 "쓸 수 있는 자원의 양"을 제한함.
- CPU: 이 컨테이너는 CPU 코어 2개까지만 사용 가능
- 메모리: 이 컨테이너는 메모리 4GB까지만 사용 가능
cgroups가 없으면 하나의 컨테이너가 호스트 자원을 다 먹어버릴 수 있음. 프로덕션 환경에서 리소스 제한을 안 걸면 하나의 폭주하는 컨테이너 때문에 전체 시스템이 죽는 참사가 벌어짐.
유니온 파일시스템: 컨테이너 이미지의 비밀
컨테이너 이미지가 어떻게 효율적으로 저장되고 배포되는지 궁금했다면, 답은 유니온 파일시스템(오버레이 파일시스템)에 있음.
기본 아이디어는 여러 레이어를 겹쳐서 하나의 파일시스템처럼 보이게 하는 거임. 예를 들어:
- 베이스 레이어: Ubuntu OS 파일들
- 두 번째 레이어: Node.js 설치
- 세 번째 레이어: 애플리케이션 코드
각 레이어는 읽기 전용이고, 맨 위에 쓰기 가능한 레이어가 올라감. 같은 베이스 이미지를 쓰는 컨테이너 100개가 있어도 베이스 레이어는 한 벌만 저장하면 되니까 디스크 공간도 아끼고 이미지 다운로드도 빨라짐.
Docker: 컨테이너를 모두의 것으로
Docker가 2013년에 등장하기 전에도 컨테이너 기술은 있었음. 근데 Docker가 한 건 이걸 "누구나 쓸 수 있게" 만든 거임.
- Dockerfile로 이미지 빌드 과정을 코드로 정의
- Docker Hub로 이미지를 공유하고 배포
- 간단한 CLI로 컨테이너 관리
docker run nginx 한 줄이면 웹 서버가 뜨는 경험이 개발자들한테 충격이었음. "내 로컬에서는 되는데..."라는 악몽에서 벗어나게 해준 고마운 존재임.
OCI 표준: 생태계를 여는 열쇠
Docker가 컨테이너를 대중화하면서 하나의 문제가 생김. Docker 포맷에 종속되는 거임. 이걸 해결하기 위해 OCI(Open Container Initiative) 표준이 만들어짐.
OCI는 컨테이너 이미지 포맷과 런타임 스펙을 표준화함. 덕분에 Docker가 아닌 다른 도구로도 같은 컨테이너 이미지를 빌드하고 실행할 수 있게 됨. 생태계가 하나의 벤더에 묶이지 않게 된 거임.
Podman: Docker의 강력한 대안
Podman은 Docker의 대안으로 주목받는 컨테이너 도구임. 두 가지 핵심 차이점이 있음:
- 데몬리스(Daemonless): Docker는 백그라운드에서 항상 돌아가는 데몬이 필요한데, Podman은 데몬 없이 동작함. 시스템 리소스를 덜 먹고, 데몬이 죽으면 전체 컨테이너가 날아가는 문제도 없음.
- 루트리스(Rootless): root 권한 없이도 컨테이너를 실행할 수 있음. Docker도 루트리스 모드를 지원하긴 하지만, Podman은 처음부터 루트리스를 기본으로 설계됨.
CLI 명령어가 Docker와 거의 동일해서 alias docker=podman 해놓고 쓰는 사람도 많음.
컨테이너 오케스트레이션: Kubernetes
컨테이너 하나 돌리는 건 쉬움. 근데 프로덕션에서 컨테이너 수백 개를 관리해야 한다면? 어떤 컨테이너를 어느 서버에 배치할지, 죽은 컨테이너를 어떻게 복구할지, 트래픽을 어떻게 분산할지... 이런 문제를 해결하는 게 컨테이너 오케스트레이션이고, 그 대표 주자가 **Kubernetes(쿠버네티스)**임.
쿠버네티스는 구글이 내부에서 쓰던 Borg 시스템의 경험을 바탕으로 만든 오픈소스 프로젝트임. 컨테이너의 배포, 스케일링, 관리를 자동화해줌. 러닝 커브가 험악하기로 유명하지만, 대규모 컨테이너 환경을 운영하려면 피할 수 없는 도구임.
실무에서 컨테이너를 쓰는 이유
팟캐스트에서 다룬 실제 활용 사례들을 정리하면:
- 개발 환경 통일: "내 로컬에서는 되는데" 문제를 해결함. 모든 개발자가 동일한 환경에서 작업 가능.
- 마이크로서비스: 서비스별로 독립적인 컨테이너로 배포. 각 서비스가 다른 언어, 다른 버전의 런타임을 쓸 수 있음.
- CI/CD: 빌드, 테스트, 배포 파이프라인에서 일관된 환경 제공. GitHub Actions나 GitLab CI에서 컨테이너를 쓰는 이유가 이거임.
마무리
컨테이너는 1979년 chroot에서 시작해서 거의 반세기에 걸쳐 진화해온 기술임. Docker가 대중화의 문을 열었고, OCI 표준이 생태계를 넓혔고, 쿠버네티스가 대규모 운영의 길을 열었음. 매일 docker run 치면서도 내부에서 뭐가 돌아가는지 모르고 있었다면, 이 에피소드가 좋은 출발점이 될 거임.
댓글
댓글
댓글을 불러오는 중...