Multipassを用いた仮想環境ってどう?

AvatarPosted by

この記事は GRIPHONE Advent Calendar 2022 4日目の記事です。

サーバーサイドエンジニアをしております皆田です。
この記事では、仮想環境を気軽に試せてしまうMultipassについて、設定から使い方までを書いていこうと思います。

今、Multipassを触ってみる理由

現状、開発にはDockerが欠かせない状態です。
弊社でもWin/macでDocker Desktopを用いて開発している状態です。
お手軽にDockerを利用できるDocker Desktopは本当に便利なツールだと思います。
ただ、たまに同期にラグがあったりしてストレスをかかえることがありました。

私はこれまでWindowsで作業していたのですが、リモート業務になるに伴い、macにリプレイスして以降、WSLでubuntu上にdocker-ceを置いたときの速度が忘れられなくて、この状況から離脱し、OSによらない環境を作れたら理想的だなと考えるようになりました。

そんな中、技術記事を読んでいたときに『MultipassでDocker Desktopを抜け出した』という記事を見かけ、OSに依存せずLinux-vmの開発環境を確立できたら便利だろうなと思ってしまったのがキッカケです。

Multipassとは

公式そのままの説明を行うなら、『Linux, mac OS, WindowsでクラウドスタイルのUbuntu仮想マシンを生成するためのツールです』の一言につきます。

2020年に出てきた比較的新しいツールで、Docker Desktop有料化時に結構騒がれていたものです。

GUIを使わない人にとっては使いやすそうなツールです。

Multipassで利用可能なイメージたち

Ubuntuベースで現状使えるものは multipass find で確認可能です。

  • Ubuntu 18.04 LTS / 20.04 LTS / 22.04 LTS
  • Anbox Cloud Appliance
  • charm-dev
  • docker
  • jellyfin
  • minikube

本記事では Ubuntu 20.04 を用います。

基本的なコマンド

コマンド説明
multipass launch仮想マシンをローンチする
multipass listインスタンスをリスト表示する
multipass shell [vm名]vmのシェルに入る
vmを抜けるにはexitと打ちます
multipass exec [vm名] — [コマンド]ワンライナーでのコマンド実行
multipass start [vm名]インスタンスを開始する
multipass suspend [vm名]インスタンスを一時停止する
multipass stop [vm名]インスタンスを停止する
multipass mount A Bマウントします
ローンチコマンド実行時にオブションで –mount A:B としても同じ結果を得られます
multipass delete [vm名]インスタンスを削除する
–all オプションで全てのインスタンスを削除可能です
multipass recover [vm名]deleteで削除したインスタンスを復元できます
multipass purgedeleteしたインスタンスを完全に削除します
復元できなくなります

※start/suspend/stopはVM名をスペースでつないで指定した複数のインスタンスを指定可能です。–allですべてのインスタンスを同時に操作することも可能です。

実際にMultipassでDockerを動かしてみる

目標

Docker for mac を離脱し、開発環境を整えるため、以下3点ができること

  • 仮想環境でdockerを起動し、macからストレスなくdockerを起動できること
  • ファイル配置さえ守っていればメンバーが同じことをすればVMアクセスに対する公開鍵設定も簡単である
  • VMを壊しても何度でも簡単に現状復帰できる

もっと言うと検証用のローカルマシンの細かい設定やプロファイラが動くようにするなどあるのですが、記事の公開を考えると作業が間に合わず、載せることができませんでした。師走ですね・・・

インストール〜Docker起動まで

コマンド一覧は作ったので、実際の設定ファイルと起動までを列挙していきます。マシンの設定を行うためのファイル(cloud-config.yaml)を用意してあげればやりたいことはできるはず!ってことで。

1. インストール

dockerが既に入っているとうまく動作しないということがあったので、docker desktopを削除したりします。mac自体にdockerを入れている場合、以下コマンド実行していきます。

# Homebrew が入っている前提ですが、強制削除します
brew uninstall --force docker docker-machine docker-compose
# 新たにインストールしなおします
brew install multipass docker docker-compose
# インストールできたことを確認しておく
docker version
docker-compose version
multipass version
# ssh用の鍵を作っておく(メールアドレスは任意)
ssh-keygen -t rsa -b 4096 -C user_name@mail.co.jp -f ~/.ssh/multipass_docker
# 鍵のパーミッションを変更しておく
chmod 600 ~/.ssh/multipass_docker
chmod 600 ~/.ssh/multipass_docker.pub

2. multipassの仮想マシン用設定ファイルを作る

こちらはcloud-config.yamlに相当するファイルを作るためのスクリプトです。

#!/bin/sh
# このファイルはhomeディレクトリに作成して利用ください。
# 作成した.pubファイルを変数に読み込む(各自、パスを設定)
AUTHORIZED_KEYS=$(cat ~/.ssh/multipass_docker.pub)

# ヒアドキュメントでファイルを作成する
cat > ./multipass_docker.yaml << _EOF_
#cloud-config
locale: en_US.UTF8
timezone: Asia/Tokyo
package_upgrade: true
users:
  - name: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh-authorized-keys:
      - ${AUTHORIZED_KEYS}

packages:
  - docker
  - avahi-daemon
  - apt-transport-https
  - ca-certificates
  - curl
  - gnupg
  - lsb-release

runcmd:
  - sudo curl -fsSL https://get.docker.com | sudo bash
  - sudo systemctl enable docker
  - sudo systemctl enable -s HUP ssh
  - sudo groupadd docker
  - sudo usermod -aG docker ubuntu
_EOF_

このスクリプトに実行権限をつけて、./make-multipass-docker-yaml.shなどとして実行しちゃいましょう。
SSHファイルがスクリプト内のファイル名で配置してあれば公開鍵を読み込んで設定してくれるようにできます。

3. ローンチ

スクリプトで作ったyamlファイルを指定してこのようなコマンドでローンチします。

multipass launch -c 4 -m 8G -d 20G -n ubuntu-docker 20.04 --cloud-init ~/multipass_docker.yaml

cpu数を4、メモリは8G、ストレージを20G、VM名をubuntu-dockerとし、ubuntu 20.04ベースで実行します。
ubuntu-docker内部のdocker設定はyaml内のruncmdで実行済みなので、ローンチはコレだけ。

ちょっと時間がかかります。

# ローンチの成否確認
multipass exec ubuntu-docker -- tail -1 /var/log/cloud-init.log

modules-final: SUCCESSと出ていれば成功しています。
※ローンチの成否に関わらずVMは出来てしまうということなので、multipass listのみの確認では不十分ぽいです

もし、ローンチしたマシンを消したい場合は以下コマンドで乱暴に全部消す!ってこともできます。
※deleteでゴミ箱に入れて、purgeで完全削除。allオプションでmultipassインスタンス全部という指定です

multipass delete --all --purge

4. SSH設定

ubuntu-dockerにSSH接続してみます。

ssh -i ~/.ssh/multipass_docker ubuntu@ubuntu-docker.local
# 接続できたらexitしましょう

~/.ssh/configを以下のように記述し、アクセスできるようにします。
※存在しないファイルの場合は同名でファイルを作ってください

Host ubuntu-docker.local
  HostName ubuntu-docker.local
  IdentityFile ~/.ssh/multipass_docker
  User ubuntu
  Port 22

鍵を利用してSSHアクセスできるか試してみます

# 念の為接続履歴を削除しておく
ssh-keygen -R ubuntu-docker.local
ssh ubuntu@ubuntu-docker.local
# 入れたらexitで抜けておきます

5. ホストOSのディレクトリをマウントする

macとVMをストレスフリーで操作したいのでマウントしておきます。
この操作は任意です。パスマッピングが楽になるのでマウントすることをおすすめされていました。

multipass mount /Users ubuntu-docker:/Users
multipass mount /private/tmp ubuntu-docker:/tmp
# マウント状況を確認する
multipass info ubuntu-docker

※macのtmpディレクトリはprivate内にあるため、このような記述になるとのこと

6. Dockerを準備する

Clientは別途インストールしてあげる必要があるらしいということで手順に従います。

ARCH=$(if [ "$(uname -m)" = "amd64" ]; then echo "amd64"; else echo "aarch64"; fi)
DOCKER_VERSION="20.10.21"
curl -sL https://download.docker.com/mac/static/stable/$ARCH/docker-$DOCKER_VERSION.tgz | tar xzv -C $HOME
# 上記curlを実行すると以下表示がされます。
x docker/
x docker/docker
x docker/cli-plugins/
x docker/cli-plugins/docker-buildx

※上記、実行して確認したところ、macのclientは20.10.18になってしまいましたが、ubuntu側は20.10.21でしたので20.10.18が正解かもしれないです

.zshrcにパス設定しておきます

echo '\nexport PATH=$PATH:$HOME/docker' >> $HOME/.zshrc
source ~/.zshrc

7. Docker Contextの切り替え

Docker Context を利用することで複数の Docker node を切り替えて利用できます。

コンテキストは任意の名前で、後から書き換えることもできるのでやってみましょう。jqコマンドをインストールしていないかたはbrewなどで予めインストールしておきましょう。

docker context create ubuntu-docker --docker "host=tcp://$(multipass info ubuntu-docker --format json | jq -r '.info["ubuntu-docker"].ipv4[0]'):2375"

docker context use ubuntu-docker

# 確認してみる
docker context list

これで準備完了です。

今までdocker desktopでやっていたことを試してみましょう。
docker-compose buildなど普通にできました。
※まだ開発環境としては正しく動く状況ではありませんが、今回はdockerを動かすことが目標だったのでここまで。

まとめ

うまくいった感はまだないのですが、いかがでしたでしょうか?

Docker Desktopの動作の重さに悩む人はまだまだ多いかと思います。
mutagenでの解決もアリですし、今回のように新しいVMツールを試してやろうとすることは時代の流れに乗り遅れないようにするためにも、どんどん遊んでみるべき!と思っています。

アドベントカレンダー2022はまだまだ序盤です。
明日の記事もお楽しみに!

参考にさせていただいたサイト

https://qiita.com/kozayupapa/items/ab686a2cfd0022411f64

https://zenn.dev/ww24/articles/7e576d6f01a366