파일 시스템이 없는 상태에서의 리눅스 커널 부팅

리눅스 시스템에서 파일 시스템이 없는 경우에 커널 패닉이 일어난다고 했는데, 실제로도 일어나는지를 보여주기 위해서 화면 캡쳐를 통해서 직접 보여주도록 하였다.

Union File System

도커의 이미지와 컨테이너 개념글에서 다뤘던 내용입니다만, 도커는 실행중에 변경된 부분을 이미지로 생성할 수 있다고도 적었습니다. 이게 가능하도록 하는 것이 바로 Union File System(UnionFS)입니다.

이 파일 시스템은 읽기 전용의 파일 혹은 디바이스에서 변경 사항을 기록하여 저장할 수 있도록 해주는 파일 시스템이다. 읽기 전용 파일을 실행할 경우, 해당 파일에 대해 쓰기가 가능한 임시 파일을 생성하여 읽기 파일을 그대로 복제하여 실행을 하게 된다. 그 다음, 수정이 된 내용에 대해 모두 사용하였다면 쓰기 작업을 진행한 다음, 기존의 읽기 파일을 대체한다. 이러한 방식을 Union Mount라고 한다.

도커에서도 해당 이미지 파일을 기본적으로 UnionFS가 지원되는 파일이다. 이 파일을 위의 Union Mount 처리를 하여 지속적인 변경 사항을 작성하여 업데이트 되는 것이다.

UnionFS를 잘 이용한 방식은 리눅스 배포판 중에 크노픽스(Knoppix)라는 배포판이 있다. 이 배포판은 CD 혹은 DVD에서 실행하는 라이브 운영체제 형식으로 배포되는데, 부팅 과정과 운영체제의 기본 실행은 램디스크에서 부팅 및 실행을 하면서도 변경된 사항에 대해서는 컴퓨터에 연결된 보조 저장장치(쓰기 가능)에 저장을 하여 다음에 실행될 때 해당 변경사항을 부팅 후 읽어들여서 적용시킨다.

도커하면 빠지지 않는 기본 이야기: 리눅스 컨테이너

도커에 대한 설명을 하다보면 거의 항상 설명하고 하는 것이 있는데, 바로 LXC(LinuX Container)입니다. 오래전부터, 리눅스/유닉스 환경에서는 chroot라는 명령어를 제공했습니다. 이 명령어는 파일 시스템에서 루트 디렉터리(/)를 변경하는 명령어입니다.

multipledistros-after-chroot.png

이렇게 특정 디렉토리를 루트 디렉토리로 변경하게 되면chroot jail이라는 환경이 생성되는데, 이 안에서는 바깥의 파일과 디렉터리에 접근할 수 없게 됩니다. 경로 자체가 격리되기 때문에 서버 정보의 유출과 피해를 최소화하는 데 주로 이용되어 왔던 기술입니다. 그러나 chroot는 chroot jail에 들어갈 실행 파일과 공유 라이브러리를 직접 준비해야 하고 설정 방법 또한 상당히 복잡합니다. 또한 완벽한 가상 환경이 아니기 때문에 제약 또한 상당히 많습니다. 이러한 환경을 Confined Environment라고 합니다.

clip_image002_0000

이후에 리눅스에서는 LXC라는 시스템 레벨의 가상화를 제공하게 됩니다. LXC는 컴퓨터를 통째로 가상화하여 OS를 실행하는 것이 아니라 리눅스 커널 레벨에서 제공하는 일종의 격리된 가상 공간을 제공합니다. 이 가상 공간에는 운영체제가 설치되지 않고 호스트의 리눅스를 그대로 이용하기 때문에 가상 머신이라고 안하고 컨테이너라고 합니다. 아래의 이미지가 LXC를 설명하기 가장 좋은 이미지인 듯 하군요.

Image.png

리눅스 커널의 자원 일부를 그대로 이용합니다. 리눅스 커널의 cgroups(control groups)를 통해 CPU, 메모리, 디스크, 네트웤 자원을 할당하여 완벽한 가상 공간을 제공합니다. 또한 프로세스 트리, 사용자 계정, 파일 시스템, IPC 등을 별도로 격리시켜서 호스트와 별개의 공간을 따로 만듭니다. 이렇게 격리된 곳이 바로 namespaces입니다. 마지막으로 보안 관리를 제공하는 SELinux(Security-Enhanced Linux) 또한 가상화된 공간에서 제공하여 보안도 호스트와 같은 수준으로 제공합니다. 즉, cgroups와 namespaces, SELinux 기능을 활용하여서 가상 공간을 제공하게 되는 겁니다. 추가적으로 필요한 자원이 있다면 드라이버를 가상 환경에 연결하여 지원해줍니다.

하지만, LXC는 격리된 공간에 대한 지원만을 할 뿐, 개발 및 서버 운영에 필요한 부가 기능에 대해서는 상당히 부족한 상황입니다. 도커는 이 리눅스 커널에서의 cgroups, namespaces, SELinux 기능을 기반으로 하여 이미지, 컨테이너의 생성 및 관리 기능과 다양한 부가 기능을 지원할 수 있도록 개발된 것입니다. 그래서 도커에 대한 설명을 하다 보면 자연스럽게 LXC에 대한 설명도 같이 들어가게 됩니다.

도커가 처음 개발될 당시에는 LXC를 통해 구현되었다고 과거 문서들에는 많이 나와있지만, 0.9 버전 이후로부터는 libcontainer를 개발하여 이용하는 것으로 알려져 있습니다. 도커 문서에는 실행 드라이버라고 하는데, native, lxc 중 선택해서 사용할 수 있습니다. lxc는 LXC에서 이용하던 라이브러리입니다. 어떤 것을 이용하는 것이 더 좋은지에 대해서는 여러모로 논의가 이어지고 있습니다만, 양쪽 다 열심히 업데이트 되고 있어서 어떻게 될지는 모르겠군요.

QVNR6.png