Kubernetes と CSI(Container Storage Interface) について
この記事は Kubernetes2 Advent Calendar 4 日目の記事です。
本記事は CSI(Container Storage Interface) と Kubernetes での CSI のサポートについて触れます。 執筆に時間があまり割けなかった為、後でもう少し加筆する、あるいは別途続きの記事を書くかもしれません。
CSI(Container Storage Interface) とは
CSI(Container Storage Interface, 以下 CSI) は Kubernetes など複数の Container Orchestration (CO) から共通のプラグインを使って SP (Storage Provider) とやり取りするためのインタフェース仕様です。 より具体的には、 CO からストレージを抽象化した Volume をアタッチ・デタッチしたりスナップショットを取ったりする機能のためのインタフェースを提供します。 CSI は Kubernetes とは独立したプロジェクトで進行しております。
また Kubernetes のプロジェクト以下で、 Kubernetes から SP が提供する CSI プラグインへ通信するための CSIDriver と関連実装を以下プロジェクトで進行しています。
Kubertenes としては CSI は 1.9 で Alpha 、 1.10 で Beta サポート対象になっています また Kubernetes での CSI 利用については他に既に試されている方もいるようです。 こちらの記事は詳細に踏み込んだ構成説明などもされており、オススメできる内容になっています。
CSI の仕様
CSI のインタフェース仕様は Protocol Buffer で定義されており、以下リポジトリで管理されています。
またこのリポジトリ内の lib/go/
ディレクトリには .proto ファイルの定義に従ったライブラリの Go 実装が配置されています。
CSI のプラグインは Controller plugin, Node plugin の二種類が想定されております。 また CO とこれら CSI プラグイン間は gRPC で通信することが想定されています。
CSI のサービス
CSI のサービスとして以下三種類が想定されています。
構成によっては実装しなくても良いサービスやメソッドがありますが、少なくとも Node Service の NodePublishVolume
, NodeUnpublishVolume
は実装する必要があります。
(でないと Node から Volume を参照できないはず)
- Identity Service
- CO から Plugin のケーパビリティ (後述) やヘルスチェック、メタデータ参照を可能にするサービス
- Controller Service
- Node をまたいで Volume の構成を管理するためのサービス
- Volume のスナップショット操作もサポートする
- Node Service
- 各 Node から Volume の操作を可能にするためのサービス
CSI における Volume の状態遷移
CSI で Node から Volume を利用されるまでに、 Volume は基本的に以下のような状態遷移をしていきます。 幾つかの状態は、プラグインが示す後述の CSI ケーパビリティによって存在しなかったりします。
CreateVolume +------------+ DeleteVolume +------------->| CREATED +--------------+ | +---+----+---+ | | Controller | | Controller v +++ Publish | | Unpublish +++ |X| Volume | | Volume | | +-+ +---v----+---+ +-+ | NODE_READY | +---+----^---+ Node | | Node Stage | | Unstage Volume | | Volume +---v----+---+ | VOL_READY | +------------+ Node | | Node Publish | | Unpublish Volume | | Volume +---v----+---+ | PUBLISHED | +------------+
ref. https://github.com/container-storage-interface/spec/blob/master/spec.md#volume-lifecycle
CSI のケーパビリティ
CSI プラグインでどのような操作をサポートするかの情報です。 CSI の仕様としては以下 4 種類のケーパビリティをサポートします。
- PluginCapability
- VolumeCapability
- Volume のファイルシステムのタイプやアクセス制御(リードオンリーなのかなど)、容量などの情報を含む
- CO は
CreateVolume
,ControllerPublishVolume
などのメソッドで指定や値の検証が可能
- ControllerServiceCapability
- Create/Delete , Publish/Unpublish などの操作をサポートするかの情報を含む
- CO は
ControllerGetCapabilities
メソッドで取得可能
- NodeServiceCapability
- Stage/Unstage などの操作をサポートするかの情報を含む
- CO は
NodeGetCapabilities
メソッドで取得可能
CSI の利用用途
CSI プラグインとしてはすでに、 NFS や iSCSI などの公式のサンプルプラグインを含め、 AWS や GCP のストレージサービスの利用を可能とするプラグインが存在します。 以下の公式ドキュメントに既に存在する CSI プラグインに関する記述があります。
簡単な CSI Plugin の実装を追ってみる
以上だけだと CSI プラグインの動作が把握し難いので、 kubernetes-csi の drivers リポジトリにある HostPath plugin の動作を追ってみます。 このプラグインはリポジトリに kubernetes への deploy 用 yaml ファイルも同梱されており動作を追うのに便利です。
HostPath plugin では CSI の Identity, Controller, Node 三種類の gRPC サービスを提供します。
その実装は github.com/kubernetes-csi/drivers/tree/master/pkg/hostpath
に存在します。
Identity Server は特に特殊な実装をしていません。
github.com/kubernetes-csi/drivers/blob/master/pkg/csi-common
に存在する、他の Driver と共通のデフォルトメソッド実装をそのまま使用しています。
Controller Server では CreateVolume
, DeleteVolume
, CreateSnapshot
, DeleteSnapshot
, ListSnapshots
を実装します。
CreateVolume
, DeleteVolume
では複雑なことをしておらず、 UUID 付きの名前のディレクトリを掘って Volume に見立て、 map で Volume の管理を行います。
CreateSnapshot
, DeleteSnapshot
はそれに似て、 Volume のディレクトリを tar czf
で固めて同じく UUID 付きのファイルに保存・管理します。
Node Server では NodePublishVolume
, NodeUnpublishVolume
, NodeStageVolume
, NodeUnstageVolume
を実装します。
NodePublishVolume
, NodeUnpublishVolume
は作成された Volume のディレクトリを k8s.io/kubernetes/pkg/util/mount
パッケージを介して mount/unmount します。
NodeStageVolume
, NodeUnstageVolume
は単にリクエストパラメータ中の Volume や ターゲットパスが空でないことをチェックしているだけになります。
HostPath プラグインでは他に複雑なチェックをする必要が無いためこうなっているのではと思われます。
kubernetes 上で想定される構成は以下の通りになっているようです。
- Controller Server のメソッドの参照
CreateVolume
など Volume の作成・削除は https://github.com/kubernetes-csi/external-provisioner コンテナを利用ControllerPublishVolume
など Volume の Publish 操作は https://github.com/kubernetes-csi/external-attacher を利用CreateSnapshot
などスナップショットの操作は https://github.com/kubernetes-csi/external-snapshotter を利用
- Node Server のメソッド参照
- https://github.com/kubernetes-csi/driver-registrar を使って CSIDriver を kubelet から参照可能にする
- kubelet から CSIDriver をプラグインにという格好で読み出し参照するロジックは Kubernetes 本体リポジトリの kubelet と関連パッケージに存在
- https://github.com/kubernetes-csi/driver-registrar を使って CSIDriver を kubelet から参照可能にする
おわりに
以上、 CSI とその Kubernetes へのインテグレーションに関する記事でした。 CSI は可搬性を担保しつつ Kubernetes での利用を重要視されて作られているようですが、 CSI の仕様含めエコシステムもまだ枯れているとは言えず、機能も多くはありません。 Kubernetes 用の単なるサンプルとはいえ HostPath プラグインで tar コマンドを実行してスナップショットを作成したりなど、もう少し抽象化されてほしい箇所もまだ存在します。
しかしながら個人的には Kubernetes での柔軟なストレージ利用には、以前の記事で挙げた通りまだまだ課題があると思っており、今後の発展を期待したいと考えています。