本記事は、Nutanix Advent Calendar 2020の20日目、12月20日分(ただし2日遅れ)としての投稿になります。
本記事の内容は、この日付時点の情報(Nutanix CSI Plugin 2.2.x系)に基づいています。そのため,今後新しいバージョンが提供された場合に,当該記載と矛盾が生じる場合がありますのでご注意ください。
はじめに
アウトプットが出せないうえに進ちょくも出せないエンジニアの @hanakara_milk です、こんばんは。
この記事の続きとして、なるべく時間を空けないうちに、NutanixのFilesのファイルストレージを利用したPersistent Volumesについても紹介したいと思います。
これが昨年のNutanix Advent Calendar 2019の自分の担当分の結びに書いた言葉ですが、 ほぼ丁度1年後にやっとNutanix CSI Plugin、Files編を書いています。大変申し訳ございません。
さて、昨年に引き続きKubernetesとストレージネタを引っ張ってきました。ここ数年、Kubernetesにおけるステートフルアプリケーションのユースケースが増加傾向にあることと、様々ななCSI実装の拡張やKubernetesのストレージソリューション、エコシステムが登場していることとの間には大きな関連性がある見てよいと思っています。
CSI実装の拡張やストレージエコシステムが増えてきたから、Kubernetesにおけるステートフルアプリケーションのユースケースが増えてきたとも言えますし、Kubernetesにおけるステートフルアプリケーションの要件が増えているからCSI実装の拡張やストレージエコシステムが増えてきたとも言えるかと思います。
その一方で、ステートフルアプリケーションが増えれば増えるほど、データの可用性や耐障害性、運用性などをどうやって担保するのか、そのためにはどのようなアーキテクチャーやインフラストラクチャーが必要なのか考える必要がでてきます。そんな悩みが、昨今のKubernetesのストレージソリューションやエコシステムの急速な進歩を推し進めているのだと思います。
なお、Kubernetesから利用可能なNutanixのストレージについての利点や簡単な概要については、昨年のKubernetes Advent Calendar 2019の2枚目の15日目をご覧下さい。
KubernetesからのNutanixストレージ上にあるNFSの利用
あらためまして、今回の投稿は、昨年のNutanix Advent Calendar 2019の22日目ではkubeadmでデプロイしたNutanixの外にあるKubernetesから、NutanixのストレージをPersistent Volumesとして、かつブロックストレージで利用することが簡単にできる、と言った内容でしたが、この投稿の冒頭でも触れていますが、その続編的な内容でファイルレベルのストレージ(NFS)編となります。
Nutanix CSI Volume PluginからNFSを利用するための要件
昨年紹介したブロックストレージをCSI Volume Pluginを使って利用する場合、Nutanix側に特にコレと言った要件はないのですが、ファイルレベルストレージを利用する場合には、少しだけ追加の要件があります。
KubernetesからNutanixストレージをNFSで利用する際には、Nutanix FilesのNFSを利用します。そのため、まずNutanix Filesが必要となります。Nutanix Filesは、Nutanixのストレージをファイルサーバー領域として使える機能で、1TiBまで誰でも無償で利用可能(Nutanix FilesのライセンスはTiB単位)です。
単純にNutanixのストレージ領域をファイルサーバーに提供するだけではなく、Nutanixストレージの従来の高いパフォーマンスと可用性を最大限活かせるよう、基本的に最小3台のNASヘッドとなるファイルサーバー用仮想アプライアンスをNutanix上に起動してNASヘッドクラスターを構成し、ファイルアクセスを分散処理しつつスケールアウト型のファイルサーバーとして機能します。
Nutanix Filesについては、今年のNutanix Advent Calendarにも参加している @masago_Omuomu さんのBlogの中で特集を組んで詳しく紹介してくれていますので、そちらをご覧下さい。
Nutanix CSI Volume PluginからNFSを利用するための準備
Nutanix CSI Volume PluginからNFSを利用するための要件であるNutanix Files側には、特にコレと言って特別な設定はないため(正常にNutanix Filesがデプロイされていることが前提ですが)、ここでは、NFSを利用したいKubernetes側の設定について記載していきます。
とは言うものの、Kubernete側の設定は、昨年の記事とほとんど差はありません。今回も、前回と同様にNutanixの外にある環境にkubeadmで立てたKubernetesにNutanix CSI Volume Pluginをインストールして利用します。
CSIの具体的な導入の手順は、以下のgithubにリンクされているドキュメントからアクセス可能です。
https://github.com/nutanix/csi-plugin
Nutanix CSI driver v2.2.0 documentation
https://portal.nutanix.com/page/documents/details?targetId=CSI-Volume-Driver-v2_2:CSI-Volume-Driver-v2_2
以下の4つのマニフェストをkubectl applyしていきます。
- ntnx-csi-rbac.yaml
- ntnx-csi-provisioner.yaml
- ntnx-csi-node.yaml
- csi-driver.yaml
加えて、secretも作成します。secretは、Nutanixのアドレス、管理者名(基本はadmin)及び管理者名のパスワードをパラメーターとして作成します。secretもサンプルが、上記のGithubから取ってきたcsi-pluginの中に含まれているので、そちらを参考に作成します。
前回の手順と少しだけ変わる部分が、StorageClassの作成です。前回はブロックストレージを利用するためのStorageClassを作成しました。今回はファイルレベルストレージ、NFSを利用するためのStorageClassを作成していきます。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: acs-afs
provisioner: csi.nutanix.com
parameters:
nfsServer: fs1.ce.local
nfsPath: nfs
storageType: NutanixFiles
こちらはnfsServer
の部分とnfsPath
をNutanix Filesで構成したNFSのサーバー名とNFSシェア名に変更して、applyするだけで問題はありません、もしStorageClass名を変更したい場合は任意のものに変更します。
今回の環境では、Nutanix Community Edition上に展開したNutanix Filesで、NFSのみのファイルサーバーを構成しています。ファイルサーバー名はfs1
、NFSシェア名はnfs
としています。一般的なNFSのサーバーのパスとしては、nfs://fs1.ce.local:/nfs/
となる構成です。
※ce.localは、今回構成した環境のNutanix Filesやその他のためのドメインです。
Nutanix FilesのNFSシェアをKubernetesから利用してみる
次に、今回は時間が押しているためPersistentVolumeClaimからの要求でNFS領域がどのように扱われるかだけ見ていきます。今回の接続環境について確認しておきます。
今回は操作しているPC上のVirtualBoxに立てたCentOS上に、シングル構成のKubernetesクラスターをkubeadmで構成し、そこからNuatnix Community Edition上のFilesのNFSをNutanix CSI Pluginを介して利用します。
また、Kubernetes上からpersistentVolumeClaim(PVC)で要求されたストレージが、Nutanix FilesのNFSシェアがどのように見えるのかを観察するためのVMをNutanix Community Edition上に1台立てて、mount
しておきます。以下のとおり、まだNFSにはファイル・フォルダ含めて何もない状態です。
[root@mon-vm mnt]# mkdir mon-vm
[root@mon-vm mnt]#
[root@mon-vm mnt]# mount -t nfs -o vers=4 fs1.ce.local:/ /mnt/mon-vm/
[root@mon-vm mnt]#
[root@mon-vm mnt]# mount | grep fs1
fs1.ce.local:/ on /mnt/mon-vm type nfs4 (rw,relatime,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.137.108,local_lock=none,addr=192.168.137.30)
[root@mon-vm mnt]#
[root@mon-vm mnt]# cd mon-vm/nfs/
[root@mon-vm nfs]# pwd
/mnt/mon-vm/nfs
[root@mon-vm nfs]#
[root@mon-vm nfs]# ls -latr
合計 1
drwxr-xr-x 3 root root 0 12月 21 11:44 ..
drwxrwxrwt 2 root root 2 12月 22 12:37 .
さっそく、persistentVolumeClaim(PVC)を作ってNFSシェア内にどのようにpersistentVolume(PV)が要求されるのかを見ていきます。今回は時間の都合上、複雑なことをせずに、ちょっと雑ではありますが、persistentVolume(PV)を利用するサンプルのnginxのDeploymentとpersistentVolumeClaim(PVC)でのストレージの要求だけでみていきます。
初期時点でのstorageclass(SC)、persistentVolumeClaim(PVC)、persistentVolume(PV)、Podの状態をkubectl getしましたが、まだ準備のところで作成したstorageclass(SC)のみが見えている状態です。
[root@mon-vm AFS]# kubectl get sc,pvc,pv,po
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storageclass.storage.k8s.io/acs-afs csi.nutanix.com Delete Immediate false 24m
[root@mon-vm AFS]#
最初にnginxのDeploymentをApplyします。persistentVolume(PV)を要求するnginxのマニフェストは以下のとおり。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-with-pv
labels:
run: nginx
spec:
replicas: 2
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nfs-share
volumes:
- name: nfs-share
persistentVolumeClaim:
claimName: afs-claim
そうするとpersistentVolume(PV)がまだ作成されていないためPodの作成がPendingになります。
[root@mon-vm AFS]# kubectl get sc,pvc,pv,po
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storageclass.storage.k8s.io/acs-afs csi.nutanix.com Delete Immediate false 26m
NAME READY STATUS RESTARTS AGE
pod/nginx-with-pv-b6cbfc5d7-6fdn8 0/1 Pending 0 8s
pod/nginx-with-pv-b6cbfc5d7-9lwl5 0/1 Pending 0 8s
[root@mon-vm AFS]#
このDeploymentで指定されたPodの作成するために必要とされるpersistentVolume(PV)のためのpersistentVolumeClaim(PVC)を作成します。persistentVolume(PV)を要求するpersistentVolumeClaim(PVC)は以下のとおり。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: afs-claim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 30Gi
storageClassName: acs-afs
PersistentVolumeClaim(PVC)によってPersistentVolume(PV)が作成され、Podの作成時に要求していたPersistentVolume(PV)要求が満たされる状態になっため、以下のようにPendingだったPodの作成が動き始めます。
[root@mon-vm AFS]# kubectl get sc,pvc,pv,po
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storageclass.storage.k8s.io/acs-afs csi.nutanix.com Delete Immediate false 28m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/afs-claim Bound pvc-992c60ac-accf-49bb-8f58-175822243302 30Gi RWX acs-afs 54s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-992c60ac-accf-49bb-8f58-175822243302 30Gi RWX Delete Bound default/afs-claim acs-afs 23s
NAME READY STATUS RESTARTS AGE
pod/nginx-with-pv-b6cbfc5d7-6fdn8 0/1 ContainerCreating 0 2m31s
pod/nginx-with-pv-b6cbfc5d7-9lwl5 1/1 Running 0 2m31s
[root@mon-vm AFS]#
上記のとおり、作成されたPersistentVolume(PV)は、persistentvolume/pvc-992c60ac-accf-49bb-8f58-175822243302
となります。では、実際のNFS上での見え方はどうでしょうか。さっそく観察してみます。
[root@mon-vm nfs]# pwd
/mnt/mon-vm/nfs
[root@mon-vm nfs]#
[root@mon-vm nfs]# ls -ltar
合計 1
drwxr-xr-x 3 root root 0 12月 21 11:44 ..
drwxr-xr-x 2 4294967294 4294967294 2 12月 22 17:41 pvc-992c60ac-accf-49bb-8f58-175822243302
drwxrwxrwt 3 root root 3 12月 22 17:41 .
[root@mon-vm nfs]#
NFS上に、pvc-992c60ac-accf-49bb-8f58-175822243302
と言うディレクトリができています。
Deploymentに記載しているとおり、nxingコンテナの/usr/share/nginx/htmlにfs1.ce.local:/nfs/pvc-992c60ac-accf-49bb-8f58-175822243302
をNFSマウントする形になっています。
※PersistentVolumeClaim(PVC)では30GiB要求しているが、10GiBしかないのは、Nutanix FilesのNFSシェアが10GiBの容量で作成しているため最大10GiBまでしかとれていない
実際にコンテナの中に入ってdf -h
で確認してみます。
[root@mon-vm AFS]# kubectl exec nginx-with-pv-b6cbfc5d7-
nginx-with-pv-b6cbfc5d7-6fdn8 nginx-with-pv-b6cbfc5d7-9lwl5
[root@mon-vm AFS]# kubectl exec nginx-with-pv-b6cbfc5d7-6fdn8 -it /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-with-pv-b6cbfc5d7-6fdn8:/#
root@nginx-with-pv-b6cbfc5d7-6fdn8:/#
root@nginx-with-pv-b6cbfc5d7-6fdn8:/#
root@nginx-with-pv-b6cbfc5d7-6fdn8:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 14G 4.3G 9.2G 32% /
tmpfs 64M 0 64M 0% /dev
tmpfs 5.9G 0 5.9G 0% /sys/fs/cgroup
/dev/mapper/centos_k8s--nfs-root 14G 4.3G 9.2G 32% /etc/hosts
shm 64M 0 64M 0% /dev/shm
fs1.ce.local:/nfs/pvc-992c60ac-accf-49bb-8f58-175822243302 10G 0 10G 0% /usr/share/nginx/html
tmpfs 5.9G 12K 5.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 5.9G 0 5.9G 0% /proc/acpi
tmpfs 5.9G 0 5.9G 0% /proc/scsi
tmpfs 5.9G 0 5.9G 0% /sys/firmware
root@nginx-with-pv-b6cbfc5d7-6fdn8:/#
root@nginx-with-pv-b6cbfc5d7-6fdn8:/# cd /usr/share/nginx/html/
root@nginx-with-pv-b6cbfc5d7-6fdn8:/usr/share/nginx/html# ls
root@nginx-with-pv-b6cbfc5d7-6fdn8:/usr/share/nginx/html#
df -h
で確認したあと、マウントされている/usr/share/nginx/html/
に移動してls
を叩きましたが、こちらのディレクトリには何もファイルがありません。
試しに、観察用のVMからmountして見えているNFS上のPVにサンプルのindex.html
を配置してみます。観察用のVMから見えているPersistentVolume(PV)ですが、こちらのファイルを配置すると、nginxコンテナでマウントされているPersistentVolume(PV)=/usr/share/nginx/html/
にファイルが見えるハズです。
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]# vi index.html
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]#
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]# cat index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>NFS PVC 確認用ページ</title>
</head>
<body>
<h1>KubernetesでNFSシェアを利用するためのテストファイル</h1>
<p>2つのnginxのPodから参照可能なNFSシェアをNutanix FilesのNFSを作成して、Kubeadmで作成したKubernetesクラスターからNutanix CSI PLUGINを通じて利用しています。</p>
</body>
</html>
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]#
観察用のVM上で作成されたindex.html
ファイルが見えるか、コンテナ内からls
で確認します。
root@nginx-with-pv-b6cbfc5d7-6fdn8:/usr/share/nginx/html# ls
index.html
root@nginx-with-pv-b6cbfc5d7-6fdn8:/usr/share/nginx/html#
無事にファイルが見えました。当然ですが、NFSはもともとReadWriteManyで利用可能です。つまり、1つの領域を複数から同時にマウントして参照・利用することが可能です。そのため、観察用のVMでマウントしているNFSに見えている、Kubernetes上のPodで要求したPersistentVolume(PV)は、コンテナからもVMからも同時に同じモノが見える状態になっています。
これでnginxコンテナ内のドキュメントルートにindex.html
が配置されたので、nginxのPodをexposeして外部から参照できるようにします。
[root@mon-vm AFS]#
[root@mon-vm AFS]# kubectl expose deployment nginx-with-pv --type="NodePort"
service/nginx-with-pv exposed
[root@mon-vm AFS]#
[root@mon-vm AFS]# kubectl get svc nginx-with-pv -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-with-pv NodePort 10.111.111.156 <none> 80:31009/TCP 17s run=nginx
ブラウザを開いて、このindex.html
がnginxのWebサーバーからきちんと見えるか確認してみます。
無事に見えました。では、今度は、このindex.html
ファイルを観察用VMから消してみます。
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]# pwd
/mnt/mon-vm/nfs/pvc-992c60ac-accf-49bb-8f58-175822243302
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]#
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]# ls
index.html
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]#
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]# rm index.html
rm: 通常ファイル `index.html' を削除しますか? y
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]#
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]# ls
[root@mon-vm pvc-992c60ac-accf-49bb-8f58-175822243302]#
ブラウザをリロードすると、当然、index.html
が消えているため、このようになります。
最後にpersistentVolumeClaim(PVC)、persistentVolume(PV)、storageclass(SC)、Pod/Deployment/Serviceを消して、この環境のお掃除をしておきます。
[root@mon-vm AFS]# kubectl delete deployments.apps nginx-with-pv
deployment.apps "nginx-with-pv" deleted
[root@mon-vm AFS]#
[root@mon-vm AFS]# kubectl delete service nginx-with-pv
service "nginx-with-pv" deleted
[root@mon-vm AFS]#
[root@mon-vm AFS]# kubectl delete pvc afs-claim
persistentvolumeclaim "afs-claim" deleted
[root@mon-vm AFS]#
[root@mon-vm AFS]# kubectl delete pv pvc-992c60ac-accf-49bb-8f58-175822243302
persistentvolume "pvc-992c60ac-accf-49bb-8f58-175822243302" deleted
[root@mon-vm AFS]#
[root@mon-vm AFS]# kubectl delete sc acs-afs
storageclass.storage.k8s.io "acs-afs" deleted
[root@mon-vm AFS]# kubectl get sc,pvc,pv,po,svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h54m
[root@mon-vm AFS]# kubectl get sc,pvc,pv,po
No resources found
[root@mon-vm AFS]#
まとめ
Nutanix CSI Pluginは、既にNutanixがある場合や、これからNutanixを導入する場合でも、Kubernetes環境に対して簡単にストレージを提供することが可能です。
ちょっとコンテナとコンテナ、コンテナとVM、コンテナと物理マシンでのファイル共有等がしたいと言った際には、NFSの場合、手軽にファイル共有ができるため、特に個人利用や開発等では重宝するかもしれません(この手の行為は商用環境ではあまりお勧めできませんが…)。
駆け足になりましたが、ショートバージョンでNutanix FilesのNFSをKubernetesから利用した場合の様子を紹介させていただきました。
NutanixのCSI Volume Pluginは、Kubernetesからステートフルなアプリケーションのためのブロックストレージ、そしてファイルレベルストレージの両方を提供できるだけでなく、今回、ご紹介できませんでしたが、ストレージの拡張、LVMボリュームのサポート、ボリュームのクローン、スナップショットとリストア、NFSの動的にプロビジョニング、IPホワイトリストやiSCSI認証など多数の機能があります。
今回は時間の都合で雑にまとめましたが、今後これらの詳細などについても投稿したいと思います。