Kubernetes CSI は、Container Storage Interface (CSI) の Kubernetes 固有の実装です。
CSI 仕様は、ストレージ システムとコンテナー オーケストレーション プラットフォーム (CO) 間の接続を可能にする標準を提供し、Kubernetes におけるストレージ管理の基盤を形成します。
CSI 標準は、任意のブロックおよびファイル ストレージ システムを、Kubernetes のようなコンテナー システム上のワークロードにどのように公開するかを規定しています。ストレージ ソリューションのサードパーティ ベンダーは、CSI を利用してプラグインを作成・提供することができ、Kubernetes のコア コードを変更することなく、新しいストレージ システムと連携させることが可能です。
Container Storage Interface (CSI) が登場する以前、Kubernetes は In-Tree K8S ボリューム プラグイン のみをサポートしており、これらは Kubernetes コア バイナリ内で作成・提供する必要がありました。つまり、ストレージ ベンダーは新しいストレージ システムをサポートするために、自社の K8S プラグインを Kubernetes のコア コードに組み込む必要があったのです。
この課題を解決しようとしたのが、FlexVolume というプラグインベースのソリューションです。FlexVolume では、サードパーティ プラグイン向けに実行可能な API を公開しました。この仕組みは、CSI と同様に k8s バイナリからの分離を実現しましたが、いくつかの問題がありました。
CSI はこれらの問題を、コンテナ化と K8S ストレージ プリミティブの活用によって解決しました。CSI は、Out-of-Tree ストレージ プラグインを利用するための事実上の標準的なソリューションとなっています。これにより、ストレージ ベンダーは StorageClass、PersistentVolume (PV)、PersistentVolumeClaim (PVC) といった標準的な K8S プリミティブを用いて、プラグインを提供できるようになりました。
CSI の主な目的は、あらゆるコンテナー オーケストレーターにおいて、あらゆる種類のストレージ システムを提供する仕組みを標準化すること です。
関連コンテンツ: [Kubernetes 永続ボリューム (Persistent Volumes) ガイド]
CSI ボリュームは、Kubernetes ワークロードで利用できる PersistentVolume リソースを提供するために使用できます。PersistentVolume は、ワークロードによって要求されたときに 動的に、または手動で提供することが可能です。
CSI ストレージ プラグインを参照する StorageClass を作成することができます。これにより、Kubernetes ワークロードは動的に PersistentVolume を作成できるようになります。これらの PersistentVolume に保存されたデータは、CSI プラグインで定義されたストレージ デバイス上に保持されます。
たとえば、次の StorageClass は、csi-driver.example.com という CSI プラグインを使用して「Fast-Storage」タイプのストレージ ボリュームをプロビジョニングできるようにします。
(この例および以下の他の例は、公式の Kubernetes CSI ブログ記事で公開されています。)
Kubernetes エンティティが、この StorageClass を要求する PersistentVolumeClaim (PVC) オブジェクトを作成すると、その StorageClass に対応する PersistentVolume が動的にプロビジョニングされます。
次の図は、Fast-Storage StorageClass を参照する PVC の例を示しています。
上記の StorageClass 定義には、タイプ、および mysecret と mynamespace という 2 つのシークレットを含む 3 つのパラメーターがある点にご注意ください。PVC が宣言されると、バックグラウンドで次の処理が行われます。
関連ブログ記事: NetApp Trident と Cloud Volumes ONTAP を用いた Kubernetes 永続ボリュームの動的プロビジョニング
PVC メカニズムを使用せずに、Kubernetes でボリュームを手動でプロビジョニングし、ワークロードで利用可能にすることができます。
次の図は、existingVolumeName という名前のストレージ ボリュームをワークロードで使用できるようにする PV オブジェクトの例を示しています。前述のとおり、CSI ボリュームはストレージ プラグイン csi-driver.example.com を参照しています。
次の図は、Kubernetes Pod テンプレートが PVC を参照して CSI ボリュームにアクセスする方法の一例を示しています。
Pod テンプレートに PersistentVolumeClaim が含まれている場合、Kubernetes は Pod をスケジュールする際に CSI プラグイン内で ControllerPublishVolume、NodeStageVolume、NodePublishVolume を含む複数の処理を実行します。これにより、ストレージ ボリュームが作成・マウントされ、Pod 内で実行されるコンテナーが利用できるようになります。
Kubernetes における CSI ドライバーは、通常、コントローラー コンポーネントとノード コンポーネントで構成されます。
コントローラー コンポーネント
コントローラー プラグインは、Deployment または StatefulSet としてデプロイされ、クラスター内の任意のノードにマウントできます。これには、CSI コントローラー サービス を実装する CSI ドライバーと、1 つまたは複数の サイドカー コンテナー が含まれます。コントローラー サイドカー コンテナーは、通常、Kubernetes オブジェクトとやり取りし、CSI コントローラー サービスを呼び出します。
コントローラーはホストへの直接アクセスを必要とせず、外部のコントロール プレーン サービスおよび Kubernetes API を介してすべての操作を実行できます。高可用性 (HA) を実現するために、複数のコントローラー コンポーネントをデプロイすることも可能ですが、同時に 1 つのコントローラーだけがアクティブになるよう リーダー選出 (Leader Election) を実装する必要があります。
コントローラー サイドカーには、以下が含まれます。
どのサイドカーをデプロイメントに含めるかは、サイドカー側で定義された仕様によって異なり、必須ではなく任意です。
コントローラーは、Kubernetes イベントを管理するサイドカー コンテナーと通信し、その後、CSI ドライバーに適切な呼び出しを送信します。呼び出しは EmptyDir ボリューム を介して共有される UNIX ドメイン ソケット によってサイドカーとドライバー間でやり取りされます。
また、コントローラー サイドカーは RBAC (役割ベースのアクセス制御) ルール を使用して Kubernetes オブジェクトとの相互作用を制御します。サイドカーのリポジトリには、RBAC ポリシーに統合できる RBAC 設定の例が提供されています。
ノード コンポーネント
ノード プラグインは、クラスター内のすべてのノードに DaemonSet としてデプロイされます。これには、CSI ノード サービス を実装する CSI ドライバーと、ノード ドライバー レジストラ として機能するサイドカー コンテナーが含まれます。
ノード コンポーネントは、すべてのノード上で動作する kubelet と通信し、CSI ノード サービスへの呼び出しを処理します。これらの呼び出しは、ストレージ システム内のボリュームをマウントまたはアンマウントし、Pod が利用できるようにします。kubelet は、ホスト上で HostPath ボリューム を介して共有される UNIX ドメイン ソケット を使用して CSI ドライバーに呼び出しを行います。さらに、ノード ドライバー レジストラは別の UNIX ドメイン ソケットを利用して、ドライバーを kubelet に登録します。
ノード プラグインは、ドライバー ボリュームをマウントするためにホストへの直接アクセスを必要とします。ファイルシステム マウントやブロック デバイスを kubelet で利用可能にするために、CSI ドライバーには 双方向のマウント ポイント が必要です。これにより、kubelet はドライバー コンテナーによって作成されたマウントを認識できるようになります。
Kubernetes は CSI ボリューム ドライバーのパッケージング方法を規定してはいませんが、Kubernetes 上でコンテナ化された CSI ドライバーを容易にデプロイするための推奨事項を提供しています。
ストレージ ベンダーは、コンテナ化された CSI ボリューム ドライバーを導入する際に、次の手順を実行することが推奨されます。
もう 1 つの選択肢として、外部プロビジョナーや外部アタッチャーを含むすべてのコンポーネントを 1 つの DaemonSet にまとめる方法もあります。ただし、この方法はより多くのリソースを消費し、External-Attacher および External-Provisioner コンポーネントのためにリーダー選出プロトコル(例: https://git.k8s.io/contrib/election)を使用する必要があります。
Kubernetes クラスターは、CSI ドライバーを使用できるようにするために 特権 Pod を有効化する必要があります。
たとえば、kubelet および API サーバーに対して --allow-privileged フラグを「true」に設定する必要があります。kubeadm、GCE、GKE などの一部の環境では、これがデフォルト設定となっています。
API サーバーは、次の特権フラグを付けて起動する必要があります。
$ ./kube-apiserver ... --allow-privileged=true ... $ ./kubelet ... --allow-privileged=true …
Container Storage Interface (CSI) では、同一ノードまたは Pod 内のコンテナー間でマウント済みボリュームを共有できるようにする マウント伝播機能 が必要です。クラスターの Docker デーモンは、マウント伝播を有効にするためにマウント共有を許可する必要があります。
NetApp Cloud Volumes ONTAP は、エンタープライズ向けのリーディング ストレージ管理ソリューションであり、AWS、Azure、Google Cloud 上で安全かつ実績のあるストレージ管理サービスを提供します。Cloud Volumes ONTAP はペタバイト規模まで容量をスケール可能で、ファイル サービス、データベース、DevOps、その他のエンタープライズ ワークロードといったさまざまなユースケースをサポートします。さらに、高可用性、データ保護、ストレージ効率、Kubernetes との統合など、豊富で強力な機能を備えています。
特に Cloud Volumes ONTAP は、コンテナ化されたワークロードにおける Kubernetes Persistent Volume のプロビジョニングおよび管理要件 をサポートしています。
詳しくはこちら: