TOC
Windows10のリング
https://docs.microsoft.com/ja-jp/windows-insider/at-home/rings
一般リリースされているWindows10とは別に、開発版Windows10を先行利用します。
開発版Windows10はMicrosoftアカウントで登録を行うことで別途費用がかかることなく利用可能となり、現在2004に相当する版はSlow Ringで利用可能になっています。だいぶ手続きが煩雑になるため、Slow RingのWindows10インストールについては手順を省略します。
今回利用しているバージョンは2004、OSビルドは19033.1になります。
WSL1とWSL2の違い
Windows10 1709(Fall Creators Update)で正式版となったWSLですがこのときのWSL1とWSL2は大きな違いがあります。
WSL1ではWindowsの中でWSL対応したディストロが動く形となり、WSL上で動作するバイナリはWindowsのシステムコールに逐次変換されたものが実行されていました。
WSL2はHyper-Vの上で動作するWSL2対応のディストロ(カスタマイズされたLinux Kernel)がWindowsを介さずに動作しています。また、動作するためのリソースもWindowsから割り当てられるのではなくHyper-Vから割り当てられるのでWindowsと分け合う形です。
WSL2のセットアップ
Windows Subsystem for Linuxを有効にする/Virtual Machine Platformを有効にする
管理者権限で起動したPowerShellで実行する場合
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
コントロールパネルから設定する場合
スタートメニュー→Windowsシステムツール→「コントロールパネル」→「プログラム」を選択します。
「Windowsの機能の有効化または無効化」を選択します。
「Windows Subsystem for Linux」と「Virtual Machine Platform」にチェックを入れ、OKを押します。
OSの再起動を促されるので、そのまま再起動します。
デフォルトのWSLバージョンを2にする
PowerShellかコマンドプロンプトを起動して以下のコマンドを実行します。
wsl --set-default-version 2
WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください
2020/03/13以降、上記コマンド実行時にカーネルコンポーネントのインストールをされるようになりました。
wsl --set-default-version 2
WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。詳細については https://aka.ms/wsl2kernel を参照してください
上記のメッセージが表示される場合は、以下のURLからカーネル更新プログラムパッケージをダウンロードし、wsl_update_x64.msi
をインストールします。
正常にインストールが終われば、デフォルトバージョンを変更できるようになります。
WSLに対応しているディストロをMicrosoft Storeでインストールする
Microsoft Storeを開いて、Ubuntuとかをインストールする。
最後にWSLで使用するユーザー名とパスワードを設定します。
インストールが終わったら確認
wsl -l -v
NAME STATE VERSION
* Ubuntu-18.04 Running 2
ファイルコピーについて
WindowsとWSLの間での相互のファイルの扱いについてはWSL1とWSL2で共通です。
WindowsからWSLのファイルを参照する
「\\wsl$」にアクセスするとディストロのルートディレクトリが見えるので、その下のホームディレクトリをクイックアクセスに登録しておくと利便性が上がるでしょう。
WSLからWindowsのファイルを参照する
Windows側のドライブレターへは/mntの下にマウントされています。Cygwinの/cygdriveと同じ感覚ですね。私の場合はWSL側のホームディレクトリにWindows側のホームディレクトリのシンボリックリンクを貼っています。
$ ls -la /mnt
total 8
drwxr-xr-x 6 root root 4096 Nov 29 19:13 .
drwxr-xr-x 23 root root 4096 Dec 20 16:01 ..
drwxrwxrwx 1 hogehoge hogehoge 512 Dec 20 15:59 c
drwxrwxrwx 1 hogehoge hogehoge 512 Dec 20 15:57 d
drwxrwxrwx 1 hogehoge hogehoge 4096 Dec 20 15:59 e
drwxrwxrwt 2 root root 40 Dec 20 16:01 wsl
$ ln -s /mnt/c/Users/hogehoge ~/winhome
良いところ
Dockerを使える
さっくりDocker CEをインストールします。
# apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -sc) stable"
# apt-get install docker-ce docker-ce-cli containerd.io
都度docker daemonを起動する必要がありますが、systemdは動いてないようです。
# systemctl start docker
System has not been booted with systemd as init system (PID 1). Can't operate.
なので、serviceコマンドでdaemonを起動します。
# service docker start
* Starting Docker: docker [ OK ]
# docker container run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Podmanも使える(追記)
インストール方法の変更
podman自体のインストール方法が変わりました(リポジトリ変更)のでインストール方法も書き直しました。こちらをご参照ください。
なお、以前の方法でインストールしてしまった方は色々面倒だと思いますので復旧させる手順を記載します。
PPAの削除
Ubuntu用のPPAは既にメンテされておらず、ビルドもコケているままなので跡形もなく削除します。
# apt-get remove --purge podman
また、改めてインストールしようとしたらPPAのパッケージの優先度が990になっていたので、PPA自体を削除します。
# apt-cache policy podman
podman:
Installed: 1.6.2-1~ubuntu18.04~ppa1
Candidate: 1.6.2-1~ubuntu18.04~ppa1
Version table:
1.7.0~1 500
500 http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04 Packages
*** 1.6.2-1~ubuntu18.04~ppa1 990
990 http://ppa.launchpad.net/projectatomic/ppa/ubuntu bionic/main amd64 Packages
100 /var/lib/dpkg/status
# add-apt-repository --remove ppa:projectatomic/ppa
More info: https://launchpad.net/~projectatomic/+archive/ubuntu/ppa
Press [ENTER] to continue or Ctrl-c to cancel removing it.
上記コマンド実行後、Enterを押して削除します。
また、1.6.2でエラーが出まくっていた状態だと整合性がとれてないようなので、こんな感じのエラーが出る場合は一旦全て削除します。
$ podman images ls
ERRO[0000] open /proc/108/ns/user: no such file or directory
$ sudo rm -rf ~/.config/containers/ ~/.local/share/containers/
この後に改めてパッケージをインストールして実行することをおすすめします。
改めてパッケージをインストール
# apt-get install podman
$ podman -v
podman version 1.7.0
$ podman container run docker.io/hello-world
Trying to pull docker.io/hello-world...
Getting image source signatures
Copying blob 1b930d010525 done
Copying config fce289e99e done
Writing manifest to image destination
Storing signatures
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
やっとrootless containerの恩恵に預かれそうです。停止したコンテナの起動ができないバグ対応も手元で確認できました。
WSLのディストロ自体がHyper-V上で動作しているため、Windowsの実行状態に関わらずWSLを実行できる
systemdは手元では動いていませんが、daemonの起動はserviceコマンドでできます。バックグラウンド動作や使用するリソースはWindowsとは別に使用されるので、より実際のLinuxに近い動作が可能となるはずです。
WSL1の時のようにUbuntu16.04にして管理者権限で起動したターミナルで起動したDockerがvolume mountもろくにできないみたいなことはなくなっています。
悪いところ
なぜかひたすらメモリリークしている
大量のファイルをWSL側にコピーするだけでそのファイルサイズの倍くらいのRAMを持っていって、返してくれません。
WSL1ではシステムコールを逐次変換するタイプのエミュレーターに近い方式だったので起こりようがない問題です。
複数のファイルをコピーしているので、たとえオンメモリで処理するようになっていたとしてもコピーが終わった分は返してほしいものです。当然RAMには限界があるので、RAMが枯渇するとWSL2が終了するわけです。タイミング次第ではWindows側のプロセスが終了します。
一応問題としてあがってはいるので、ここを見ながら様子見ですね。
RAM割当、swap割当を変更する
WSL2では、WSLに割り当てるRAMの量、swapの量を設定ファイルに記述することで最大量を決められます。
記述するファイルのパスはWindowsの%UserProfile%\.wslconfigです。ユーザーのホームディレクトリになりますね。
例えばこのような内容にして
[wsl2]
memory=6GB
swap=4GB
コマンドプロンプトかPowerShellからWSLをシャットダウンしてみるわけです。1
wsl -l -v
NAME STATE VERSION
* Ubuntu-18.04 Running 2
wsl --shutdown
$ free -h
total used free shared buff/cache available
Mem: 5.8G 61M 5.7G 68K 29M 5.6G
Swap: 4.0G 0B 4.0G
これでWSLから扱えるRAMが6GBとswapとして4GBが割り当てられる訳ですね。SSDの容量が逼迫してなければswapに無尽蔵に当てればなんとかなるはずなので当面これで凌ぐのがベターですかね。
/proc/sys/vm/drop_cachesに3を書き込む(追記)
上記Githubのissueを見ていたところ、ワークアラウンドとしてWSL上の/proc/sys/vm/drop_cachesに3を書き込むという方法が書かれていました。
Just in case, here’s a qworkaround to free the allocated caches/buffers memory without shutting down the whole WSL (ref):
これが何を意味するかというと、Linux Kernel2.6.16以降ではこのファイルに0、1、2、3を書き込むと、メモリキャッシュのクリアを強制的に行うとのこと。それぞれの数値の意味は以下の通り。
設定値 | manの説明 |
---|---|
0 | デフォルト値(manに記載なし) |
1 | ページキャッシュを開放 |
2 | dentryとinodeを開放 |
3 | ページキャッシュ、dentry、inodeを開放 |
dentryが個人的になんなのかよくわからないのですが、inodeというファイル単位に振られている識別子を開放ということは直近でアクセスのあったファイルはKernelのキャッシュに格納されているという理解をしています。
また、manには(恐らく)ダーティーページは開放されないので、操作する前にsync
を実行しておくべきとの記載もあります。
ということでやってみます。kernelパラメータの変更はechoでファイルに書き込むのと同じ操作をsysctl
コマンドでもできるので、個人的な好みでこっちでやります2
まずは巨大なファイル群をコピーしてRAMを使っている状態にさせます。
そうしたらsyncとsysctlでキャッシュを追い出します。実行前後でfreeコマンドを実行して、どのくらい差がでるか確認します。
# free && sync && sysctl -w vm.drop_caches=3 && free
total used free shared buff/cache available
Mem: 6088868 70436 110788 72 5907644 5725172
Swap: 4194304 0 4194304
vm.drop_caches = 3
total used free shared buff/cache available
Mem: 6088868 71140 5962112 72 55616 5865680
Swap: 4194304 0 4194304
freeが110788から5962112に5.8GB増えているのがわかります。Windows側から見たタスクマネージャでも4.3GB程度RAMが開放されているのが見て取れます。
ひとまずwsl.exe --shutdown
を実行せずとも強制的にRAMを開放する手段は確保できました。但しこれはsysctl -w vm.drop_caches=3
を実行したタイミングでその時のメモリキャッシュを開放するので、詰まってきた時に実行する必要があります。
sync
を実行することとコマンドの引数が長いのでaliasを切ってしまいます。
$ echo 'alias freedropcaches="sync && sudo sysctl -w vm.drop_caches=3"' >> ~/.bashrc
これで以降のログインからは以下のコマンドで処理ができるようになります(sudoを使っているので事前の一定時間にsudoしてない場合は実行ユーザーのパスワードが要求されます)
$ freedropcaches
[sudo] password for hogehoge:
vm.drop_caches = 3
正攻法で行くなら/proc/meminfo
をinotifyか何かで監視して、中のSReclaimable
が一定値を超えたら実行するような仕組みを作れれば運用が楽にできそうな気がしています。難しい…時間が取れたら作りましょう。参考になりそうなのはこちら。
Xの起動ができない(VcXsrv)
この辺を見ると解決方法はあるようですが、的確な解決法をまだ見つけられてないので解決できたら追記します。
スポンサーリンク
comments powered by Disqus