본문 바로가기
DevOps & Cloud

[DevOps] 도커와 컨테이너 (Docker and Container)

by yhames 2024. 9. 18.
728x90

도커란?

도커는 컨테이너를 생성하고 관리하는 도구입니다.

 

도커를 사용하는 이유

표준화된 실행 환경을 구축

 

도커를 사용하면 운영체제에 관계없이 표준화된 실행 환경을 구축할 수 있습니다. 이는 개발환경과 실제 서비스 환경을 동일하게 만들어 서비스 환경과 개발 환경의 차이로 인한 문제를 줄일 수 있습니다. 또한 여러 개발자가 협업할 때 개발 환경을 통일시키는 데 큰 도움이 되고, 여러 프로젝트를 동시에 진행할 때 각 프로젝트의 환경을 분리할 수 있습니다.

 

가상머신과 도커 컨테이너의 차이

 

가상머신은 하이퍼바이저를 통해 게스트 OS를 생성하고, 각 게스트 OS에 애플리케이션을 실행합니다. 반면 도커는 호스트 OS 위에 도커 엔진을 설치하고, 컨테이너를 생성하여 애플리케이션을 실행합니다.

 

가상머신을 사용해도 도커를 사용하는 것과 동일한 환경을 구축할 수 있습니다. 하지만 가상머신은 호스트 OS 내부에 게스트 OS를 생성하고 실행해야하기 때문에 메모리, CPU, 디스크 공간을 더 많이 사용하게 됩니다. 또한 게스트 OS를 생성할 때마다 수동으로 설정 작업을 해야합니다. 반면 도커는 호스트 OS 위에 컨테이너를 생성하므로 가상머신보다 빠르게 실행됩니다. 또한 컨테이너는 이미지를 기반으로 생성되기 때문에 설정 작업을 반복할 필요가 없습니다.

 

컨테이너란?

 

컨테이너는 가상화 기술을 이용하여 운영체제 수준에서 리소스 격리를 제공하는 기술입니다. 컨테이너는 가상 머신과는 다르게 게스트 운영체제를 가지고 있지 않습니다. 대신 호스트 운영체제의 커널을 공유하고, 리소스 격리를 위한 네임스페이스컨트롤 그룹을 이용합니다.

 

 

컨테이너는 갑자기 등장한 기술이 아니라 리눅스 커널의 기능을 이용하여 점진적으로 발전해온 기술입니다. 리눅스 커널은 chroot 명령어를 통해 프로세스를 격리할 수 있게 해주었고, 이후에는 네임스페이스와 컨트롤 그룹을 통해 리소스를 격리할 수 있게 되었습니다.

 

프로세스 격리 (chroot)

chroot는 프로세스가 접근할 수 있는 파일 시스템의 루트 디렉토리를 변경하는 명령어입니다. chroot를 이용하면 프로세스가 특정 디렉토리를 루트 디렉토리로 인식하게 할 수 있습니다.

 

$ chroot /new/root /bin/bash

 

탈옥 문제 (pivot_root)

chroot는 프로세스가 접근할 수 있는 파일 시스템의 루트 디렉토리를 변경할 뿐, 프로세스가 접근할 수 있는 파일 시스템을 변경하지는 않습니다. 따라서 아래와 같이 간단한 코드로 탈옥이 가능합니다.

 

#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
        mkdir(".out", 0755);
        chroot(".out");
        chdir("../../../../../");
        chroot(".");
        return execl("/bin/sh", "-i", NULL);
}

 

pivot_root는 mount chroot와 달리 namespace를 이용하여 프로세스가 접근할 수 있는 파일 시스템을 격리합니다.

 

$ mkdir new_root
$ mount -t tmpfs none new_root
$ cd new_root
$ mkdir put_old
$ pivot_root new_root put_old
$ umount /put_old   # put_old에 대한 접근 차단

 

중복 문제 (overlay filesystem)

 

프로세스가 격리되었지만 컨테이너가 늘어날 때마다 파일 시스템에는 중복된 이미지가 쌓이게 됩니다. 이를 해결하기 위해 overlay filesystem을 사용합니다.

 

 

overlay filesystem여러 파일 시스템을 하나로 합치는 방식으로, 여러 이미지를 하나로 합쳐서 중복을 줄일 수 있습니다.

 

$ mount -t overlay overlay -o lowerdir=tools:myroot,upperdir=rootfs/container,workdir=rootfs/work rootfs/merge

 

rootfs
├── container
├── merge
│   ├── bin
│   ├── excape_chroot
│   ├── lib
│   ├── lib64
│   ├── proc
│   └── usr
└── work
    └── work

 

위 파일 트리에서 Merged View를 의미하는 merge 디렉토리에는 tools와 myroot 디렉토리가 합쳐져 있습니다. container 디렉토리는 LowerDir에서 수정된 파일을 기록합니다.

 

네임스페이스 (namespace)

pivot_root에서 마운트 네임스페이스를 이용하여 파일 시스템을 격리했습니다. 하지만 여전히 컨테이너에서 호스트의 다른 프로세스들이 보인다거나 컨테이너에서 호스트의 포트를 사용하고, 컨테이너에 루트 권한이 남아있는 등 여러 문제가 있습니다. 이를 해결하기 위해 여러 종류의 네임스페이스를 사용하여 프로세스의 격리 수준을 높이는 방식으로 컨테이너를 구현합니다.

 

다음은 컨테이너에서 격리하는 네임스페이스의 종류입니다.

네임스페이스 설명
마운트 네임스페이스 마운트 포인트 격리 (2002)
UTS 네임스페이스 hostname, domain name 격리 (2006)
IPC 네임스페이스 IPC 객체격리 (2006)
PID 네임스페이스 pid 넘버 네임스페이스 격리 (2008)
네트워크 네임스페이스 네트워크 스택 가상화 및 격리 (2009)
USER 네임스페이스 UID/GID 넘버 스페이스 격리 (2012)

 

자세한 실습 내용은 이게 돼요? 도커 없이 컨테이너 만들기 / if(kakao)2022를 참고하세요.

 

컨트롤 그룹 (cgroup)

 

마운트 네임스페이스를 사용하여 프로세스의 격리 수준을 높였지만, 여전히 프로세스의 리소스 사용량을 제한할 수 없습니다. 만약 하나의 컨테이너가 너무 많은 CPU를 사용하면 다른 컨테이너의 CPU 사용량이 부족해질 수 있습니다. 이러한 문제를 해결하기 위해 cgroup을 사용하여 프로세스의 리소스 사용량을 제한합니다.

 

  • cgorups 생성
$ mkdir /sys/fs/cgroup/cpu/red
$ mkdir /sys/fs/cgroup/memory/red

 

  • cgroups 자원 설정
$ echo 40000 > /sys/fs/cgroup/cpu/red/cpu.cfs_quota_us
$ echo 209715200 > /sys/fs/cgroup/memory/red/memory.limit_in_bytes
$ echo 0 > /sys/fs/cgroup/memory/red/memory.swappiness

 

  • cgroups에 프로세스 추가
$ echo "1" > /sys/fs/cgroup/cpu/red/cgroup.procs
$ echo "1" > /sys/fs/cgroup/memory/red/cgroup.procs

 

자세한 실습 내용은 이게 돼요? 도커 없이 컨테이너 만들기 / if(kakao)2022를 참고하세요.

 

참고자료

 

이게 돼요? 도커 없이 컨테이너 만들기 / if(kakao)2022

 

반응형

'DevOps & Cloud' 카테고리의 다른 글

[DevOps] 가상머신 (Virtual Machine)  (0) 2024.06.07