この投稿は、Nutanix Advent Calendar 2025 の 10日目です。今日は、Nutanix Data Services for Kubernetes(NDK)2.0 で、NKP クラスタ上にあるアプリのスナップショット取得(バックアップ)→ リストアを実施してみます。
今回の内容です。
- 今回の環境
- 1. NDK のインストール
- 2. デモ アプリ(Wordpress)の起動
- 3. NDK の設定(StorageCluster の作成)
- 4. NDK Application の設定(保護対象の指定)
- 5. ApplicationSnapshot の作成
- 6. リストアの実施
今回の環境
NKP v2.16.1 のワークロード クラスタを用意してあります。NKP の環境構築についてはこちらをどうぞ。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION nkpndk-md-0-zv4pm-jkcdc-mz4mg Ready <none> 69m v1.33.5 nkpndk-p82sm-twt5k Ready control-plane 70m v1.33.5
作業用マシンに、helm をインストールしてあります。
$ helm version
version.BuildInfo{Version:"v3.19.0", GitCommit:"3d8990f0836691f0229297773f3524598f46bda6", GitTreeState:"clean", GoVersion:"go1.24.7"}
NKP v2.16.1 の NKP クラスタには、デフォルトで Nutanix CSI Direver 3.3.8 がインストールされています。
$ kubectl get csidriver csi.nutanix.com -o json | jq -r .metadata.labels
{
"app.kubernetes.io/instance": "nutanix-csi",
"app.kubernetes.io/managed-by": "Helm",
"app.kubernetes.io/management-plane": "PrismCentral",
"app.kubernetes.io/name": "nutanix-csi-storage",
"app.kubernetes.io/version": "3.3.8",
"helm.sh/chart": "nutanix-csi-storage-3.3.8"
}
1. NDK のインストール
今回は、NDK 2.0 をインストールします。
1-1. Helm Repo の追加
NDK のチャートが公開されている Helm Repo を追加します。
$ helm repo add ntnx-charts https://nutanix.github.io/helm-releases/
追加されました。
$ helm repo list NAME URL ntnx-charts https://nutanix.github.io/helm-releases/
NDK 2.0 の Helm Chart が公開されています。
$ helm search repo ntnx-charts/ndk NAME CHART VERSION APP VERSION DESCRIPTION ntnx-charts/ndk 2.0.0 2.0.0 Helm chart for Nutanix Data Services for Kubern...
1-2. Nutanix DockerHub トークンの入手
Nutainx Support & Insight Portl の、NDK のダウンロードページで、Nutanix DockerHub の nutanixndk ユーザーのトークンを入手します。

1-3. NDK のインストール
下記のコマンドで、NDK をインストールします。
helm install ndk ntnx-charts/ndk \ --version 2.0.0 \ -n ntnx-system \ --set config.secret.name=nutanix-csi-credentials \ --set imageCredentials.credentials.username=nutanixndk \ --set imageCredentials.credentials.password='トークン' \ --set tls.server.enable=false
実際に実行すると、下記のように表示されます。
$ helm install ndk ntnx-charts/ndk \ --version $NDK_VERSION \ -n ntnx-system \ --set config.secret.name=nutanix-csi-credentials \ --set imageCredentials.credentials.username=$DOCKER_USERNAME \ --set imageCredentials.credentials.password=$DOCKER_PASSWORD \ --set tls.server.enable=false NAME: ndk LAST DEPLOYED: Wed Dec 10 11:47:25 2025 NAMESPACE: ntnx-system STATUS: deployed REVISION: 1 TEST SUITE: None
少し待つと、NDK の Pod が Running になります。
$ kubectl get pods -n ntnx-system -l app.kubernetes.io/name=ndk NAME READY STATUS RESTARTS AGE ndk-controller-manager-754bcbf7d4-2jlhg 4/4 Running 0 2m10s
NDK のインストールにより、Kubernetes クラスタに下記のような CRD が追加されます。
$ kubectl get crd | grep nutanix applications.dataservices.nutanix.com 2025-12-10T11:47:24Z applicationsnapshotcontents.dataservices.nutanix.com 2025-12-10T11:47:24Z applicationsnapshotreplications.dataservices.nutanix.com 2025-12-10T11:47:24Z applicationsnapshotrestores.dataservices.nutanix.com 2025-12-10T11:47:24Z applicationsnapshots.dataservices.nutanix.com 2025-12-10T11:47:25Z appplannedfailovers.dataservices.nutanix.com 2025-12-10T11:47:25Z appprotectionplans.dataservices.nutanix.com 2025-12-10T11:47:25Z appunplannedfailovers.dataservices.nutanix.com 2025-12-10T11:47:25Z fileserverreplicationrelationships.dataservices.nutanix.com 2025-12-10T11:47:25Z filesreplicationpolicies.dataservices.nutanix.com 2025-12-10T11:47:25Z haapplicationcontents.dataservices.nutanix.com 2025-12-10T11:47:25Z haapplications.dataservices.nutanix.com 2025-12-10T11:47:25Z jobschedulers.scheduler.nutanix.com 2025-12-10T11:47:25Z protectionplans.dataservices.nutanix.com 2025-12-10T11:47:25Z remotes.dataservices.nutanix.com 2025-12-10T11:47:25Z replicationtargets.dataservices.nutanix.com 2025-12-10T11:47:25Z storageclusters.dataservices.nutanix.com 2025-12-10T11:47:25Z
kubectl api-resources では、下記のように見えます。
$ kubectl api-resources --api-group=dataservices.nutanix.com NAME SHORTNAMES APIVERSION NAMESPACED KIND applications app dataservices.nutanix.com/v1alpha1 true Application applicationsnapshotcontents asc,ascs dataservices.nutanix.com/v1alpha1 false ApplicationSnapshotContent applicationsnapshotreplications appsnaprep dataservices.nutanix.com/v1alpha1 true ApplicationSnapshotReplication applicationsnapshotrestores asr dataservices.nutanix.com/v1alpha1 true ApplicationSnapshotRestore applicationsnapshots as dataservices.nutanix.com/v1alpha1 true ApplicationSnapshot appplannedfailovers pfo dataservices.nutanix.com/v1alpha1 true AppPlannedFailover appprotectionplans appplan dataservices.nutanix.com/v1alpha1 true AppProtectionPlan appunplannedfailovers upfo dataservices.nutanix.com/v1alpha1 true AppUnplannedFailover fileserverreplicationrelationships fsrr dataservices.nutanix.com/v1alpha1 false FileServerReplicationRelationships filesreplicationpolicies frp,frps dataservices.nutanix.com/v1alpha1 true FilesReplicationPolicy haapplicationcontents haac dataservices.nutanix.com/v1alpha1 false HAApplicationContent haapplications haa dataservices.nutanix.com/v1alpha1 true HAApplication protectionplans pplan dataservices.nutanix.com/v1alpha1 true ProtectionPlan remotes remote,remotes dataservices.nutanix.com/v1alpha1 false Remote replicationtargets dataservices.nutanix.com/v1alpha1 true ReplicationTarget storageclusters dataservices.nutanix.com/v1alpha1 false StorageCluster $ kubectl api-resources --api-group=scheduler.nutanix.com NAME SHORTNAMES APIVERSION NAMESPACED KIND jobschedulers scheduler.nutanix.com/v1alpha1 true JobScheduler
2. デモ アプリ(Wordpress)の起動
バックアップ・リストア対象のアプリケーション用意しておきます。今回は、下記で紹介されている Wordpress を起動します。
今回は demo-01 Namespace でアプリを起動します。
$ kubectl create ns demo-01 namespace/demo-01 created
Wordpress の DB(MySQL)に設定するパスワードを格納する、Secret を作成します。
$ kubectl create secret generic mysql-pass --from-literal password='nutanix/4u' -n demo-01 secret/mysql-pass created
アプリケーションを起動します。今回はオンラインの YAML を直接指定します。
$ kubectl apply -n demo-01 -f https://k8s.io/examples/application/wordpress/mysql-deployment.yaml service/wordpress-mysql created persistentvolumeclaim/mysql-pv-claim created deployment.apps/wordpress-mysql created $ kubectl apply -n demo-01 -f https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml service/wordpress created persistentvolumeclaim/wp-pv-claim created deployment.apps/wordpress created
これで、Wordpress を構成する Kubernetes リソース一式が起動されました。外部接続用の IP アドレスは、10.1.7.93 になっています。
$ kubectl get all -n demo-01 NAME READY STATUS RESTARTS AGE pod/wordpress-c8b9849f8-tf6wt 1/1 Running 0 4m23s pod/wordpress-mysql-766bf4cb5c-t4qwp 1/1 Running 0 5m7s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/wordpress LoadBalancer 10.104.163.199 10.1.7.93 80:32726/TCP 4m23s service/wordpress-mysql ClusterIP None <none> 3306/TCP 5m7s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/wordpress 1/1 1 1 4m23s deployment.apps/wordpress-mysql 1/1 1 1 5m7s NAME DESIRED CURRENT READY AGE replicaset.apps/wordpress-c8b9849f8 1 1 1 4m23s replicaset.apps/wordpress-mysql-766bf4cb5c 1 1 1 5m7s
アプリのデータを含む、PVC も作成されています。
$ kubectl get pvc -n demo-01 NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE mysql-pv-claim Bound pvc-27441a18-846c-4b85-912b-4640d067ad19 20Gi RWO nutanix-volume10m wp-pv-claim Bound pvc-a34dd7f0-40d0-4b8a-a436-6c8fa643500d 20Gi RWO nutanix-volume 10m
Web ブラウザで 10.1.7.93 を開くと、Wordpress が利用可能になっています。

テスト用に記事を投稿しておきます・・・

3. NDK の設定(StorageCluster の作成)
NDK が Nutainx クラスタと連携するための、「StorageCluster」リソースを作成します。
パラメータとして必要になる、Prism Centarl と Prism Element の UUID を確認します。どちらも Web UI から確認できますが、今回は NKP クラスタ ノードのラベルから確認します。
$ kubectl get nodes nkpndk-p82sm-twt5k -o json | jq -r .metadata.labels | grep prism "csi.nutanix.com/prism-central-uuid": "16222475-b017-4c43-XXXX-XXXXXXXXXXXX", "csi.nutanix.com/prism-element-uuid": "00063c9a-1efe-0a33-XXXX-XXXXXXXXXXXX",
StorageCluster リソースの YAML を作成します。
storage-cluster.yml
- managementServerUuid:Prism Element の UUID を指定
- storageServerUuid:Prism Element の UUID を指定
リソースを作成します。
$ kubectl apply -f storage-cluster.yml storagecluster.dataservices.nutanix.com/st-cluster created
StorageCluster リソースが作成されました。
$ kubectl get storageclusters.dataservices.nutanix.com NAME AVAILABLE st-cluster true
4. NDK Application の設定(保護対象の指定)
NDK では、捜査の対象を Application リソースとして定義します。今回は demo-01 Namespace 全体を app-01 Application に含めます。
下記のような YAML ファイルを用意します。
ndk-application.yml
リソースを作成します。
$ kubectl apply -f yaml/ndk-application.yml -n demo-01 application.dataservices.nutanix.com/app-01 created $ kubectl get applications -n demo-01 NAME AGE ACTIVE LAST-STATUS-UPDATE app-01 12s True 11s
5. ApplicationSnapshot の作成
app-01 Application を対象として、NDK のスナップショット(ApplicationSnapshot)を作成します。
下記のような YAML を用意します。
ndk-snapshot.yml
ApplicationSnapshot を作成します。
$ kubectl apply -f yaml/ndk-snapshot.yml -n demo-01 applicationsnapshot.dataservices.nutanix.com/app-01-snapshot-01 created
作成直後の状態です。
$ kubectl get applicationsnapshot -n demo-01 NAME AGE READY-TO-USE BOUND-SNAPSHOTCONTENT SNAPSHOT-AGE CONSISTENCY-TYPE app-01-snapshot-01 25s false asc-d33f89b1-1f2b-4154-9050-17a0ed304cd9
少し待つと、スナップショットの処理が完了して READY-TO-USE が true になります。
$ kubectl get applicationsnapshot -n demo-01 NAME AGE READY-TO-USE BOUND-SNAPSHOTCONTENT SNAPSHOT-AGE CONSISTENCY-TYPE app-01-snapshot-01 32s true asc-d33f89b1-1f2b-4154-9050-17a0ed304cd9 1s CrashConsistent
MySQL 用の PVC/PV に対応する Volume Group を確認すると、NDK により Recovery Point が作成されています。

6. リストアの実施
あえて Wordpress 関連のリソースを削除して、NDK のスナップショットをリストアしてみます。
6-1. 既存リソースの削除
まず、既存の Wordpress 関連リソースを削除してしまいます。
$ kubectl delete deployment -n demo-01 --all deployment.apps "wordpress" deleted deployment.apps "wordpress-mysql" deleted $ kubectl delete pvc -n demo-01 --all persistentvolumeclaim "mysql-pv-claim" deleted persistentvolumeclaim "wp-pv-claim" deleted $ kubectl delete svc -n demo-01 --all service "wordpress" deleted service "wordpress-mysql" deleted
リソース一式が削除されました。
$ kubectl get all -n demo-01 No resources found in demo-01 namespace. $ kubectl get pvc -n demo-01 No resources found in demo-01 namespace. $ kubectl get pv No resources found
ただし、ApplicationSnapshot は残してあります。
$ kubectl get applicationsnapshot -n demo-01 NAME AGE READY-TO-USE BOUND-SNAPSHOTCONTENT SNAPSHOT-AGE CONSISTENCY-TYPE app-01-snapshot-01 14m true asc-d33f89b1-1f2b-4154-9050-17a0ed304cd9 14m CrashConsistent
6-2. リストアの実行
リストアを実行する、ApplicationSnapshotRestore リソースの YAML を作成します。
ndk-restore.yml
リストアを実行します。
$ kubectl apply -f yaml/restore.yml -n demo-01 applicationsnapshotrestore.dataservices.nutanix.com/app-01-restore-01 created
少し待つと、COMPLETED が true になります。
$ kubectl get applicationsnapshotrestore -n demo-01 NAME SNAPSHOT-NAME COMPLETED app-01-restore-01 app-01-snapshot-01 true
ちなみに、リストアの状態は下記のように確認できます。
$ kubectl describe applicationsnapshotrestore -n demo-01 app-01-restore-01 Name: app-01-restore-01 Namespace: demo-01 Labels:Annotations: API Version: dataservices.nutanix.com/v1alpha1 Kind: ApplicationSnapshotRestore Metadata: Creation Timestamp: 2025-12-10T12:55:15Z Finalizers: dataservices.nutanix.com/application-restore Generation: 1 Resource Version: 89152 UID: fcee0a9e-1d1a-4398-81c2-11658f285c4d Spec: Application Snapshot Name: app-01-snapshot-01 Status: Completed: true Conditions: Last Transition Time: 2025-12-10T12:55:15Z Message: Observed Generation: 1 Reason: RequestCompleted Status: False Type: Progressing Last Transition Time: 2025-12-10T12:55:15Z Message: All prechecks passed and finalizers on dependent resources set. Skipped restoring resources since they already exist: ["/v1, Kind=Secret, demo-01/mysql-pass","/v1, Kind=ConfigMap, demo-01/kube-root-ca.crt","/v1, Kind=ServiceAccount, demo-01/default"] Observed Generation: 1 Reason: PrechecksPassed Status: True Type: PrechecksPassed Last Transition Time: 2025-12-10T12:55:15Z Message: Restore requests for all eligible volumes submitted Observed Generation: 1 Reason: VolumeRestoreRequestsSubmitted Status: True Type: VolumeRestoreRequestsSubmitted Last Transition Time: 2025-12-10T12:55:16Z Message: All eligible application configs restored Observed Generation: 1 Reason: ApplicationConfigRestored Status: True Type: ApplicationConfigRestored Last Transition Time: 2025-12-10T12:55:31Z Message: All eligible volumes restored Observed Generation: 1 Reason: VolumesRestored Status: True Type: VolumesRestored Last Transition Time: 2025-12-10T12:55:31Z Message: Application restore successfully finalised Observed Generation: 1 Reason: ApplicationRestoreFinalised Status: True Type: ApplicationRestoreFinalised Finish Time: 2025-12-10 12:55:31 Start Time: 2025-12-10 12:55:15 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal WaitingForVolumesToBind 59s (x3 over 59s) NDK Waiting for PVCs to get Bound. Unbound PVCs: [mysql-pv-claim wp-pv-claim] Normal WaitingForVolumesToBind 59s NDK Waiting for PVCs to get Bound. Unbound PVCs: [wp-pv-claim mysql-pv-claim] Warning UpdateStatusFailed 44s (x2 over 60s) NDK Operation cannot be fulfilled on applicationsnapshotrestores.dataservices.nutanix.com "app-01-restore-01": the object has been modified; please apply your changes to the latest version and try again
これで、リソース削除前の状態にリストアできました。EXTERNAL-IP は自動採番なのですが、空いていた以前とおなじ IP アドレスが割り当てられています。
$ kubectl get all -n demo-01 NAME READY STATUS RESTARTS AGE pod/wordpress-c8b9849f8-72h87 1/1 Running 0 106s pod/wordpress-mysql-766bf4cb5c-rpg45 1/1 Running 0 106s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/wordpress LoadBalancer 10.101.113.100 10.1.7.93 80:32512/TCP 106s service/wordpress-mysql ClusterIP None <none> 3306/TCP 106s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/wordpress 1/1 1 1 106s deployment.apps/wordpress-mysql 1/1 1 1 106s NAME DESIRED CURRENT READY AGE replicaset.apps/wordpress-c8b9849f8 1 1 1 106s replicaset.apps/wordpress-mysql-766bf4cb5c 1 1 1 106s
Wordpress でも、さきほど作成した投稿がリストアできています。

以上。
