tech.guitarrapc.cóm

Technical updates

WSL1 から WSL2 の対応

WSL1 を長い間使っていましたが、先日 Windows 10 Version2004 がリリースされて WSL2 に切り替えを行いました。

WSL2 いいのですが、WSL1 と同じように、あるいはちょっと欲張ろうと思うと少し困ったのでメモ。

目次

TL;DR

Windows 10 May 2020 Updateがリリースされてから2週間使ってますが、もう WSL1 に戻る気はないぐらいには気に入っています。おすすめです。 具体的には、

  • 👍: WSL2 にして apt/pip3 が爆速になってうれしい
  • 👍: WSL1 とおおむね使い勝手は変わらず、WSL2上のdockerでボリュームマウントが可能になってよかった(標準的なLinuxとみなせるようになった)
  • 🙅: WSL2 の Windowsボリュームのアクセスはとても遅くなった
  • 🙅: Windows のシステムボリュームは余計に食うようになったので 50GB 程度空きは欲しい (あるいはOSリセットすると減るはず)

kubernetes 周りに関しては、特段変化を感じません。

WSL1 で何をしていたのか

WSL1 では、Ubuntu 18.04 を動かして、中でアプリケーションやインフラにかかわるツールを動作させていました。 Docker でもいいのですが、普段使いのツールや、Windows でマウントしているファイルを(EOLを含めて) そのまま Linux で動作させたときの動作もサクッと確認できるのがいいのです。

  • dotnet core SDK
  • golang
  • cmake
  • Kubernetes (kubctl/helm/kubesec/sops...)
  • terraform
  • docker/docker-compose
  • aws cli/azure cli
  • jq/yq
  • sed 他

docker とWSL の使い分けはそのカジュアルさです。 WSLは、bash と入力するだけでほぼ Linux とみなせるインタラクティブな環境に行けるので、普段使いのUbuntu 環境に利用しています。多少無茶な使い方をしても、アンインストールして store から入れなおせばフレッシュになるので壊せる開発環境という感じです。 一方のdocker は、アプリ動作環境を閉じ込めるためや、特定のソフトウェアの挙動、壊れるだろうという操作やシステム設定の変更など戻すことがめんどくさいことをするときに使っています。

WSL2 で何をするのか

基本的な利用目的は変わりません。手軽にさくっと Linux 環境として Ubuntu を利用します。 WSL1 から WSL2 に変化することで期待したのは、ディスクIOです。 概ね事前にやっていた結果と Windows 10 Version 2004 における WSL2 に違いはなく、WSL1 に比べて ext4 上でのディスク書き込みの速度が上がりました。 具体的な変化は次の通りです。

  • apt update|instal が爆速になる
  • pip3 も爆速化
  • Windows マウントファイルへのアクセスは非常に低速に
  • WSL2上のDockerでボリュームマウントが可能になった

ディスクアクセスの改善は顕著です。具体的なシチュエーションだと、apt update/install に関しては、これまでUbuntu 18.04 を入れた後に実行すると10min 程度食うのを覚悟していたものが1min 程度になっています。pip3 も同様です、ansible 入れてみてください。 ただ、Windows のマウントディレクトリ ( /mnt/c など) でのファイル操作はけた違いに遅くなりました。(知ってた) そのため、例えばdocker-compose で Windows のフォルダを WSL2 からマウントするのはものを選びます。100MB を超えるdocker転送は永遠に終わらない気分になります。(node_modules とかつらい)

Windows のパス上からそのまま bash で WSL2 を起動する流れは変わらないものの、大き目なファイルサイズを伴う docker-compose に関しては Windows上で扱うか、ext4 上に git clone するのがいいでしょう。

しれっと書きましたが、WSL2ではWSL上のファイルをWSLのdockerにボリュームマウントできるようになっています。WSL1 では、WSL 上のファイルを WSL上で実行した docker にボリュームマウントできず、ふとしたdocker操作で挙動が違って無駄に時間を費やすことがありましたがなくなりました。最高です。

WSL2 への対応

WSL1 の環境を WSL2 にするにあたり、どのような対応をしたかメモしておきます。

Windows システムボリュームの利用が増えた

WSL1からWSL2にすると、Docker Desktop (35GB)、wsl (9GB)、Ubuntu 18.04(5GB) で 約50GB余計にシステムボリューム(C:) を利用するようになってしまいました。

デスクトップは長い間 256GB M.2 SSD (Samsung SSD 950 Pro) でやっていましたが、WSL2 にして残り 1.8MB になったためシステムボリュームを 1TB NVMe に差し替えました。 Crucial は 最近P2 が出ましたが、ちょっと試してみたかった P1 で。

https://www.crucial.jp/catalog/ssd/p1www.crucial.jp

なお、Windows.old を含めてゴミを消しても容量はすぐに埋まりきりがなくなったので仕方ない。

qiita.com

なお、Windows 10も入れなおして開発環境、WSL2を組みなおしたところ利用容量が 76.1GB になったので、まぁそんなものです。知ってた。(だから 256GB で過ごせていた) Windowsの入れ直しは、Media Creation Tool で Windows 10 May 2020 Update で USBブートを作るのが今も安定でした。

Windows Features が不要に

幸いなことに、 Docker Desktop for Windows をインストールすると WSL2 周りは一通り入ります。(Kernel のぞく) そのため、これまで Enable-WindowsOptionalFeature でインストールしていた Microsoft-Windows-Subsystem-Linux、Hyper-V は不要になりました。

https://github.com/guitarrapc/local-provisioner/compare/wsl1...604c08d7313060c681fc2ecb91d9839df7056ccf#diff-500458443dc2514ec7bec4fde7ce776eL1-L25

脱Hyper-Vは、Windows 10 Home でも利用できるようになっていますし最高ですね。(Virtual Box とかも動くし)

tech.guitarrapc.com

WSL OS

WSL2 でも、現状は Ubuntu 18.04 を使っています。 折を見て Ubuntu 20.04 に切り替えていきますが、まずは変化を見たいので変えていません。

Provisioning

WSL1 と変わらず、WSL2 においても ansible を使って環境を構築しています。 私の場合は、Windows / macOS / Ubuntu を各種環境を利用するので、全環境に対してこのリポジトリの内容を当てています。

github.com

Ubuntu 18.04 においては、WSL1/WSL2であっても ansible で当てています。 Diff は次の通りです。

https://github.com/guitarrapc/local-provisioner/compare/wsl1...724dad71fd0852173e10fbca4a961eec92db2710

いくつか初期化回りの変更をメモしておきます。

dockerの入れ直しをやめた

docker は、WSL1 においては docker.io の公式同様に入れなおしていましたが、WSL2 においてはデフォルトから変更していません。

-    - { role: "docker", tags: [docker] }
+    #- { role: "docker", tags: [docker] }

https://github.com/guitarrapc/local-provisioner/compare/wsl1...604c08d7313060c681fc2ecb91d9839df7056ccf#diff-b905abb381284c6c36b4ac2b6dc30641L24-L25

また、bashログイン時の起動も止めています。

- sudo -S cgroupfs-mount
- sudo usermod -aG docker $USER
- sudo service docker start
- # wsl1 using windows docker-compose. wsl2 don't need this line.
- # export DOCKER_HOST=tcp://localhost:2375 

https://github.com/guitarrapc/dotfiles-linux/commit/db47ddf5c1ba8400acb502b256c8a03bbcb5749b

WSL2でdocker の入れ直しをやめたのは、docker の入れ直しを行うことで Windows 上の Docker for Windows のイメージと WSL2 上のイメージ一覧が同期されなくなったためです。(Windows はWindows、WSL2 の UbuntuはUbuntu と個別にイメージを持つようになってしまった。)

# この結果を Windows と WSL で共有する
docker image ls

WSL2 を使うにあたって、Windows の状況がそのまま利用できるメリットを手放す理由は相応のものがない限り薄く、特に docker に関しては同じイメージが使えるのが最高なのでdocker の入れ直しはやめました。

systemd/snap

当初wsl2 なら snapも行けるしと思って試していた形跡があります。が、結局 snap使っていません。(また使えるようにファイルは残しています) 実際 systemd/snapd を動かして、snap 経由でのインストールも可能になりましたが、以下の理由で辞めています。

  • kubectl は意図通り snap のほうが楽だった
  • snap で差し替えたかった pip3 の snap ファイルが欲しいものではなかった
    • 具体的には ansible が公式がなく個人のパッケージは python2 版
  • Windows から bash や wsl で WSL2 を起動したときに、$HOME に移動するようになってしまう
    • WSL2 は、wsl や bash で Ubuntu に入ると Windows のパスのまま維持しますが、snap 対応を入れたスクリプトでのログインしなおしでパスが $HOME になってしまう

snapを使うことでバージョニングを楽にインストールをしたいと思ったのですが、なかなか難しいようです。 現状あんまり snap に頑張る気もないので、やめました、はい。

Windows パスの分離

WSL2 は WSL1 同様に、標準では Windows のPATH が $PATH に入ってきます。 これにより、WSL2 上で code . とすることで Remote WSL がVS Code で使えたりします。(~/docker.cfg も Windows の docker cred のパスが入っています)

Windows PATHがWSLで使えるのはすごく便利なのですが、WSL1 で Windows のパスとWSLのパスが競合してWSLでアプリ動作がおかしくなった経験があります。 そのため、 /etc/wsl.conf でPATH を停止しています。

[interop]
appendWindowsPath = False

wsl.conf をおいて、 wsl --shutdown を実行することでWSL上で Windows のパスが入らなくなります。

$ echo $PATH
/home/guitarrapc/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/guitarrapc/.dotnet/tools

まとめ

おおむねWSL2 にして幸せになります。 ディスク容量は明らかに食うようになるので、私は割り切ってシステムボリュームを1TB まで増やしてわずらわしさを感じないようにしました。 ただ、ラップトップでなくても、PCのシステムドライブはそれほど大きくないことも多いので要注意な感じがあります。