Kubernetes使おうとすると早い段階で永続化の話が自然と出てくる。データベースをクラスタ内で動かすとか、ユーザー界の理由もありうるし、クラスタの土台となるツールが永続ボリューム(Persistent Volume)を要求することもある。

どっかのクラウドの上で動いているのなら、K8s内の永続ボリューム要請(PVC)はそのクラウドが提供する(普段有料)ストレージに自動的に繋がって、そのサービス上でPVとして振る舞う、指定容量をもらう。ただそういったストレージは基本ネットワーク越しでつながるもので、もともと速くないディスクIOにさらにネットワークの遅れも加わる。

Kubernetes使おうとする理由はもちろんそれぞれあるが、その複雑性を対価にしてもやりたいのは柔軟な成長(スケール)がよくあると思う。ディスクやり取りと大量にする機械学習なり何なりだと、上記のようにその記憶装置がネットワーク越しだとどうしてもアプリのパフォーマンスのボトルネックになる場合もある。だからと思うが、かなり前からそのノード内の物理ストレージをPVにできないかという要求が出ている。

Kubernetes内蔵では以前 hostPath の指定で似たような仕組みができていたが、扱いがほぼ完全に手動ですごく手間がかかる。また1.14で一般公開(GA)になった local ストレージも1.16の時点でまだ動的(dynamic)ボリューム作成ができず。そういった不満や不便を解消するためにRancherCybozuも似たようなものを作っている。

ただ何が標準になるか何が一般的なのかもわからず、自分のk3sのノードにとりあえずローカルストレージが使いたいだけなのでKubernetesの local で行くことにした。SIGの外部コントローラを入れて動かすこと自体は難しくはない。ガイドの通りHelmでマニフェスト作って、ConfigMapだけ自分で使いたいパスとかを設定した。

上記にもある通り、ローカルストレージはまだ動的に要求に応じてボリュームを作ることはできない。何を意味するかというと、該当のノードでそれぞれ、要求されるパスのマウントを事前に手動なりAnsibleなりで準備する必要がある。俺はノード一つだし、PVCもそう多くないので手動で fstabbind のマウントとしてそれぞれ追加している。

/storage/source-folder /mnt/mount-path none bind

気をつけないといけないのは、イメージによってその要求するストレージの場所(パス)が設定できたりできなかったりする。できない場合はイメージ自体をいじるか、妥協してイメージの要求に合わせたパスにマウントを作るしかない。言うまでもないが後者の方が圧倒的に楽。(ただし一箇所にマウント揃えなくなって散らかる。)

また、ローカルで静的なストレージだからいろいろと制限にぶつかったりする。デプロイメントを消してやり直す時PVが消えず、その中身を保持したいのならOS側から一回マウント外して再マウントするとか、当然だがストレージがノードの容量に依存するので入れるアプリが申請する容量がでかすぎると一瞬でパンクしちゃうとか、普段あまり気にしないことも意識しないといけない。

単ノードで軽量k3sクラスタでこうして自分のサイト程度のものを動かす分には全然問題ないし、外部ストレージの料金もかからないからスマート。ディスクIOの重い処理をクラスタで商業目的な規模で動かすならそれなりの覚悟で費用対効果を考えてネ。