前提
- 本記事執筆時の各ツールのバージョン
kubernetes v1.16.5
docker 19.03.12 - 書いている人は k8s をこれから使ってみようとしている人。
悩み
- k8s で Node 外のストレージを使ってデータ永続化する手法としていろんなリソースが出てくる(PersistentVolume, PersistentVolumeClaim, StorageClass, StatefulSet などなど)が、なんでこんなにいっぱい出てくるのかわからない。しかし設定ファイルの書き方はわかるので使えている。
結論
- ストレージを扱いやすいように抽象化しているのだが、誰にとって扱いやすいのかが個人的には理解のポイントだった。インフラを管理する人と、システム開発する人がいることを頭に入れると理解しやすくなった。
- Kubernetesのデータ永続化入門の図がとてもわかりやすかったので見てみてください。
- そして結局公式ドキュメントにたどり着くので、詳しくはこちらを見てください。(はじめっからここ見とけばよくわからなくなることもなかった説)
各種リソースの説明
Volume に直接外部ストレージを指定する
いきなり Kubernetes のリソースではない話ですが、Pod
の yaml ファイルの.spec.volumes
に直接ボリュームの具体的な指定を記述するやつです。
公式ドキュメントを見ると、いろんな種類の Volume が並んでいます。外部ストレージを直接指定する場合は、nfs
とかiscsi
とかを指定します(ネットワークストレージの種類に全然詳しくないので、この辺はよくわかってない)。GKE とか EKS みたいなマネージドのサービスだと独自のストレージが用意されていたりします。
そして後述のPersistentVolume
もvolumes
の指定として並列になっています。
ちなみに、外部ストレージを直接具体的に指定すると、Pod
とストレージが密結合になってしまうので、間に抽象レイヤーを入れる、というのはわかります。それがPersistentVolume
だと理解していたけれど、なぜPersistentVolumeClaim
とわかれているのかが、いまいち腑に落ちていなかったのが動機で調べたのがこの記事です。
ひとりでいじっているときの盲点だったのですが、実際の k8s 使うような規模の開発では、インフラ管理者とシステムの開発者はだいたい別だし、開発者は複数の人たちが入れ替わったり増減したりするという当たり前のことを思い出すと理解できました。
PersistentVolume (PV)
これが外部ストレージの実体となるリソースです。具体的な実装内容が定められています。名前の通り、データを永続化するためのボリュームで、Pod
とは違うライフサイクルでクラスター内に存在します。
後述するStorageClass
を基に動的に生成され確保されることもあれば、インフラ管理者があらかじめ手動で用意することもあります。
調べた感じ、動的に確保されるのが主流のようなので、PVリソースを直接手動で用意するのは少なそうですが、インフラを厳密に管理したい時に手動で用意するんだろうか。
PersistentVolumeClaim (PVC)
これは開発者側のストレージへの要求です。
欲しいパフォーマンスや挙動を記述すると、それを満たすPVが確保されます。
また、その要求もStorageClass
によって抽象化されているので、実際には全部を具体的に指定することはありません。インフラ管理者が用意したStorageClass
から適切なものを選ぶことになります。
ちなみに、後述するStatefulSet
を使う場合は yaml ファイルにvolumeClaimTemplates
というのがあり、それによってこのPVCも直接作成しなくてもよいです。
StorageClass (SC)
PV のクラスです。プログラミングで言うクラスと同様で、確保する PV の雛形です。
これによって、インフラ管理者は PV の具体的な実装を抽象化しつつ開発者からのストレージ要求に答えることができます。
また、開発者もインフラの中身を気にすることなく欲しいストレージを確保することができます。
StatefulSet
これだけ、ここまで説明してきたものとは毛色が違うリソースなのですが、Deployment
と同じコントローラーという種類に属するリソースです。アプリケーション(一群のPod
)をクラスターにデプロイします。
各 PV に固有のIPアドレスやDNS名がついたり、起動順序が保証されることにより、Pod
と PV の紐付けが簡単になります。名前の通り、ステートフルなアプリケーションに向いたものです。
例えばよく出てくる用途としては、プライマリ/レプリカ構成のデータベースなどです。
Deployment
との大きな違いは、Deployment
が複数のPod
に共通の PV が紐付けられるのに対し、Pod
ごとに専用の PV が紐付けられるということや、世代管理はしていないのでDeployment
のようにロールバックはできないということじゃなかろうかと思います。
調べただけで、まだ使ってないので使ってみてわかったことがあったら追記する。
ということで
わかってみれば難しいことではなかったんですが、やっぱり前提になってる状況とか課題とかを把握していないと、ちゃんと理解するのは難しいなと思った次第です。