はじめに
仕事で,AWS上に全く同じ設定の code-server を複数建てたい,という要件がありました。
- それぞれの code-server はクライアントが利用し,事前配布のファイルを編集したりファイルを新規作成したりする
- 利用期間は数日から一週間で,期間終了後はシステムごと破棄する
- 費用節約のため業務時間外にはシャットダウンしたい
EC2で作ってもいいのですが,費用がかかること,code-server 構築コードがAWS依存になることがデメリットです。
そこで,ECS on EC2でコンテナ化し,ユーザが作成するファイルをEFSに保存する構成を考えました。
ホームディレクトリのサブディレクトリにEFSをマウントするだけなら簡単ですが,これだと以下の不都合があります。
- 業務時間終了にシャットダウンするとコンテナの中身が元に戻り,ユーザ設定が保存されない
- マウントしたEFSにファイルを事前配布するのが難しい(Dockerfileと比べて)
- 事前配布のファイルがEFS上に複数配布され,無駄が多い
この記事は,Linux の overlayfs で何とかできないか... と思って試行錯誤した記録です。
方針
privilaged コンテナ前提で,以下のようにしてみます。
- コンテナにEFSをマウントする
- EFS上にディスクイメージを作り,コンテナ内でループバックデバイスにlosetup。mkfs.ext4などしておく
- コンテナ内でループバックデバイスをマウント
- fuse-overlayfs によりコンテナのファイルシステムをlower,ループバック上のファイルシステムを upper とする
落とし穴いろいろ
コンテナ内からは overlay タイプのマウントができなかったので,fuse-overlayfs を使います。
当初は EFSを upper として利用するように fuse-overlayfs を設定していたのですが, code-server のログインページ以外が見えない... という現象になります。
恐らくこれは inotify を NFS がサポートしていないことに起因する問題で,@parcel/watcher かその使い方(多分 vscode)がよくない... です。
https://github.com/coder/code-server/issues/6953
これに気が付くまでとても時間が必要でした...
今回のユースケースではEFSを共有する必要はないので,ディスクイメージのストレージとしてだけ使います。
EFSにディスクイメージを作るとき,sparse file として作成できるように配慮が必要です。
そうしないと,ディスクイメージ * コンテナ数 分のストレージ容量に課金され,IOPSと帯域を無駄に消費してしまいます。
また,ループバックデバイスは namespace 対応ではないので,全コンテナ間で共通です。
コンテナが空きループバックデバイスを使うようにスクリプトを作る必要があります。
結果
コンテナ5個に,wxWidgets のソースコード(zipで23MB)を展開してみました。各コンテナにマウントしたEFSには16GBのスパースファイルを作り,そこにext4ファイルシステムを作って fuse-overlayfs でマウントしています。EFS のディスク容量をどの程度消費するか確認してみます。
zip を展開したのち,find してみたり, code-server を日本語にしたりと操作してみています。
クライアント数が途中で0になっているのは,コンテナホストを落としたためです。
ストレージバイト数が出てこないのはなぜでしょう(CloudWatchでもとても小さい)...
ちゃんと sparse file になっているようです。
おわりに
こんなに苦労するなら EBS にすればよかったんじゃ... と思ってみてみると,EBSはタスク終了時に削除されてしまったり,色々制約があるようです。
また,EBS だとプロビジョニングした容量分の請求になり,少し値段が上がりそうです。
このような使い方は一般的でないと思いますが,動くことが分かってすっきりしました。
samba4 の DCコンテナを作るときなど,色々応用できそうです。