機能も増えてきた WSL2 を使おう!

2023/12/05に公開

シーエー・アドバンス Advent Calendar 2023 5日目

普段自宅のPCでは WSL を使って、Linux環境を利用しています。WindowsではWSLがLinux環境として使えます。

そんな WSL もリリースされてから結構時間が経ちますが、最近いろいろと機能の更新があったので、機能の調査してみました!

インストール

たった1行です。

wsl --install

詳細は下記で!

https://learn.microsoft.com/en-us/windows/wsl/install

新機能を試す

2.0.0 が今年(2023) にリリースされ、以下の設定項目が追加され、新しい機能が使えるようになっています。

リリース内容

https://github.com/microsoft/WSL/releases/tag/2.0.0

[experimental]
autoMemoryReclaim=gradual | dropcache | disabled
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true

この中で気になるもの。

autoMemoryReclaim は WSL(Linux) が確保しているメモリのキャッシュを開放する設定で、これにより、メモリの節約ができそうです。

networkingMode はネットワークインターフェースを wsl と windows で同じものを使うようにする(ミラー)設定で、windows の firewall の設定などを適切に行えば、他の端末から WSL にダイレクトでアクセスできるようになりそうです(他の端末から wsl に ssh で接続したり、ウェブサーバーにアクセスしたり)

新機能は experimental としてリリースされましたが、2.0.5 のバージョンから、新機能のうちのいくつかは通常の機能に昇格したようです。
(当初は、.wslconfig の [experimental] セクションで設定を書く必要がありましたが、通常機能に昇格したものは [wsl2] セクションに記載します。後方互換性のため、[experimental] セクションに記載してもいいようですが)

https://github.com/microsoft/WSL/releases/tag/2.0.5

autoMemoryReclaim を試す

この機能のお陰で、キャッシュ用途のメモリを徐々に開放してくれて、メモリの節約ができる嬉しい機能です。一気にメモリが開放されるわけじゃないので、キャッシュの良さも活かしつつ、パフォーマンスのバランスも取れるはず(という触れ込み)

.wslconfig の [experimental] セクションに autoMemoryReclaim=gradual を記載し、wsl を再起動したら、機能が有効になります。

機能が有効になったかどうかは、以下のファイルの有無を確認すればいいみたいです。あれば有効。

❯ ls /sys/fs/cgroup/memory.reclaim
/sys/fs/cgroup/memory.reclaim

上記ファイルがあることを確認し、npm install などの、ファイルキャッシュをたくさん使いそうな操作を行って、メモリの変化を見てみました。

npm install 実行前

Linux 上で観測したメモリ

Every 2.0s: free -h                                                                                                               junya-windows: Mon Dec  4 21:55:13 2023

              total        used        free      shared  buff/cache   available
Mem:          3.8Gi       996Mi       2.4Gi        13Mi       513Mi       2.6Gi
Swap:         1.0Gi       695Mi       328Mi

buff/cache が 513MB 程度でスタート

Windows 上のタスクマネジャーで観測した VmmemWSL のメモリ使用量

タスクマネジャーでは1GB弱でスタート

npm install 直後

Linux 上で観測したメモリ

Every 2.0s: free -h                                                                                                               junya-windows: Mon Dec  4 21:57:23 2023

              total        used        free      shared  buff/cache   available
Mem:          3.8Gi       763Mi       1.9Gi        13Mi       1.2Gi       2.8Gi
Swap:         1.0Gi       695Mi       328Mi

buff/cache が増えて、npm install で作成されたファイルのキャッシュが作られていそうな雰囲気。

Windows 上のタスクマネジャーで観測した VmmemWSL のメモリ使用量

VmmemWSLのメモリ使用量めっちゃ上がる~

npm install してからしばらく経過

Linux 上で観測したメモリ

Every 2.0s: free -h                                                                                                               junya-windows: Mon Dec  4 22:02:32 2023

              total        used        free      shared  buff/cache   available
Mem:          3.8Gi       730Mi       2.5Gi        12Mi       590Mi       2.9Gi
Swap:         1.0Gi       717Mi       306Mi

7分くらいで、実行前のメモリ使用量まで落ち着いた

Windows 上のタスクマネジャーで観測した VmmemWSL のメモリ使用量

WSL が保持しているメモリの減少も確認できた。でも開始当初と比べると、メモリの使用量多い・・・。
Windows からみたメモリの使用量はすごく緩やかに開放されるのかもしれない。

networkingMode を試す

こちらは、WSL のネットワークの挙動を変更する機能です。
networkingMode=mirrored に設定した場合、仮想マシン的な存在である WSL と、 Windows で同じネットワークインターフェースを使うようになります。

従来(NAT)

従来は、WSLのネットワークは NAT になっていて、他の端末から WSL にネットワークを介してアクセスするには、起動の都度変わる WSL のIPアドレスに対して、ポートフォワーディング(netsh の portproxy)の設定を行う必要がありました。

ざっくり言うとこんな感じで通信できるようにポートフォワーディングを行う必要があった↓
(他の端末 → Windows のネットワークインタフェースのポート → WSLのIPアドレスのポート)

※Windows 上で firewall の設定をして、ポートフォワードするポートの Inbound も許可しておく必要があります

mirrored

mirrored にすると、Windows と WSL でネットワークインターフェースが同じになるので、上記の3段構成が以下の2段構成に変わります!

(他の端末 → Windows & WSL のインターフェース)

インターフェースがミラーされるので、他の端末からは Windows に通信する感じで、WSLに直接アクセスができるようになリます。

設定が有効になっているかどうかは、以下のコマンドを wsl 上で実行することで確認できます。

❯ /usr/bin/wslinfo --networking-mode
mirrored

何が嬉しいかというと、WSLをサーバーの用途として使いたいときに、ネットワークに繋げやすくなったというところですね。
そもそも、そんな用途あんまり無さそうですが・・・w
ただ、なにかしらウェブアプリをWSLで開発して、それのスマホレイアウトを確認しようというときに、PCのブラウザではなくて、実機で直接 WSL のサーバーにリクエストその表示を確認するといったことなら1ミリくらい需要ありそうです。

まあ・・・頑張ってWSLでサーバー動かすぐらいなら、Linuxインストールしたほうが簡単なんですけどね~😭

あれ?なんか動かない?

試したんですが、なんか動かない・・・

調べてみると、色々と問題がありそうでした。

Docker との互換性問題!

https://qiita.com/shigeokamoto/items/fc9fa1a395f3fd72fafa

残念!networkingMode=mirrored が有効になっていると、WSL 上で起動した docker コンテナにポートフォワーディングができないようです!
つまり、docker コンテナで nginx を起動したときにブラウザから http://localhost でアクセスできません!
なお、従来の nat モードなら普通に docker 使えますので、nat に戻せば問題なしです。

80 番ポートのウェブサーバーが動きません!

コンテナがだめなら、WSL上に直接ウェブサーバー動かせばいいじゃん!と思い、
python -m http.server や nginx のデーモン起動などを試しましたが、
なにやら 80 番ポートが使用済で WSL 上でウェブサーバーが起動できません!

sudo lsof -i tcp:80 とかで、80 番ポートを使っているプロセスを WSL上で 探しましたが、見つからず。

NETSTAT.EXE -aon | grep ":80" のコマンドを Powershell で実行すると、以下のプロセスが80番ポートを使っていたことがわかりました。

❯ NETSTAT.EXE -aon | grep ":80"
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4924

更に、プロセス4924をタスクマネジャーで検索すると、Service Host: IP Helper のプログラムが実行されていることがわかりました。(タスクマネジャーって検索できるんですね!便利!)


タスクマネジャーの上部に検索ボックスがあることに初めて気がついて・・・感動

このタスク(プロセス) を止めてしまえば、80 番ポートが開放されて、WSL上で起動しているウェブサーバーが使えるようになりそうですが、
なんか Windows 標準のプログラムのようなので、止めると OS のネットワーク機能に支障がありそうで、断念。

ウェブサーバーだけじゃなくて、SSH の 22 番ポートも同じタスクに使われてしまっているので、ある端末から、WSL に SSH するというのも難しそうです。

なお、80 番以外の適当な空いているポート番号を使えば、一応 WSL 上でウェブサーバー起動して、localhost:4567 とかでアクセスできることは確認できました。

ネットワークインターフェースでは WSL と Windows で同じIPアドレスになっていた

機能を有効にすると、たしかにネットワークインターフェースは、WSLとWindowsで同じIPアドレスが振られていました。

Windows のIPアドレス
ipconfig.exe

~~~ 省略 ~~~

Wireless LAN adapter Wi-Fi:

   Connection-specific DNS Suffix  . : flets-west.jp
   IPv6 Address. . . . . . . . . . . : 240b:252:9083:bd00:d528:6d3f:8a21:45a2
   Temporary IPv6 Address. . . . . . : 240b:252:9083:bd00:8537:40e:937c:2a46
   Temporary IPv6 Address. . . . . . : 240b:252:9083:bd00:9167:4e64:d975:944a
   Link-local IPv6 Address . . . . . : fe80::2ae9:7ed3:7476:6ee2%14
   IPv4 Address. . . . . . . . . . . : 192.168.11.5
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : fe80::212:e2ff:fe70:7148%14
                                       192.168.11.1

~~~ 省略 ~~~
WSL(Ubuntu) のIPアドレス
ip a
'1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: loopback0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:6d:b1:28 brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 9c:2d:cd:93:55:84 brd ff:ff:ff:ff:ff:ff
4: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 00:15:5d:e7:30:f6 brd ff:ff:ff:ff:ff:ff
5: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 10:b1:df:70:0c:eb brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.5/24 brd 192.168.11.255 scope global noprefixroute eth2
       valid_lft forever preferred_lft forever
    inet6 240b:252:9083:bd00:8537:40e:937c:2a46/128 scope global nodad noprefixroute
       valid_lft forever preferred_lft forever
    inet6 240b:252:9083:bd00:d528:6d3f:8a21:45a2/64 scope global nodad deprecated noprefixroute
       valid_lft forever preferred_lft 0sec
    inet6 fe80::2ae9:7ed3:7476:6ee2/64 scope link nodad noprefixroute
       valid_lft forever preferred_lft forever

ただ、前述の通り、IPアドレスが共通化されても、Docker が以前のように使えなくなったり、
80 番ポートが競合してしまったりと、
mirrored のネットワークモードはなかなか制約多くてまだ使いづらい印象です。

まとめ

  • autoMemoryReclaim はいい感じにメモリ節約してくれる
  • networkingMode=mirrored はなんだかまだ不安定。制約も多し。でもいつかもっと改善されてほしい!

今後も WSL の研究続けていきます!

参考

https://devblogs.microsoft.com/commandline/windows-subsystem-for-linux-september-2023-update/

Discussion