우리는 왜 컨테이너가 필요한가
컨테이너에 대해 잘 알지 못했던 인턴 시절 힘들었던 일 중 하나를 꼽으라면 단연 서버 환경 설정이다. 당시 개발하던 프로그램마다 사용하는 라이브러리 버전이 달라서 설정하는 데 애를 먹곤 했다. 리눅스 초보였던 나는 그러다 설정이 꼬이기라도 하면 OS를 밀고 다시 깔기 위해 주머니에 우분투 부팅 USB를 지니고 다녔다.
이런 문제를 해결하기 위해 도커가 세상에 등장했다.
도커는 분리된 별도의 환경을 가지는 컨테이너에서 각각의 애플리케이션을 실행할 수 있도록 해준다.
- 이제 개발자는 애플리케이션을 개발하고 도커 컨테이너로 만들기만 하면 된다.
- 유니온 마운트1) 기반으로 효율적으로 실행 환경을 이미지로 만들고 공유할 수 있다.
컨테이너란 무엇인가
- 완전히 분리된 환경
- 가상머신 처럼 각자의 프로세스, 서비스, 네트워크 인터페이스, 마운트를 가진다. (OS kernel 을 공유한다는 점이 가상머신과 다르다.)
- 컨테이너로 실행된 프로세스는 커널을 공유하지만, namespace2), cgroups3), root 디렉터리 격리 등의 커널 기능을 활용해 격리되어 실행된다.
- Host 머신에게는 프로세스로 인식되고 컨테이너 관점에서는 마치 독립적인 환경을 가진 가상머신처럼 보인다.
그렇다면, 컨테이너와 가상머신은 어떻게 다를까?
![container-vs-virtual-machine](/images/Container%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0/1.png)
- 가상 머신은 OS를 가진다.
- 컨테이너는 OS가 없어서 오버헤드가 적고 가볍다. 따라서 이미지 사이즈가 작고 부팅, 배포가 빠르다.
- Hypervisor는 뭘까?
- 머신이 가지고 있는 물리적 자원을 가상머신이 사용할 수 있는 가상의 자원으로 변환해주는 중간 레이어이다. 가상화된 하드웨어, 가상화된 네트워크 인터페이스, 가상 CPU 등을 제공하여 가상머신을 구현하고 게스트 커널을 통해 가상 하드웨어에 접근한다. (가상화할 부분이 많다...)
- 가상머신들이 이 위에서 각각의 OS를 가진 상태로 동작한다.
- Host OS에서 실행된다.
- 컨테이너는 커널이 완전 격리되지 않기 때문에 같은 커널을 가지는 컨테이너만 사용 가능하다.
- 예를 들어 커널이 리눅스인 Ubuntu에서 도커를 사용해서 리눅스 커널을 가진 컨테이너(CentOS, Debian, Fedora 등)는 사용할 수 있지만 커널이 다른 Windows는 사용할 수 없다.
컨테이너는 뭐고 이미지는 뭐지?
- 하나의 이미지로 여러 컨테이너를 만들 수 있다.
- 실행 중인 이미지 인스턴스 === 컨테이너
appendix. 용어 정리
- 1) 유니온 마운트 (union mount) > 하나의 디렉터리에 여러 개의 디렉터리를 마운트함으로써 마치 하나의 통합된 디렉터리처럼 보이게 하는 것이다. 도커에서 이미지 구현에 사용된다. 효율적인 이미지 구현을 가능하게 한다. 이미지 빌드 과정에서 캐시를 사용해서 속도를 향상시켜준다.
- 2) 리눅스 네임스페이스 (linux namespaces) > 특정 프로세스의 리눅스 리소스 접근을 제어하기 위해 사용되는 기능이다. 네임스페이스는 리소스 별로 IPC 네임스페이스, 마운트 네임스페이스, 네트워크 네임스페이스, 프로세스 ID 네임스페이스, 사용자 네임스페이스, UTS 네임스페이스, 컨트롤 그룹 네임스페이스 등으로 나뉜다. 시스템 상에서 실행되는 프로세스들은 기본적으로 init 프로세스의 네임스페이스를 공유하지만 시스템콜이나 unshare 명령어를 사용해 리소스 별로 네임스페이스를 분리하는 것이 가능하다.
- 3) 컨트롤 그룹 (cgroup) > 프로세스에서 사용 가능한 CPU, 메모리, 네트워크 대역폭, 디스크 I/O 등을 그룹 단위로 제어하는 리눅스 커널의 기능이다. 네임스페이스 분리를 통해 각 프로세스를 그룹으로 나누어 통제한다. 상위 계층에서 분리를 통제할 수 있도록 해준다. 각 네임스페이스에 속한 프로세스에게는 하나의 머신 그 자체처럼 작용한다. cgroup을 통해 LXC가 만들어졌다.
글 작성을 위해 참고한 링크 및 서적