multipass 사용법 & VM에서 nginx 가지고 놀기

zdpk·2024년 6월 30일

multipass

목록 보기
1/1
post-thumbnail

multipass는 ubuntu를 개발한 Canonical에서 만든 CLI tool이다.

CLI 환경에서 간단한 명령어 몇 개로 Ubuntu 가상 환경을 구축해준다.

공식 홈페이지에서는 이러한 간단하게 구축 가능한 VM을 Cloud-Style VMs라고 표현하고 있다.

마치 AWS CLI를 사용하여 aws ec2 run-instances ~ 명령어 하나로 VM을 구축하는 것과 유사하기 때문이다.

Docker Engine을 통해 linux image를 실행할 경우, systemd 등이 존재하지 않는데,

이는 Docker Container의 철학 및 설계로 인해 누락된 것이다.

Container는 경량화 된 가상화이기 때문에 빠르게 시작되고 최소한의 자원만 사용해야 하며,

일반적으로 단일 프로세스를 실행하도록 설계 되었기 때문에 init.d, systemd 등의 Daemon Process Manager들은 포함되지 않은 것이다.

가벼워서 좋긴 하지만, nginx 등을 구축할 때는 systemctl 명령어를 사용하는 예제가 상당히 일반적인데 환경의 차이로 인해 혼란을 빚을 수 있을 것이다.

이처럼 Container 보다는 조금 무겁지만 Linux와 동일한 환경을 갖추고 싶을 때 multipass를 사용하면 적절하다.

사용법은 매우 간단하기 때문에 글이 상당히 짧을 것이다.

Host 환경은 macOS Sonoma 14.4.1이다.


설치

  1. brewmultipass를 설치한다.
$ brew install multipass

설치하고 실행하면 된다.

그러면 우측 상단에 주왕색 아이콘이 보일 것이다.

그리고 명령어를 자주 쳐야 하는데, multipass가 너무 길어서 불편한 감이 있다.

고로 ~/.zshrcalias를 등록할 것이다.

$ vi ~/.zshrc

# ~/.zshrc 파일에 alias 추가
alias mp = multipass

이제 multipass 대신 mp를 입력해서 명령어를 수행할 수 있다.

이건 옵션이므로, 등록을 안했다면 multipass로 입력하면 된다.


VM 이미지 찾기

multipass find로 사용 가능한 VM 이미지 목록을 볼 수 있다.

alias를 등록 했다면 mp find를 써도 된다.

$ mp find 

Image                       Aliases           Version          Description
20.04                       focal             20240626         Ubuntu 20.04 LTS
22.04                       jammy             20240627         Ubuntu 22.04 LTS
23.10                       mantic            20240619         Ubuntu 23.10
24.04                       noble,lts         20240628         Ubuntu 24.04 LTS

Blueprint                   Aliases           Version          Description
anbox-cloud-appliance                         latest           Anbox Cloud Appliance
charm-dev                                     latest           A development and testing environment for charmers
docker                                        0.4              A Docker environment with Portainer and related tools
jellyfin                                      latest           Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media.
minikube                                      latest           minikube is local Kubernetes
ros-noetic                                    0.1              A development and testing environment for ROS Noetic.
ros2-humble                                   0.1              A development and testing environment for ROS 2 Humble.

4개의 Image가 보이고 모두 ubuntu다.

Canonical에서 만들었으니 당연할 수도.

그래서 이후 VM을 만들 때, 이 중에서 버전을 고르면 된다.

안 고르면 최신 lts 버전이 설치된다.

BluePrint 라는 것도 있는데

docker, minikube 등 Cloud에서도 컨테이너 환경이 일반화 된 만큼 이러한 환경을 VM을 띄우자마자 이미 구축된 상태로 만들어 두는 것이다.

매 번 설치하려면 귀찮으니 말이다.

Blueprint는 잠시 후에 좀 더 살펴보겠다.


VM 실행

아무런 옵션을 주지 않으면 다음 명령어 만으로 VM을 띄울 수 있다.

$ mp launch 

Container가 아니기 때문에 시간은 좀 더 오래 걸리지만, 사용법은 매우 간단하다.

그리고 list 명령어로 현재 보유한 VM들을 볼 수 있다.

# VM 생성 및 실행
$ mp list

Name                    State             IPv4             Image
brimming-javelina       Running           192.168.80.6     Ubuntu 24.04 LTS

이렇게 옵션을 안 주면 VM 이름은 자동으로 들어간다.

그래서 VM을 여러 대 만들고 용도에 따라 구분하려면 --name 혹은 축약형인 -n 옵션을 줘서 원하는 이름을 줄 수 있다.

# 이름을 first-vm으로 지정하여 VM 생성 및 실행
$ mp launch -n first-vm

이제 mp list로 2대의 VM을 확인할 수 있다.

$ mp list

Name                    State             IPv4             Image
brimming-javelina       Running           192.168.80.6     Ubuntu 24.04 LTS
first-vm                Running           192.168.80.7     Ubuntu 24.04 LTS

버전을 지정하지 않았기 때문에 최신 lts 24.04 버전의 ubuntu가 설치 되었는데,

버전을 맨 뒤에 명시하면 원하는 버전을 설치할 수 있다.

# 이름을 second-vm, ubuntu 22.04 버전 지정하여 VM 생성 및 실행
$ mp launch -n second-vm 22.04
$ mp list

Name                    State             IPv4             Image
brimming-javelina       Running           192.168.80.6     Ubuntu 24.04 LTS
first-vm                Running           192.168.80.7     Ubuntu 24.04 LTS
second-vm               Running           192.168.80.8     Ubuntu 22.04 LTS

VM은 리소스를 먹기 때문에 first-vm 말고 삭제하겠다.

$ mp delete brimming-javelina
$ mp delete second-vm
$ mp list

Name                    State             IPv4             Image
brimming-javelina       Deleted           --               Ubuntu 24.04 LTS
first-vm                Running           192.168.80.7     Ubuntu 24.04 LTS
second-vm               Deleted           --               Ubuntu 22.04 LTS

delete로 삭제하면 되는데, State를 Deleted로 바꿔주는 것이지, 실제 파일을 삭제하는 것은 아니므로 완전히 지우려면 추가적인 작업이 필요하다.

$ mp purge

mp purge를 수행하고 mp list로 확인해보면

$ mp list

Name                    State             IPv4             Image
first-vm                Running           192.168.80.7     Ubuntu 24.04 LTS

이제 더 이상 삭제된 VM들이 보이지 않을 것이다.


SSH 접속

first-vm VM이 실행 중이긴 한데, 아직 실제로 접속은 못해봤다.

local에 만든 VM에 SSH로 접속하는 절차를 거치면 마치 AWS EC2 등의 remote VM에 접속할 때와 동일하게 사용할 수 있는데,

이것 역시 매우 간단하다.

$ mp shell first-vm

ubuntu@first-vm:~$

SSH Key를 생성하거나 등록할 필요 없이, shell 명령어만 입력해도 접근이 된다.

실제로 ubuntu 환경이 맞는지 다음 명령어로 확인해보자

$ cat /etc/os-releases

PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
...

길어서 아랫쪽은 좀 잘랐다.

NAME이 Ubuntu로 나온다면 접속이 잘 된 것이다.

이제 nginx를 설치해보자.

# 관리자 모드 전환
$ sudo su -

# 패키지 목록 및 버전 정보 update
$ apt-get update
# nginx 설치
$ apt-get install nginx -y

설치가 완료되었다.

nginx를 실행하고 요청을 보내보자

# nginx 실행
$ systemctl start nginx

# nginx에 요청 보내기
$ curl localhost:80 -v

응답이 좀 길긴 한데 밑으로 내리면 대충 이런 응답이 올 것이다.

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Windows에서 재부팅 할 때마다 자동 시작되는 프로그램들이 있는데

그것과 유사한 것이 systemd다.

시작 프로그램이라 보면 된다.

systemd의 컨트롤러인 systemctl을 통해 nginx를 시작 프로그램에 등록한다.

#  nginx 시작 프로그램에 등록
$ systemctl enable nginx

이제 VM을 껐다 켜보고 nginx가 여전히 실행 중인지 확인해 볼 것이다.

$ exit
$ exit

exit으로 VM을 나간다.

아까 sudo su -로 관리자 모드로 shell에 접속했기 때문에 2번 exit 해야 HOST의 shell로 나가진다.

stop 명령어로 VM을 중지하겠다.

컴퓨터를 끄는 명렁이라 생각하면 된다.

$ mp stop first-vm

그리고 다시 켜준다.

$ mp start first-vm

참고로 restart는 이 두 동작을 한 번에 해준다.

이제 접속해서 nginx가 잘 수행되는지 확인해보자.

# VM SSH 접속
$ mp shell first-vm

# admin 전환
$ sudo su -

# nginx 확인
$ ps -ef | grep nginx

root        1005       1  0 16:38 ?        00:00:00 nginx: master process nginx
www-data    1006    1005  0 16:38 ?        00:00:00 nginx: worker process

ps -ef로 nginx가 방금 시작되었음을 확인할 수 있다.

nginx는 기본적으로 master, worker process가 구동된다.

컴퓨터를 껐다 켜도 nginx가 재부팅 때마다 잘 실행되는 것을 확인했다.

(참고로 관리자 전환을 안 하면 nginx를 볼 수 없다.)

$ curl localhost:80 -v

마지막으로 요청 한 번 날려보고 이번에는 시작 프로그램에서 제거하겠다.

# 시작 프로그램에서 nginx 등록 해제
$ systemctl disable nginx

$ exit
$ exit

그리고 restart로 VM 재부팅 해준다.

# 재부팅
$ mp restart first-vm

# 재접속
$ mp shell first-vm
# 관리자 전환
$ sudo su -

# nginx 실행 확인
$ ps -ef | grep nginx
root         986     973  0 16:41 pts/1    00:00:00 grep --color=auto nginx

이번에는 master, worker process가 나오지 않는다.

$ curl localhost:80 -v

* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* connect to ::1 port 80 from ::1 port 57712 failed: Connection refused
*   Trying 127.0.0.1:80...
* connect to 127.0.0.1 port 80 from 127.0.0.1 port 34548 failed: Connection refused
* Failed to connect to localhost port 80 after 1 ms: Couldn't connect to server
* Closing connection
curl: (7) Failed to connect to localhost port 80 after 1 ms: Couldn't connect to server

curl 요청 역시 실패한다.

nginx가 실행 중이지 않다는 소리다.

이로써 systemctl의 역할을 대충 느꼈을 것이다.

그럼 다시 nginx를 시작 프로그램으로 등록해주자.

# nginx 시작 프로그램 등록
$ systemctl enable nginx

다시 요청 보내면 오류 난다.

$  curl localhost:80 -v

* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* connect to ::1 port 80 from ::1 port 54244 failed: Connection refused
*   Trying 127.0.0.1:80...
* connect to 127.0.0.1 port 80 from 127.0.0.1 port 45754 failed: Connection refused
* Failed to connect to localhost port 80 after 4 ms: Couldn't connect to server
* Closing connection
curl: (7) Failed to connect to localhost port 80 after 4 ms: Couldn't connect to server

당연히 시작 프로그램으로 등록하는 명령어가 지금 당장 실행을 해준다는 이야기는 아니기 때문이다.

그 때는 다음 명령어를 실행하면 된다.

# nginx 시작
$ systemctl start nginx

이제 응답이 잘 온다.

# 요청 확인
$ curl localhost:80 -v

# process 확인
$ ps -ef | grep nginx
root        1129       1  0 16:44 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data    1130    1129  0 16:44 ?        00:00:00 nginx: worker process
root        1133     973  0 16:44 pts/1    00:00:00 grep --color=auto nginx

root 권한으로 16:44분에 /usr/sbin/nginx -g daemon on; master_process on; 명령어를 통해서 master process가 실행 되었다는 이야기다.

즉, systemctl start nginx/usr/sbin/nginx -g daemon on; master_process on; 명령어로 대체될 수 있다.

stop 명령어로 nginx를 중지해보자

# nginx 종료
$ systemctl stop nginx

# process 확인
ps -ef | grep nginx
root        1151     973  0 16:46 pts/1    00:00:00 grep --color=auto nginx

process에서 없어졌다.

아까 그 명령어를 직접 쳐서 실행해보자.

# nginx 실행
$ /usr/sbin/nginx -g "daemon on; master_process on;"
$ curl localhost:80 -v

nginx가 잘 실행되어 응답이 잘 온다.

$ ps -ef | grep nginx

root        1153       1  0 16:47 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data    1154    1153  0 16:47 ?        00:00:00 nginx: worker process
root        1159     973  0 16:47 pts/1    00:00:00 grep --color=auto nginx

process도 확인된다.

이전과 동일하다.

대충 이런 식으로 돌아간다.

실행, 종료만 해봤는데 설정을 변경한 뒤, nginx -s reload 명령어를 통해 nginx 실행 중에도 패킷 손실 없는 설정 변경 적용 등의 유용한 기능들도 지원한다.

  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/share/nginx/)
  -e filename   : set error log file (default: stderr)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file

위와 같이 signal도 보내고 설정 파일도 먹이는 등의 작업을 할 수 있다.

nginx 자체는 stop, quit, reopen, reload 외의 다른 linux signal도 받을 수 있다.


자원 할당

VM은 가상 머신으로, 실제 물리 머신 위에서 돌아가지만, CPU, Memory, Disk 등의 자원을 별도로 할당, 격리한다는 특징이 있다.

그러나 이전에 우리가 생성한 VM이 CPU 등의 자원을 얼마나 소모할건지 명시한 적이 없다.

그래서 자동으로 할당된 것이며, 각 VM이 리소스를 얼마나 먹고 있는지 간단하게 확인 가능하다.

$ mp get local.first-vm.cpus
1

$ mp get local.first-vm.memory
1.0GiB

$ mp get local.first-vm.disk
5.0GiB

이런 식으로 확인하면 된다.

vm instance명 앞에 local이라고 붙여줘야 하는데, multipass가 remote 자원도 관리할 수 있기 때문에 구분해 주는 것이다.

어쨌든 기본값이 CPU 1개, memory 1GiB, disk 5.0GiB라고 한다.

이건 환경에 따라 달라질 수도 있다.

이번에는 직접 자원 할당을 명시해보겠다.

# 자원 직접 할당
$ mp launch -n my-vm2 --cpus=2 --memory=2G --disk=10G

# 축약형
$ mp launch -n my-vm -c=2 -m=2G -d=10G

축약형도 있으니 둘 중 아무거나 쓰면 된다.

$ mp get local.my-vm.cpus
2

$ mp get local.my-vm.memory
2.0GiB

$ mp get local.my-vm.disk
10.0GiB

자원이 명시한 만큼 할당 되었음을 확인했다.

이런식으로 자원이 좀 더 필요할 때는 원하는 만큼 할당해서 쓰면 나쁘지 않을 것이다.


쓰다 보니 조금 길어져서 다음 장으로 넘기겠다.

현재는 VM을 제거하면 모든 데이터가 유실되는데,

VM을 제거해도 Host에 데이터를 남길 수 있도록 disk mount 하는 방법과

docker처럼 vm을 이미지화 하는 것, blueprint 등에 대해서는 다음 장에 정리해보겠다.

1개의 댓글

comment-user-thumbnail
2025년 4월 15일

훌륭한 분석입니다! Multipass가 가벼우면서도 systemctl을 사용할 수 있도록 하는 점이 정말 마음에 듭니다. 다양한 환경에서 일관성을 추구하는 개발자에게는 hero clicker 의 판도를 바꿀 만한 제품이라고 확신합니다!

답글 달기