Red Hatでソリューションアーキテクトをしている田中司恩( @tnk4on )です。 この連載はvSphere環境上にOpenShift Container Platform(以下、OpenShift)およびOpenShift Virtualizationの環境を構築する方法を解説するシリーズです。 第3回は共有ストレージの作成について解説します。今後の連載予定は下記の通りです。 第1回:OpenShiftのインストール 第2回:OpenShiftインストール後の作業 第3回:共有ストレージの作成(NFS CSIドライバーの構築) (←本記事) 第4回:OpenShift Virtualizationのインストールと実行 第5回:vSphere仮想マシンの移行 【番外編】:共有ストレージの作成(NFSプロビジョナーの構築) (2024/7/17追記:2つ目のディスクを/mnt/nfsにマウントする手順を追加しました) (2024/7/23追記:NFS CSIドライバーを使用する内容に変更しました。以前の内容は番外編として別記事にしました。) (2024/9/29追記:NFS CSIドライバーのアップデート方法を追加しました) (2024/10/2追記:踏み台サーバーに2つ目のディスクを追加するコマンドを修正しました) -目次- 共有ストレージの作成概要 前提条件 1. OpenShift Virtualizationに必要なストレージ 1-1 ストレージのアクセスモードについて 1-2 永続ストレージ 1-3 永続ボリュームの動的プロビジョニング 1-4 Container Storage Interface (CSI) 2. 踏み台サーバー上のNFSサーバー設定 2-1 NFSサーバーの設定 3. NFS CSIドライバーの設定 3-1 NFS CSIドライバーについて 3-2 NFS CSIドライバーの動作 3-3 NFS CSIドライバーのインストール (1)Helmのインストール (2)NFS CSIドライバーのインストール (追記)NFS CSIドライバーのアップデート (3)NFS CSIドライバーのインストールの確認 3-4 ストレージクラスとボリュームスナップショットクラスの作成 (1)ストレージクラスの作成 (2)ボリュームスナップショットクラスの作成 3-5 デフォルトストレージクラスの設定 3-6 動的プロビジョニングの動作テスト (1)サンプルファイルのダウンロード (2)PVCとPodの作成 (3)確認 (4)サンプルのPodとPVの削除 (5)NFS CSIドライバーの削除 4. イメージレジストリの設定 4-1 イメージレジストリーの構成 4-2 イメージレジストリーの設定 4-3 レジストリーの公開 4-4 レジストリーの操作 (1)ログイン (2)イメージのプッシュ (3)プッシュしたイメージの確認 (4)OpenShift上のイメージをプルする まとめ 共有ストレージの作成概要 本記事ではOpenShift Virtualizationに必要な共有ストレージの作成を目的として、下記の内容を紹介します。 OpenShift Virtualizationに必要なストレージ 踏み台サーバー上のNFSサーバー設定 NFS CSIドライバーの設定 イメージレジストリの設定 OpenShiftの標準サブスクリプションである OpenShift Container Platform (OCP)やその下位エディションの OpenShift Kubernetes Engine (OKE) *1 は複数ノードから書き込み可能な共有ストレージの機能は標準搭載していません。 通常はOpenShiftクラスター外部のストレージ製品を利用する形態でこれを構成します。 対して、OCPの上位エディションの OpenShift Platform Plus (OPP) *2 にはOpenShift Data Foundation(ODF) *3 が含まれます。このODFを使用することでOpenShiftをHCIで構成し共有ストレージを提供できるようになります(vSphereで言うところのvSANと同様のことができるとイメージください)。 ODFはOpenShiftに統合されたストレージであるため、実稼働環境における推奨されたストレージの選択です。 しかしながら、ODFはその構成上非常に多くのリソースを使用します。潤沢なリソースがない環境での利用は難しいため、今回の検証環境でODFは利用しません。 今回は1台のRHEL(または他のLinux等でも可)で構成できる NFSを利用したシンプルな共有ストレージ を作成することとします。 なお、このストレージはあくまで検証用途であり、実稼働環境での利用はできませんのでご注意ください。 *4 前提条件 連載 第1回 および 第2回 の作業を完了していることとします 全体の構成や各パラメーターなどは連載 第1回 を参照してください 作業用端末のプロンプトは % とします 踏み台サーバーのプロンプトは $ とします 踏み台サーバーの作業は明示的に記載がある場合を除いて、作業ディレクトリ ${HOME}/work で作業することとします 第2回の作業完了後の構成 1. OpenShift Virtualizationに必要なストレージ 1-1 ストレージのアクセスモードについて OpenShift Virtualizationに必要なストレージの要件についてはOpenShiftのインストールドキュメントに記載があります。 その一節にライブマイグレーションについての要件の記載があります。 ライブマイグレーションには共有ストレージが必要です。OpenShift Virtualizationのストレージは、ReadWriteMany(RWX)アクセスモードをサポートし、使用する必要があります。 第12章 ベアメタルへのインストール | Red Hat Product Documentation ReadWriteMany(RWX) モードとは、複数のノードからの読み書き(ReadWrite)に対応したアクセスモードのことです。 対して ReadWriteOnce (RWO) とは、1つのノードから読み書きに対応したアクセスモードです。 RWOとRWXのアクセスモードの違い アクセスモードは他にもReadOnlyMany(ROX)やReadWriteOncePod(RWOP)がありますが本記事では詳細な解説は省略します。 OpenShiftが対応しているアクセスモードの詳細については下記ドキュメントの「表3.1 アクセスモード」を参照ください。 3.3. 永続ボリューム | Red Hat Product Documentation OpenShiftではブロック、ファイル、オブジェクトの3種類のストレージタイプに対応しており、RWXモードで利用可能なのは ファイル か オブジェクト のタイプです。 OpenShiftで推奨されるストレージのタイプ 第7章 スケーラビリティとパフォーマンスの最適化 | Red Hat Product Documentation 今回は構築が簡単なNFSを使った ファイルストレージ を共有ストレージとして使用します。 1-2 永続ストレージ OpenShiftがサポートするストレージのタイプは大別して2つのカテゴリーに大別されます。 一時ストレージ :Podとコンテナーが短期間のローカルストレージの操作に使用し、再起動や障害でデータが失われることを想定したストレージ 永続ストレージ :Podとコンテナーがデータの永続性を保証し、再起動や障害後もデータが保持されるストレージ OpenShift Virtualizationでは仮想マシンのディスクが永続化されている必要があるため、使用するストレージのタイプは 永続ストレージ になります。 本記事では一時ストレージについては触れませんので、詳細は下記ドキュメントを参照ください。 1.2. ストレージタイプ | Red Hat Product Documentation 1-3 永続ボリュームの動的プロビジョニング OpenShiftでPodやコンテナで永続ストレージを利用する場合は 永続ボリューム(PV) を利用します。 PVはOpenShiftクラスタ内で永続的なストレージリソースを提供するためのオブジェクトです。 また、PVはクラスタ全体で利用可能なストレージを抽象化し、コンテナのライフサイクルとは独立してデータを保存できます。 PVの 動的プロビジョニング とは、必要なときに必要な量のストレージを自動的に割り当てる機能です。これにより、管理者は事前に大量のストレージを確保する必要がなくなり、効率的なリソース利用が可能となります。 [PVの動的プロビジョニングメリット] 自動化: 手動でのストレージ割り当ての手間が省ける。 効率化: 必要な分だけストレージを割り当てるため、無駄が少ない。 スケーラビリティ: 必要に応じてストレージを増減できるため、システムのスケールアップ・ダウンが容易。 手動プロビジョニングと動的プロビジョニングのPV作成のフローを図で表したものが下記になります。 手動プロビジョニングによるPV作成のフロー 動的プロビジョニングによるPV作成のフロー 1-4 Container Storage Interface (CSI) Container Storage Interface (CSI) は、異なるコンテナーオーケストレーションシステム間でコンテナーストレージを管理するためのAPI仕様です *5 。 ストレージベンダーはCSIに準拠したプラグイン(ドライバー)を開発することで、他のコンテナーオーケストレーションシステムでもプラグインに対応したストレージが機能するようにします。 CSIはストレージを共通化した仕様で抽象化することにより、接続に必要な手順を一律化し、コンテナーオーケストレーションシステムが多様なストレージに対応が可能となります。 OpenShiftはKubernetesを拡張したものであり、純粋なアップストリーム版のKubernetes(いわゆるVanilla Kubernetes)と同様にCSIドライバーを利用できます。 このCSIドライバーを利用することでPVの動的プロビジョニングを行うことができます。 2. 踏み台サーバー上のNFSサーバー設定 今回の検証環境の構成では永続ストレージの元となるNFSサーバーは踏み台サーバー上で実行します。 そのために、まずはLinuxでNFSサーバーを実行する基本機能として、NFSのエクスポートを行います。 踏み台サーバー上のNFSサーバー設定後の構成 2-1 NFSサーバーの設定 NFSをエクスポートする基点となるディレクトリを作成します。 このディレクトリはOSの起動ディスクとは別のディスク上に作成することとします。 第1回で踏み台サーバーの仮想マシンに2つ目のディスクを追加していない場合は追加してください。 govc コマンドで実行する場合は下記のコマンドを使用します。 踏み台サーバーに2つ目のディスクを追加します。 $ node=bastion $ govc vm.disk.create \ -vm ${node} \ -name "${node}/${node}_1.vmdk" \ -size 500G \ -thick=false \ -ds=NVMe ディスクデバイスを確認します。 下記のように2つ目のディスクが追加されました。 $ govc device.ls -vm ${node} | grep disk disk-1000-0 VirtualDisk 104,857,600 KB disk-1000-1 VirtualDisk 524,288,000 KB 2つ目のディスクをOS上で使用できるようにし、 /mnt/nfs にマウントします。 下記のコマンドを実行します。(2つ目のディスクが/dev/sdbにあることとします) $ sudo parted /dev/sdb --script mklabel gpt $ sudo parted /dev/sdb --script mkpart primary ext4 0% 100% $ sudo mkfs.ext4 /dev/sdb1 $ sudo mkdir -p /mnt/nfs $ echo '/dev/sdb1 /mnt/nfs ext4 defaults 0 0' | sudo tee -a /etc/fstab $ sudo systemctl daemon-reload $ sudo mount -a 正常にマウントされているか確認します。 $ df -h /mnt/nfs ファイルシス サイズ 使用 残り 使用% マウント位置 /dev/sdb1 492G 28K 467G 1% /mnt/nfs 次に /etc/exports ファイルにNFSエクスポート用の設定を追記します。 $ sudo vi /etc/exports /mnt/nfs 192.168.1.0/24(rw,async,no_subtree_check,no_root_squash) exportfs -r コマンドを使用して設定の検証を行います。設定に問題がなければ何も出力はされません。 $ sudo exportfs -r $ たとえば、エクスポートするディレクトリが見つからない場合は下記のエラーが出ます。 $ sudo exportfs -r exportfs: Failed to stat /mnt/nfs: No such file or directory NFSエクスポートの設定に問題がなければファイアーウォールの設定を行います。 NFSで使用するポートをファイアーウォール設定に追記します。 $ sudo firewall-cmd --add-service nfs --permanent $ sudo firewall-cmd --reload NFSサービスを自動起動サービスに登録し、同時に起動します。 $ sudo systemctl enable --now nfs-server これでNFSサーバーの設定が完了しました。 3. NFS CSIドライバーの設定 踏み台サーバー上に構築したNFSサーバーを利用してPVの動的プロビジョニングを行うため、OpenShiftに NFS CSI driver for Kubernetes (以下、NFS CSIドライバー)をインストールします。 NFS CSIドライバー導入後の構成 3-1 NFS CSIドライバーについて OpenShiftでPVの動的プロビジョニングを行うためにはストレージとそれに対応したCSIドライバーが必要です。 今回構築したストレージはRHELで立てた汎用的なNFSサーバーなので専用のCSIドライバーがありません。 そこで今回は、汎用的なNFSサーバーをバックエンドに使用しPVの動的プロビジョニングを行うことができるNFS CSIドライバーを利用します。 このNFS CSIドライバーはKubernetes CSIでホストされているリポジトリの1つです。OSSで開発されておりApache-2.0 licenseに従い無償で利用できます。 kubernetes-csi/csi-driver-nfs: This driver allows Kubernetes to access NFS server on Linux node. NFS CSIドライバーはfsGroupPolicy、Volume Snapshot、Volume Cloningに対応しています。 実稼働環境ではストレージベンダーなどの製品をご利用ください。 3-2 NFS CSIドライバーの動作 NFS CSIドライバーの動作の流れは下記の通りです NFS CSIドライバーの動作 3-3 NFS CSIドライバーのインストール NFS CSIドライバーをインストールする流れは下記のとおりです。 Helmのインストール NFS CSIドライバーのインストール 現時点ではコマンドの詳細を深く理解する必要はありません。まずはおまじない的にコマンドをコピペして実行してください。 (1)Helmのインストール NFS CSIドライバーのインストールでHelm *6 を使用します。 Helmはパッケージマネージャーの1つで、アプリケーションをパッケージ(Helmではチャートという)としてKuberenetes上に簡単にデプロイできる仕組みです。 今回の構成では踏み台サーバーにHelmをインストールします。Helmのインストールドキュメントは下記です(本記事ではRed Hatが提供しているHelmのバイナリを利用します)。 6.2. Helm のインストール | Red Hat Product Documentation x86_64の環境にHelmをインストールするコマンド例は下記のとおりです。 $ sudo curl -L https://mirror.openshift.com/pub/openshift-v4/clients/helm/latest/helm-linux-amd64 -o /usr/local/bin/helm $ sudo chmod +x /usr/local/bin/helm Helmのインストール後、 helm コマンドを実行して動作確認を行います。 $ helm version WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/user/work/auth/kubeconfig WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/user/work/auth/kubeconfig version.BuildInfo{Version:"v3.14.4+37.el9", GitCommit:"7163c12e65c8c0a40334c0a4b514b991ea37aa21", GitTreeState:"clean", GoVersion:"go1.21.9 (Red Hat 1.21.9-2.el9_4)"} KUBECONFIG 環境変数がセットされていて、かつ kubeconfig ファイルのパーミッションが所有者以外から読み込み可能になっているとコマンドの出力に警告が出ます。 気になる方は chmod コマンドでパーミッションを変更してください。 $ chmod 600 auth/kubeconfig (2)NFS CSIドライバーのインストール NFS CSIドライバーはOpenShiftにインストールします。初めにチャートリポジトリを追加し、その後にインストールを行います。 helm repo add コマンドでNFS CSIドライバーのチャートリポジトリを追加します。 実行コマンド $ helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts 実行コマンドと結果 $ helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts "csi-driver-nfs" has been added to your repositories ~/.config/helm ディレクトリが作成され、参照するリポジトリの情報が保存されます helm install コマンドでNFS CSIドライバーをインストールします。 --version オプションを使ってバージョンを指定します。(記事執筆時点での最新版はv4.8.0) 実行コマンド $ helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.8.0 --namespace kube-system :インストール先のネームスペースに kube-system を指定 --version v4.8.0 :インストールするバージョンを指定。指定するバージョンはNFS CSIドライバーのリリースページ *7 を参照のこと helm install コマンドを実行すると下記のような応答が出力されます 実行コマンドと結果 $ helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.8.0 NAME: csi-driver-nfs LAST DEPLOYED: Fri Jul 19 10:40:55 2024 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: The CSI NFS Driver is getting deployed to your cluster. To check CSI NFS Driver pods status, please run: kubectl --namespace=kube-system get pods --selector="app.kubernetes.io/instance=csi-driver-nfs" --watch NFS CSIドライバーが正常にインストールできたかどうかは次の手順で確認します。 (追記)NFS CSIドライバーのアップデート NFS CSIドライバーのリリースページ *8 で新しいバージョンがリリースされた場合は、 helm repo update を行うことで新しいバージョンのインストールを行うことができます。 下記はチャートリポジトリのアップデートを行い、 v4.9.0 をインストールする手順です。 実行コマンド $ helm repo update $ helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.9.0 実行コマンドと結果 $ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "csi-driver-nfs" chart repository Update Complete. ⎈Happy Helming!⎈ $ helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.9.0 NAME: csi-driver-nfs LAST DEPLOYED: Thu Sep 26 23:18:01 2024 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: The CSI NFS Driver is getting deployed to your cluster. To check CSI NFS Driver pods status, please run: kubectl --namespace=kube-system get pods --selector="app.kubernetes.io/instance=csi-driver-nfs" --watch (3)NFS CSIドライバーのインストールの確認 OpenShiftのWebコンソールから「管理者向け表示」のプルダウンを選択し「開発者」を選択します。 これにより開発者向け表示(Developerパースペクティブ)に切り替えることができます。 開発者向け表示(Developerパースペクティブ)に切り替える 左のメニューから「トポロジー」を選択します。プロジェクトのプルダウンメニューから「すべてのプロジェクト」を選択します。 「デフォルトプロジェクトの表示」スイッチをオンにします。 トポロジーメニューのプロジェクト表示 「デフォルトプロジェクトの表示」をオンにすることでOpenShift上の管理用のプロジェクトの選択が可能になります。 入力欄に kube-system と入力して表示のフィルタリングを行い、プロジェクト欄に表示された kube-system を選択します。 フィルタリングを行いkube-systemを選択 画面内に「D」のアイコンがついた csi-nfs-controller というオブジェクト(Deployment)と、「DS」のアイコンがついた csi-nfs-node というオブジェクト(DaemonSet)が表示されます。 csi-nfs-controller がNFS CSIドライバーの管理コンテナ、 csi-nfs-node が各ノード上で稼働する実行コンテナになります。 csi-nfs-controller と csi-nfs-node の2つを合わせたものが csi-driver-nfs という名前のHelmチャートとしてデプロイされています。 csi-nfs-controllerのDeploymentの詳細表示 csi-nfs-nodeのDaemonSetの詳細表示 左のメニューからHelmを選択すると、現在選択しているプロジェクトに登録済みのHelmリリース *9 の情報が表示されます。 デプロイされたHelmリリースの表示 「HR」アイコンが付いたHelmリリース名(ここでは csi-driver-nfs )のリンクを選択します。 Helmリリースの詳細 リソースタブを選択すると、Helmでインストールされたリソースの名前やタイプが一覧で表示されます。 3-4 ストレージクラスとボリュームスナップショットクラスの作成 インストールしたNFS CSIドライバーを使ってPVの動的プロビジョニングを行うために ストレージクラス (StorageClass)を作成します。 ストレージクラスとはPVの動的プロビジョニングを定義するために使用されます。ユーザーは必要なストレージクラスを指定して永続ボリューム要求(PVC)を作成します。 ストレージクラスの詳細については下記のドキュメントを参照してください。 5.6. デフォルトストレージクラスの管理 | Red Hat Product Documentation また、合わせてOpenShift Virtualizationで仮想マシンのスナップショットを取得するための ボリュームスナップショットクラス (VolumeSnapshotClass)も作成します。 ボリュームスナップショットについては下記のドキュメントを参照してください。 5.4. CSI ボリュームスナップショット | Red Hat Product Documentation (1)ストレージクラスの作成 下記のコマンドでストレージクラスのカスタムリソースを storageclass-nfs.yaml という名前で作成します。 $ cat > storageclass-nfs.yaml <<EOF apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-csi provisioner: nfs.csi.k8s.io parameters: server: 192.168.1.206 share: /mnt/nfs reclaimPolicy: Delete volumeBindingMode: Immediate EOF server: 192.168.1.206 :NFSサーバーのIPアドレス(またはホスト名)を指定します share: /mnt/nfs :NFSサーバー上でエクスポートしているパス名を指定します reclaimPolicy: Delete :PVを削除した時にNFSサーバー上のデータを保持するかどうかを指定します。 Delete はPVCの削除と同時にPVも削除され、NFSサーバー上の実データも削除されます。 PVCの削除後もPVとして残す場合は Retain 、PVは削除しつつもNFSサーバー上の実データを残す場合は Archive を指定します。 下記のコマンドでストレージクラスを作成します。 $ oc create -f storageclass-nfs.yaml (2)ボリュームスナップショットクラスの作成 下記のコマンドでボリュームスナップショットクラスのカスタムリソースを snapshotclass-nfs.yaml という名前で作成します。 $ cat > snapshotclass-nfs.yaml <<EOF apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass metadata: name: csi-nfs-snapclass driver: nfs.csi.k8s.io deletionPolicy: Delete EOF 下記のコマンドでボリュームスナップショットクラスを作成します。 $ oc create -f snapshotclass-nfs.yaml 3-5 デフォルトストレージクラスの設定 デフォルトストレージクラスとは2つ以上のストレージクラスが存在する場合に 標準的に使用されるストレージクラス のことです。 今回の構成ではストレージクラスは1つしか作成されていませんが、明示的に設定をしておくことで他のストレージクラスよりも優先的に利用するようにしておきます。 デフォルトストレージクラスを設定するには下記のコマンドを実行します。 今回はストレージクラス名: nfs-csi に対して通常のコンテナアプリケーションと仮想マシンの両方にデフォルト設定を行います。 $ oc patch storageclass nfs-csi -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' $ oc patch storageclass nfs-csi -p '{"metadata": {"annotations":{"storageclass.kubevirt.io/is-default-virt-class":"true"}}}' 同様にデフォルトボリュームスナップショットクラスを設定するコマンドを実行します。 ボリュームスナップショットクラス名は csi-nfs-snapclass を指定します。 $ oc patch volumesnapshotclass csi-nfs-snapclass --type merge -p '{"metadata": {"annotations":{"snapshot.storage.kubernetes.io/is-default-class":"true"}}}' $ oc patch volumesnapshotclass csi-nfs-snapclass --type merge -p '{"metadata": {"annotations":{"snapshot.storage.kubevirt.io/is-default-virt-class":"true"}}}' 設定が反映されているか下記のコマンドを実行して確認を行います。 oc get コマンドで引数に storageclass と nfs-csi を指定し、さらに -o yaml オプションを追加して、ストレージクラスの設定内容をYAML形式で出力を行います。 $ oc get storageclass nfs-csi -o yaml 出力結果内の annotations: に先ほど設定した値が反映されているか確認できます。下記の出力結果を展開して内容を確認ください。 出力結果を開く $ oc get storageclass nfs-csi -o yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: annotations: storageclass.kubernetes.io/is-default-class: "true" storageclass.kubevirt.io/is-default-virt-class: "true" creationTimestamp: "2024-07-23T05:35:49Z" name: nfs-csi resourceVersion: "596631" uid: 86a54044-89fa-4f49-8c35-6c5bc6cff696 parameters: server: 192.168.1.206 share: /mnt/nfs provisioner: nfs.csi.k8s.io reclaimPolicy: Delete volumeBindingMode: Immediate 同様にボリュームスナップショットクラスの設定内容を確認します。 oc get コマンドの引数は volumesnapshotclass を csi-nfs-snapclass 指定します。 $ oc get volumesnapshotclass csi-nfs-snapclass -o yaml 出力結果を開く $ oc get volumesnapshotclass csi-nfs-snapclass -o yaml apiVersion: snapshot.storage.k8s.io/v1 deletionPolicy: Delete driver: nfs.csi.k8s.io kind: VolumeSnapshotClass metadata: annotations: snapshot.storage.kubernetes.io/is-default-class: "true" snapshot.storage.kubevirt.io/is-default-virt-class: "true" creationTimestamp: "2024-07-23T05:37:13Z" generation: 1 name: csi-nfs-snapclass resourceVersion: "597248" uid: 774868f9-23f8-46c7-b02e-bf832d6c31ec 3-6 動的プロビジョニングの動作テスト NFS CSIドライバーの設定ができたので実際にサンプルのDeploymentを実行して動的プロビジョニングの動作テストを行います。 (1)サンプルファイルのダウンロード NFSプロビジョナーのリポジトリで公開されているサンプルのファイルをダウンロードします。 PVCとPodの実行が定義されたDeploymentのYAMLファイルをダウンロードします。 $ wget https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/deploy/example/deployment.yaml $ ls -d deployment.yaml deployment.yaml (2)PVCとPodの作成 oc create コマンドでYAMLファイルからリソースを作成します。 -f オプションで読み込むYAMLファイルを指定します。 最初にテスト実行用のプロジェクトを作成し、そのプロジェクト内にリソースを作成します。 下記のコマンドでプロジェクトを新規作成します。名前は test とします。 実行コマンド $ oc new-project test 実行コマンドと結果 $ oc new-project test Now using project "test" on server "https://api.ocp.home.lab:6443". You can add applications to this project with the 'new-app' command. For example, try: oc new-app rails-postgresql-example to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application: kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname 続けてDeploymentリソースを作成します。 実行コマンド $ oc create -f deployment.yaml 実行コマンドと結果 $ oc create -f deployment.yaml persistentvolumeclaim/pvc-deployment-nfs created deployment.apps/deployment-nfs created PVCとPodの実行を定義したDeploymentが作成されました。 (3)確認 Webコンソールの管理者向け表示のメニューから「ストレージ>PersistentVolumeClaims」を選択すると、作成されたPVCとバインドされたPVが一覧で表示されます。 「プロジェクト」選択プルダウンから test を選ぶと、先ほど作成した test プロジェクト上に作成されたPVCが表示されます。 サンプルのDeploymentから作成されたPVCとPV このサンプルでは下記の情報が確認できます。 PVC:pvc-deployment-nfs PV:pvc-43c68d68-95f2-4b2a-99cf-4eef0debba39 PVの容量:10 GiB 使用したストレージクラス:nfs-csi 踏み台サーバー上のNFSエクスポートディレクトリを確認すると、PV用のディレクトリが自動で作成されていることが分かります。 $ tree /mnt/nfs/ /mnt/nfs/ └── pvc-43c68d68-95f2-4b2a-99cf-4eef0debba39 └── outfile 1 directory, 1 file NFSサーバー上に作成されるディレクトリの命名規則は PV名 と同じものになります。 Webコンソールの管理者向け表示のメニューから「Workloads>Pods」を選択すると、実行中のPodが一覧で表示されます。 サンプルのPod( deployment-nfs-7579c47f6-r6zbq )のステータスが Running になっており、このPodが正常に実行していることが分かります。 testプロジェクトで実行中のPod一覧 Pod名の deployment-nfs-7579c47f6-r6zbq のリンクを選択するとPodの詳細画面が表示されます。 このコンテナが mcr.microsoft.com/oss/nginx/nginx コンテナイメージから作成されていて状態が Running になっており、コンテナの実行が継続していることが確認できます。 また、このコンテナではPVは nfs という名前でボリュームとして扱われており、コンテナ内の /mnt/nfs ディレクトリに読み書き可能でマウントされています。 サンプルPodの詳細情報 このサンプルではコンテナの実行コマンドとしてホスト名と日時を1秒ごとにループで書き込み続けるようにプログラムされています *10 。 そのため、サンプルのPod起動後にNFSサーバー上のディレクトリを確認すると、コンテナの中で作成された outfile ファイルに継続的にデータが書き込み続けていることが分かります。 $ tail -f /mnt/nfs/pvc-43c68d68-95f2-4b2a-99cf-4eef0debba39/outfile deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:02 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:03 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:04 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:05 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:06 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:07 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:08 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:09 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:10 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:11 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:12 UTC 2024 deployment-nfs-7579c47f6-r6zbq Tue Jul 23 08:04:13 UTC 2024 ... (4)サンプルのPodとPVの削除 作成したサンプルのPodとPVを削除する場合は下記のコマンドを実行します。 oc delete project コマンドでプロジェクトごとOpenShift上のリソースを削除します。 実行コマンド $ oc delete project test 実行コマンドと結果 $ oc delete project test project.project.openshift.io "test" deleted 実行中のコンテナが強制的に停止し、すべてのリソースが削除するまで数十秒程度かかります。 PV削除後のNFSサーバー上の実体ディレクトリは下記のようになります。 $ tree /mnt/nfs/ /mnt/nfs/ 0 directories, 0 files PV削除と同時に実体のディレクトリも削除されます (5)NFS CSIドライバーの削除 NFS CSIドライバーの削除を行う場合は helm delete コマンドを実行します。 helm delete コマンドに引数として csi-driver-nfs とネームスペースに kube-system を指定して実行します。 $ helm uninstall csi-driver-nfs -n kube-system 4. イメージレジストリの設定 NFS CSIドライバーを設定したことで永続ボリュームを利用できるようになりました。 次は、OpenShiftのインストール後の作業の1つであるイメージレジストリの設定を行います。 この作業はストレージの設定が事前に必要なため、第2回のインストール後の作業では対象外としました 4-1 イメージレジストリーの構成 イメージレジストリはOpenShiftの内部で実行されるコンテナレジストリーです。 イメージレジストリーはパブリックなコンテナレジストリーと同様に、OpenShift上でビルドしたコンテナイメージを登録したり、登録したコンテナイメージからコンテナを実行できます。 また、OpenShiftの外部との接続口(ルート)を作成することでイメージレジストリーを外部へ公開できます。 イメージレジストリーの構成図 イメージレジストリーの設定方法はOpenShiftのインストールドキュメントに記載があります。下記のドキュメントを参照してください。 第24章 任意のプラットフォームへのインストール | Red Hat Product Documentation 実稼働環境におけるレジストリーの推奨ストレージは オブジェクトストレージ です(次点はブロックストレージ)。 本記事で紹介するファイルストレージを使った構成はあくまで検証用途での利用を前提としています。 ファイルストレージは、実稼働ワークロードを使用した OpenShift イメージレジストリークラスターのデプロイメントには推奨されません。 https://docs.redhat.com/ja/documentation/openshift_container_platform/4.16/html/scalability_and_performance/scalability-and-performance-optimization#specific-application-storage-recommendations 4-2 イメージレジストリーの設定 まず、現在のイメージレジストリーの設定を確認します。 下記のコマンドで configs.imageregistry.operator.openshift.io のリソースから storage と managementState の値を取得します。 実行コマンド $ oc get configs.imageregistry.operator.openshift.io -o json | jq '.items[] | {storage: .spec.storage, managementState: .spec.managementState}' 実行コマンドと結果 $ oc get configs.imageregistry.operator.openshift.io -o json | jq '.items[] | {storage: .spec.storage, managementState: .spec.managementState}' { "storage": {}, "managementState": "Removed" } storage は空の値、 managementState は Removed がセットされています。 次に、下記のコマンドを実行してレジストリーPodが 存在しないこと を確認します。 oc get pod コマンドで -l オプションを使用し、ラベルが docker-registry=default であるポッドをフィルタリングします。 実行コマンド $ oc get pod -n openshift-image-registry -l docker-registry=default 実行コマンドと結果 $ oc get pod -n openshift-image-registry -l docker-registry=default No resources found in openshift-image-registry namespace. イメージレジストリーがまだ設定されていないことが確認できました。下記のコマンドを実行し、イメージレジストリーを有効化します。 実行コマンド $ oc patch config.imageregistry.operator.openshift.io/cluster --type merge -p '{"spec":{"storage":{"pvc":{"claim":""}}}}' $ oc patch config.imageregistry.operator.openshift.io/cluster --type merge -p '{"spec":{"managementState":"Managed"}}' 実行コマンドと結果 $ oc patch config.imageregistry.operator.openshift.io/cluster --type merge -p '{"spec":{"storage":{"pvc":{"claim":""}}}}' config.imageregistry.operator.openshift.io/cluster patched $ oc patch config.imageregistry.operator.openshift.io/cluster --type merge -p '{"spec":{"managementState":"Managed"}}' config.imageregistry.operator.openshift.io/cluster patched コマンドの実行後、先ほどの設定を再度確認します。 claim に image-registry-storage の値が自動で追加されています。 実行コマンド $ oc get configs.imageregistry.operator.openshift.io -o json | jq '.items[] | {storage: .spec.storage, managementState: .spec.managementState}' 実行コマンドと結果 $ oc get configs.imageregistry.operator.openshift.io -o json | jq '.items[] | {storage: .spec.storage, managementState: .spec.managementState}' { "storage": { "managementState": "Managed", "pvc": { "claim": "image-registry-storage" } }, "managementState": "Managed" } しばらくしてからレジストリーPodを確認すると、下記のように先ほどは無かったレジストリーPodが起動していることが分かります。 $ oc get pod -n openshift-image-registry -l docker-registry=default NAME READY STATUS RESTARTS AGE image-registry-5cd6bf8ddf-mgkpm 1/1 Running 0 53s デフォルトではレジストリーPodのレプリカ数は1で実行されます。 PVのアクセスモードがRWXをサポートしている場合はレジストリーPodのレプリカ数を2にして高可用性構成が可能です。 下記のコマンドを実行して自動で作成されたPVCとPVの設定を確認します。 イメージレジストリーのPVはデフォルトで100GiBの容量を使用します。 $ oc get pvc -n openshift-image-registry NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE image-registry-storage Bound pvc-b3c88568-404c-40c1-a4c8-d252b804a9fc 100Gi RWX nfs-csi <unset> 2m4s $ oc get pv -n openshift-image-registry NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE pvc-b3c88568-404c-40c1-a4c8-d252b804a9fc 100Gi RWX Delete Bound openshift-image-registry/image-registry-storage nfs-csi <unset> 2m11s 4-3 レジストリーの公開 OpenShift上で起動したイメージレジストリーを外部から利用できるように公開設定を行います。 イメージレジストリーの公開方法のドキュメントは下記です。 第5章 レジストリーの公開 | Red Hat Product Documentation 下記のコマンドを実行してイメージレジストリーを公開します。 実行コマンド $ oc patch configs.imageregistry.operator.openshift.io/cluster --type=merge -p '{"spec":{"defaultRoute":true}}' 実行コマンドと結果 $ oc patch configs.imageregistry.operator.openshift.io/cluster --type=merge -p '{"spec":{"defaultRoute":true}}' config.imageregistry.operator.openshift.io/cluster patched イメージレジストリーの公開後、下記のコマンドで接続するためのURL( HOST/PORT )を確認できます。 $ oc get route default-route -n openshift-image-registry NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD default-route default-route-openshift-image-registry.apps.ocp.home.lab image-registry <all> reencrypt None 4-4 レジストリーの操作 (1)ログイン 外部のコンテナツール(今回はPodmanを使用します)から公開したイメージレジストリーを利用するためにはコンテナレジストリーへのログインが必要です。 下記のコマンドを実行してコンテナレジストリーへのログインを行います。 イメージレジストリーのURLを取得し HOST 環境変数へセットします。 $ HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}') $ echo ${HOST} default-route-openshift-image-registry.apps.ocp.home.lab Ingress Operatorの証明書を取得してシステムの信頼された証明書ストアに追加することで、イメージレジストリーへのHTTPSでのアクセスを行えるようにします。 oc get secret で証明書を取得し、踏み台サーバー上の証明書ストアに保存します。 $ oc get secret -n openshift-ingress router-certs-default -o go-template='{{index .data "tls.crt"}}' | base64 -d | sudo tee /etc/pki/ca-trust/source/anchors/${HOST}.crt > /dev/null 信頼されたルート証明書の一覧を更新します。 $ sudo update-ca-trust enable podman login コマンドを実行しイメージレジストリーへログインを行います。 ログインに使用するユーザーは ocpadmin を使用します。 ocpadmin でログインしていない場合は事前に oc login を実行します(連載第2回を参照)。 $ unset KUBECONFIG $ oc login -u ocpadmin https://api.ocp.home.lab:6443 $ podman login -u ocpadmin -p $(oc whoami -t) ${HOST} Login Succeeded! が表示されたらログイン成功です。 (2)イメージのプッシュ Podmanでサンプルのコンテナイメージを作成し、イメージレジストリーへプッシュします。 下記のコマンドを実行し、ベースイメージにUBI9を使用したContainerfileを作成します。 $ cat > Containerfile <<EOF FROM ubi9 RUN echo "hello" | tee hello.txt EOF podman build コマンドでコンテナイメージをビルドします。 $ podman build -t ${HOST}/openshift/push-test . 出力結果を開く $ podman build -t ${HOST}/openshift/push-test . STEP 1/2: FROM ubi9 Resolved "ubi9" as an alias (/etc/containers/registries.conf.d/001-rhel-shortnames.conf) Trying to pull registry.access.redhat.com/ubi9:latest... Getting image source signatures Checking if image destination supports signatures Copying blob f50ab65647ec done | Copying config e9beb314b7 done | Writing manifest to image destination Storing signatures STEP 2/2: RUN echo "hello" | tee hello.txt hello COMMIT default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test --> 4d7c9eb63a75 Successfully tagged default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test:latest 4d7c9eb63a75563e6c4deee82d472ddf5fd0770ca4850b0e2e379ee03fe280fc podman push コマンドでコンテナイメージをプッシュします。 $ podman push ${HOST}/openshift/push-test 出力結果を開く $ podman push ${HOST}/openshift/push-test Getting image source signatures Copying blob 09a48287d5f7 done | Copying blob f36b8ecab85c done | Copying config 4d7c9eb63a done | Writing manifest to image destination (3)プッシュしたイメージの確認 Skopeoを使ってプッシュしたコンテナイメージがイメージレジストリーに登録されているか確認します。 下記のコマンドを実行します。 すでに podamn login を実行しているため skopeo login の実行は不要です(SkopeoはPodmanのログイン情報を利用できます)。 $ skopeo inspect docker://${HOST}/openshift/push-test 下記を展開して出力結果を確認ください。 出力結果を開く $ skopeo inspect docker://${HOST}/openshift/push-test { "Name": "default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test", "Digest": "sha256:4c537beccd99c1853f7e242dcfab054cbaf0bf5535233bcb2ac24335f2f8492f", "RepoTags": [ "latest" ], "Created": "2024-07-09T21:16:33.272504929Z", "DockerVersion": "", "Labels": { "architecture": "x86_64", "build-date": "2024-06-28T07:36:05", "com.redhat.component": "ubi9-container", "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI", "description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.", "distribution-scope": "public", "io.buildah.version": "1.33.7", "io.k8s.description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.", "io.k8s.display-name": "Red Hat Universal Base Image 9", "io.openshift.expose-services": "", "io.openshift.tags": "base rhel9", "maintainer": "Red Hat, Inc.", "name": "ubi9", "release": "1123.1719560047", "summary": "Provides the latest release of Red Hat Universal Base Image 9.", "url": "https://access.redhat.com/containers/#/registry.access.redhat.com/ubi9/images/9.4-1123.1719560047", "vcs-ref": "92a4a475241865d0d11bd861fb2b29fbd9b17df0", "vcs-type": "git", "vendor": "Red Hat, Inc.", "version": "9.4" }, "Architecture": "amd64", "Os": "linux", "Layers": [ "sha256:f50ab65647ec96ba313779f24c41e04bc6fde3e3ee79ee377ea8fd1901b896d5", "sha256:68513cceebd5b717b7e307a2c2ff646147e5a84b16657755c25da1be2732bf15" ], "LayersData": [ { "MIMEType": "application/vnd.oci.image.layer.v1.tar+gzip", "Digest": "sha256:f50ab65647ec96ba313779f24c41e04bc6fde3e3ee79ee377ea8fd1901b896d5", "Size": 79313334, "Annotations": null }, { "MIMEType": "application/vnd.oci.image.layer.v1.tar+gzip", "Digest": "sha256:68513cceebd5b717b7e307a2c2ff646147e5a84b16657755c25da1be2732bf15", "Size": 270, "Annotations": null } ], "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "container=oci" ] } Webコンソール上で確認する場合は、メニューの「Builds>ImageStreams」を選択します。 イメージレジストリーに登録されているイメージの一覧が表示されます。 名前で検索できますのでプッシュしたイメージ名: push-test を入力します。 OpenShiftの外部からプッシュしたイメージの表示 push-test のリンクを選択するとイメージの詳細画面が表示されます。 パブリックイメージリポジトリー に表示されているURLが、OpenShiftの外部からこのイメージをプルする時のURLになります。 イメージレジストリーの登録したイメージの詳細表示 (4)OpenShift上のイメージをプルする OpenShift上のイメージをローカルにプルするテストを行います。 ローカルにあるコンテナイメージを削除します。 $ podman images $ podman rmi push-test:latest 出力結果を開く $ podman images REPOSITORY TAG IMAGE ID CREATED SIZE default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test latest 4d7c9eb63a75 19 minutes ago 220 MB registry.access.redhat.com/ubi9 latest e9beb314b7a2 11 days ago 220 MB $ podman rmi push-test:latest Untagged: default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test:latest Deleted: 4d7c9eb63a75563e6c4deee82d472ddf5fd0770ca4850b0e2e379ee03fe280fc podman pull コマンドでイメージをプルします。 $ podman pull ${HOST}/openshift/push-test $ podman images 出力結果を開く $ podman pull ${HOST}/openshift/push-test Trying to pull default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test:latest... Getting image source signatures Copying blob f50ab65647ec skipped: already exists Copying blob 68513cceebd5 done | Copying config 4d7c9eb63a done | Writing manifest to image destination 4d7c9eb63a75563e6c4deee82d472ddf5fd0770ca4850b0e2e379ee03fe280fc $ podman images REPOSITORY TAG IMAGE ID CREATED SIZE default-route-openshift-image-registry.apps.ocp.home.lab/openshift/push-test latest 4d7c9eb63a75 21 minutes ago 220 MB registry.access.redhat.com/ubi9 latest e9beb314b7a2 11 days ago 220 MB イメージレジストリー上のイメージをプルすることができました。 まとめ OpenShift Virtualizationで使用するための共有ストレージの作成を行いました。 汎用的なNFSサーバーをバックエンドに使用し、NFS CSIドライバーを使用することでPVの動的なプロビジョニングが行えます。 このストレージはOpenShift Virtualization以外でも使用できるため、イメージレジストリーのイメージ保存用のストレージの設定を行いました。 また、イメージレジストリーを公開設定を行うことにより、OpenShiftの外部からイメージをプッシュ、プルできるようになります。 第1回からここまでの作業でようやくOpenShift Virtualizationのインストールを行う準備が整いました。 次はいよいよOpenShift Virtualizationの設定になります。 (次回予告) 次回はOpenShift Virtualizationのインストールと仮想マシンの実行方法について解説します。 *1 : Red Hat OpenShift Kubernetes Engine | Red Hat *2 : Red Hat OpenShift Platform Plus とは?をわかりやすく解説 *3 : Red Hat OpenShift Data Foundation | Red Hat *4 : 7.1.2.1. 特定アプリケーションのストレージの推奨事項を参照 第7章 スケーラビリティとパフォーマンスの最適化 | Red Hat Product Documentation *5 : container-storage-interface/spec: Container Storage Interface (CSI) Specification. *6 : Helm *7 : Releases · kubernetes-csi/csi-driver-nfs *8 : Releases · kubernetes-csi/csi-driver-nfs *9 : OpenShift上にHelmでデプロイされたアプリケーションやサービスのインスタンスのこと *10 : 詳細を知りたい方はdeployment.yamlファイルの中身を参照ください