blog.stackframe.dev

systemd-nspawn으로 가벼운 컨테이너 만들기

옛날에는 서버 성능이 바쳐준다면 한 서버에 웹 서버, 메일 서버, 데이터베이스, 네임서버들을 싸그리 넣고 격리란 개념없이 운영하는게 평범하였고 이로인해 하나의 보안사고가 다른 서비스들까지 영향을 미치며 서버 업그레이드는 고사하고 유지하는 것조차 힘든 일이었다. 하지만 Docker가 나오면서 서비스를 컨테이너 단위로 간단하게 분리하고 기존의 문제점들을 해결하였기에 컨테이너 기술이 이제는 거의 필수가 되었다.

그렇다면 systemd-nspawn은 무엇일까. systemd-nspawn은 현재 대다수의 리눅스 배포판에서 채용하고 있는 systemd에 포함된 컨테이너 실행 프로그램이다. 리눅스 시스템의 root 디렉터리나 이미지를 입력하면 자동으로 init을 찾아서 부팅하고 격리된 공간을 만든다. 다른 컨테이너 프로그램처럼 네트워크나 사용자 ID도 네임스페이스로 호스트와 분리가 가능하다.

systemd-nspawn이 가지는 장점은 꽤 있다. systemd가 사용되고 있는 배포판이라면 대부분 systemd-nspawn도 포함되어 있다. 따라서 호스트 배포판이 변경되더라도 systemd-nspawn이 존재만 한다면 추가적인 설치없이 컨테이너를 실행할 수 있다. 거기다 기존의 systemd의 강력한 장점인 일관성있고 직관적인 설정이 가능하기에 관리도 편리하다. 추가적으로 호스트의 systemd-journald와도 연동되기에 호스트에서 바로 실행되고 있는 컨테이너의 로그를 가져와 볼 수 있다.

호스트에서 읽은 stackframe-dev 컨테이너의 부팅 로그

물론 단점도 있다. 컨테이너 단위가 리눅스 root 시스템이라 프로그램 하나를 실행시키기 위해서라도 배포판 전체를 설치해야 한다. linux 커널 이미지와 initramfs는 없어도 되지만 그래도 잡아먹는 용량은 크다. 그리고 Docker Hub registry 같은 이미지를 제공하는 서비스가 없다. machinectl이라는 컨테이너 관리 명령어에 pull-tar, pull-raw같은 외부에서 이미지를 로드해서 저장하는 명령이 존재하지만 제한적이다.

systemd-nspawn의 설명은 이정도로 해두고 실제 사용으로 넘어가보자. 먼저 컨테이너로 사용할 배포판을 정해야한다. 컨테이너로 사용할 배포판에 따라 root 디렉토리를 구성해주는 명령어가 다르니 거기에 맞는 명령어를 써야한다. Arch Linux는 pacstrap, Debian이나 Ubuntu는 debootstrap, CentOS는 기본 패키지 관리자인 yum 명령어에 --installroot= 옵션을 써서 할 수 있다. 나는 Arch Linux를 사용할 예정이다.

먼저 컨테이너로 사용할 root 디렉토리를 구성한다:

# mkdir arch-root
# pacstrap -c ./arch-root base vim

-c 옵션은 pacman 캐시에 있는 패키지를 활용하겠다는 의미이다. 이게 없으면 매번 인터넷에서 불러오기 때문에 설치가 느리다. base는 Arch Linux의 기본 구성 패키지들을 의미하고 뒤의 vim은 내가 필요해서 넣은 것이다. base만 설치하면 어떤 텍스트 에디터도 설치되지 않아서 초기설정 할 때 애먹는다.

설치가 끝나면 이제 machinectl 명령에서 간편하게 사용할 수 있도록 /var/lib/machines/ 디렉토리로 옮기는게 좋다. 굳이 옮기지 않아도 systemd-nspawn 명령으로 직접 부팅이 가능하나 귀찮다. 아예 systemd service 유닛을 만들어서 사용한다면 몰라도 여기서는 간단하게 machinectl 명령을 사용할 것이다. cp 명령을 사용하는게 아니라 machinectlimport-fs 명령을 사용하여 옮긴다:

# machinectl import-fs ./arch-root archlinux-baremetal

설치된 이미지를 확인하면 아래와 같이 나올 것이다:

# machinectl list-images

설치된 이미지 리스트

이제 이 이미지를 컨테이너로 실행해보자:

# machinectl start archlinux-baremetal
# machinectl status archlinux-baremetal

컨테이너가 정상적으로 실행되었다.

컨테이너에 root 권한으로 접속하려면 shell 명령을 사용한다:

# machinectl shell archlinux-baremetal

컨테이너를 종료하려면 poweroff, 재시작하려면 reboot 명령을 사용한다:

# machinectl poweroff archlinux-baremetal
# machinectl reboot archlinux-baremetal

추가적으로 이미지를 clone 명령으로 복제가 가능하다:

# machinectl clone archlinux-baremetal arch1

이렇게 복제된 이미지는 완전히 동일하므로 /etc/machine-id를 지워서 새로 생성하도록 하는 것이 필요할 것이다.

댓글