はじめに
GAFA社長でっす。
この記事はNutanix Advent Calender 2024のために書き始めたのですが、ちょっとひとつの記事にするにはボリュームが大きすぎるので、分割して公開します。ていうかクリスマスまでに最後まで書ききれるのか?
2024年、Nutanixが俄然張り切り出した領域のひとつが、AIワークロードのためのプラットフォームとしてのNutanixという切り口です。分散ストレージとしてのAOS、Kubernetesクラスタの管理、GPUリソースの管理といったNutanixがそもそも得意としているテクノロジーをAIワークロードを動かすために活用しましょう、という話です。
話はわかるけど、実際何がどう動くのよ?というのを簡単にお見せするために、私が今年よく披露したデモが、Nutanix Kubernetes Platform(NKP)の上でDifyを動かし、バックエンドではNUSやNDBを使用して、 「ジョジョのことならなんでも知ってるジョジョマニアくん」 という簡単なRAGアプリケーションをその場で作って見せる、というものでした。
Nutanixでやると構築自体はちょちょいとできるのですが、「どうやって構築するの?」という声も多いので、ざっくり手順を公開します。
この記事は第一弾、NKP編です。
作業環境の準備
NKPは様々なインフラ上で動作するため、デプロイ方法も様々ですが、ここでは以下を前提とします。
- Nutanixクラスタ(NCI)の上に、NKPの Nutanix Infrastructure Providerを使ってデプロイする
- インターネットに接続されている(dockerhubからイメージをpullできる)環境である
NKPのインストーラーは nkp というシングルバイナリで提供されます。実際にはこのコマンドで kind (Kubernetes in Docker)のbootstrapクラスタがローカルに展開され、そこからCluster APIを利用してデプロイ先のインフラにKubernetesクラスタが展開されます。
nkpコマンドは、Linux版とMacOS(Darwin)版があります。手元のPCで動かしてもよいのですが、せっかくNutanixを使うので、Nutanixクラスタ上に作業用の仮想マシンを立てましょう。
DockerあるいはPodmanと、kubectl/helmが使えればよいので、Linuxのディストリビューションはまあなんでもよいのですが、私は使い慣れているUbuntu24.04で作業します。
Docker,kubectl,helmをインストールし、nkpのバイナリをパスの通ったところに配置しておきます。作業を行うユーザーでdockerコマンドが実行できるようにしておきましょう。
デプロイ先のインフラの準備
詳しくはドキュメントを読むべきですが、Nutanix Infrastructure Providerを使用してNutanixクラスタ上にNKPをデプロイする場合は、
- 使用するSubnet
- そのSubnet内で、Kubernetesのノード数ぶんのIPアドレスの空きがあるIPAMプールがあること
- 同じSubnet内で、ひとつのKubernetesクラスタにつき下記がIPAMプール外で 割り当て可能なこと
- Kubernetes API用のIPアドレス x1
- MetalLBロードバランサー用のIPアドレス x1以上 (ひとつはNKPの管理サービス用にTraefikが使う)
 
を確認しておきましょう。
あとプロダクション環境の場合は、TLSのためにDNSとか証明書とかも当然準備する必要がありますが、今回は社内検証環境なので割愛。
NKPのノードイメージを作る
Kubernetesの各ノードは仮想マシンとして展開されますので、そのための仮想マシンイメージを用意しておく必要があります。
NKPのダウンロードサイトにはRocky9.5ベースのイメージが用意されていますが、NKPのKonvoy Image Builderという機能を使ってカスタムイメージを作成することもできます。
今回はNutanix Enterprise AI (NAI)を動作させるため、Ubuntu22.04のイメージを作成しておきます。
$ export NUTANIX_USER=nkp   # Prism Centralのadmin権限を持つユーザー名
$ export NUTANIX_PASSWORD=nx2Tech685!   # 上記ユーザーのパスワード
$ ./nkp create image nutanix ubuntu-22.04 --cluster PHX-POC174 --endpoint 10.38.174.39 --subnet Secondary --insecure
これでPackerのビルドVMが立ち上がり、しばらく待つとPrism Central上に仮想マシンイメージが登録されます。
Prism Centralのユーザーは、デフォルトの admin ユーザーを使用するとあとあとめんどくさいことになるので、必ずNKP専用のユーザー(Admin権限が必要)を作成しておくようにしましょう。
NKPをデプロイする
管理クラスタのデプロイ
NKPはシングルクラスタでも動作しますが、Cluster APIやGit Operatorを駆使してマルチKubernetesクラスタを管理するための便利機能がいろいろついてきます。
マルチクラスタ構成において、クラスタを管理するためのクラスタは Management Cluster 、管理対象となるクラスタは Managed Cluster と呼ばれていますが、紛らわしいのでこの記事では「管理クラスタ」「ワークロードクラスタ」と呼びます。ちなみにシングルクラスタ構成の場合は Self Managed Cluster となります。
ワークロードクラスタの構成は、管理クラスタ上のCluster APIリソースとしてKubernetesネイティブに管理されます。また、NKPにはワークロードクラスタをグループ化する workspaceという概念があり、アプリケーションのライフサイクルをクラスタ単位だけではなく、workspace単位で管理することもできます。
今回は最終的に複数のKubernetesクラスタを使用するので、管理クラスタではユーザーワークロードは動かさない前提でシンプルに作成します。
以下のコマンドでTUIが起動しますので、あとは必要な情報を入れていくだけです。
$ nkp create cluster nutanix
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│  Prism Central  >  Cluster Configuration  >  Additional Configuration (optional)  >  Create Cluster│
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│Prism Central Endpoint*: https://10.38.174.39:9440/                                                 │
│Username*: nkp                                                                                      │
│Password*: ***********                                                                              │
│Insecure: ( )No (•)Yes                                                                              │
│Additional Trust Bundle: A PEM file as base64 encoded string                                        │
│Project:                                                                                            │
│                                                                                                    │
│> (No Project)                                                                                      │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│Prism Element Cluster*:                                                                             │
│                                                                                                    │
│> PHX-POC174                                                                                        │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│Subnet*:                                                                                            │
│                                                                                                    │
│  Primary                                                                                           │
│> Secondary                                                                                         │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│shift+tab Move Up       enter/tab Select Item      ctrl+p Previous Page                             │
│tab       Move Down     /         Filter Items     ctrl+n Next Page                                 │
│left      Move Left     esc       Remove Filter    ctrl+c Quit                                      │
│right     Move Right                                                                                │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
最初のページでPrism Centralのユーザー名とパスワードを入れると、Project Prism Element Cluster Subnet は選択肢が自動的に表示されるので選ぶだけです。
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│Cluster Name*: nkpmgmt                                                                              │
│Control Plane Endpoint*: 10.38.174.135:6443                                                         │
│VM Image*:                                                                                          │
│                                                                                                    │
│> nkp-rocky-9.5-1.30.5-20241207055446                                                               │
│nkp-ubuntu-22.04-1.30.5-20241207070359                                                              │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│                                                                                                    │
│Kubernetes Network                                                                                  │
│Service Load Balancer IP Range*: 10.38.174.136-10.38.174.138                                        │
│Pod Network: 192.168.0.0/16                                                                         │
│Service Network: 10.96.0.0/12                                                                       │
│                                                                                                    │
│Storage                                                                                             │
│Reclaim Policy: (•)Delete ( )Retain                                                                 │
│File System: (•)ext4 ( )xfs                                                                         │
│Hypervisor Attached Volumes: (•)Yes ( )No                                                           │
│Storage Container*:                                                                                 │
│                                                                                                    │
│  default-container-171380                                                                          │
│> k8s                                                                                               │
│  objectsd076ab2dd490845c87ccf0b65cca62235                                                          │
│                                                                                                    │
│  •••                                                                                               │
│                                                                                                    │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
Control Plane Endpoint は、KubernetesのAPIエンドポイントです。選択したSubnetの中の、IPAMプール外のアドレスを指定してください。
Service Load Balancer IP Range は、MetalLBが使用するIPアドレスのレンジです。このレンジの最初のIPアドレスが、NKPのダッシュボード(Kommander Dashboard)用のTraefikのIngressで使用されます。
VM Image はあらかじめPrism Centralに登録されているNKP用のイメージが出てきます。ここで何も出てこない場合はイメージの登録が失敗している、あるいはイメージ名が間違っています。
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│Cluster Domain/ FQDN / Hostname for Ingress: FQDN                                                   │
│                                                                                                    │
│ACME Configuration                                                                                  │
│ACME Server: https://acme-v02.api.letsencrypt.org/directory                                         │
│Email address for ACME Server: example@domain.com                                                   │
│                                                                                                    │
│Ingress                                                                                             │
│Certificate file: local filepath to certificate PEM file                                            │
│Private key file: local filepath to private key PEM file                                            │
│CA chain file: local filepath to CA chain PEM file                                                  │
│                                                                                                    │
│Registry                                                                                            │
│Registry URL: https://registry-1.docker.io                                                          │
│Registry CA Certificate: local filepath to registry CA Certificate                                  │
│Registry Username: jyoshise                                                                         │
│Registry Password: ***************                                                                  │
│                                                                                                    │
│SSH                                                                                                 │
│SSH User: konvoy                                                                                    │
│SSH public key: /home/ubuntu/.ssh/id_rsa.pub                                                        │
│                                                                                                    │
│Proxy                                                                                               │
│HTTP Proxy:                                                                                         │
│HTTPS Proxy:                                                                                        │
│No Proxy: comma separated No Proxy list for all nodes in the cluster                                │
│                                                                                                    │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
このページは入力必須ではないのですが、Registry の項目は埋めた方がいいです。デフォルトでdockerhubからコンテナイメージを引っ張ってくるのですが、社内ネットワークから匿名でやろうとすると常にdockerhubのrate limitに引っかかる状態になっていると思うので、ImagePullBackOffしか出ねえってなります。
これを避けるには、ローカルにミラーレジストリを立てる(そのためのAir-Gapped Bundleというものも用意されています)という手もありますが、dockerhubのログイン情報を入れるだけでもだいたい回避できます。
最後に確認画面で、
│━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━│ 
│Create NKP Cluster?: ( )Create (•)Dry Run                                                           │ 
│                                                                                                    │ 
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ 
と出ます。ここで Create を選択するとbootstrapクラスタが作成され、Nutanix上に管理クラスタがデプロイされます。
このTUIではあまり細かい構成の指定ができない(ノードのサイズや数も選べない)のですが、 Dry Run を選択すると、実際のデプロイは行われず、ClusterリソースなどのManifest(YAML)が吐き出されるので、そのYAMLを編集してからbootstrapクラスタを起動し、kubectl applyするということも可能です。あるいは、nkp create clusterコマンドのオプションで各種指定をすることもできます。
ここでは管理クラスタはデフォルト構成でデプロイしますので、Createを選択します。
 ✓ Creating a bootstrap cluster 
 ✓ Initializing new CAPI components 
 ✓ Initializing new CAPI components 
 ✓ Creating ClusterClass resources 
 ✓ Creating ClusterClass resources
Generating cluster resources
cluster.cluster.x-k8s.io/nkpmgmt created
secret/nkpmgmt-pc-credentials created
secret/nkpmgmt-pc-credentials-for-csi created
secret/nkpmgmt-image-registry-credentials created
configmap/kommander-bootstrap-configuration created
secret/global-nutanix-credentials created
 ✓ Waiting for cluster infrastructure to be ready 
 ✓ Waiting for cluster control-planes to be ready 
 ✓ Waiting for machines to be ready
ここまで進むと、KubernetesクラスタのノードがNutanixクラスタ上に展開され始めているはずです。Prism Centralでタスクを眺めてそれをつまみに一杯やりましょう。
nkpコマンドでは以下のように確認できます。bootstrapクラスタのkubeconfigファイルが作成されているので、それを指定します。(つまり kubectl get cluster -Aなどでも確認できます。)
$ ./nkp describe cluster -c nkpmgmt --kubeconfig=nkpmgmt-bootstrap.conf
NAME                                                                           READY  SEVERITY  REASON                       SINCE  MESSAGE                                                      
Cluster/nkpmgmt                                                                False  Warning   ScalingUp                    36s    Scaling up control plane to 3 replicas (actual 2)            
├─ClusterInfrastructure - NutanixCluster/nkpmgmt-nnsbp                                                                                                                                           
├─ControlPlane - KubeadmControlPlane/nkpmgmt-2hvnj                             False  Warning   ScalingUp                    36s    Scaling up control plane to 3 replicas (actual 2)            
│ ├─Machine/nkpmgmt-2hvnj-2gpl7                                                True                                          2m55s                                                               
│ │ └─MachineInfrastructure - NutanixMachine/nkpmgmt-2hvnj-2gpl7                                                                                                                                 
│ └─Machine/nkpmgmt-2hvnj-kbh7x                                                True                                          12s                                                                 
│   └─MachineInfrastructure - NutanixMachine/nkpmgmt-2hvnj-kbh7x                                                                                                                                 
└─Workers                                                                                                                                                                                        
  └─MachineDeployment/nkpmgmt-md-0-6pzld                                       False  Warning   WaitingForAvailableMachines  10s    Minimum availability requires 4 replicas, current 1 available
    ├─Machine/nkpmgmt-md-0-6pzld-tfcmp-2jdxs                                   True                                          56s                                                                 
    │ └─MachineInfrastructure - NutanixMachine/nkpmgmt-md-0-6pzld-tfcmp-2jdxs                                                                                                                    
    ├─Machine/nkpmgmt-md-0-6pzld-tfcmp-j686t                                   False  Info      WaitingForInfrastructure     11s    1 of 2 completed                                             
    │ └─MachineInfrastructure - NutanixMachine/nkpmgmt-md-0-6pzld-tfcmp-j686t                                                                                                                    
    ├─Machine/nkpmgmt-md-0-6pzld-tfcmp-p59zl                                   False  Info      WaitingForInfrastructure     11s    1 of 2 completed                                             
    │ └─MachineInfrastructure - NutanixMachine/nkpmgmt-md-0-6pzld-tfcmp-p59zl                                                                                                                    
    └─Machine/nkpmgmt-md-0-6pzld-tfcmp-xvmgx                                   False  Info      WaitingForInfrastructure     11s    1 of 2 completed                                             
      └─MachineInfrastructure - NutanixMachine/nkpmgmt-md-0-6pzld-tfcmp-xvmgx                                                                                                                    
ここまでは、Cluster APIリソースはbootstrapクラスタの上にあるのですが、管理クラスタが立ち上がった後はそれらが管理クラスタ上に移動され、bootstrapクラスタは削除されます。つまり管理クラスタが自分自身もCluster APIで管理するということ。
 ✓ Initializing new CAPI components 
 ✓ Initializing new CAPI components 
 ✓ Creating ClusterClass resources 
 ✓ Moving cluster resources 
You can now view resources in the moved cluster by using the --kubeconfig flag with kubectl.
For example: kubectl --kubeconfig="/home/ubuntu/nkp/nkpmgmt.conf" get nodes
 ✓ Deleting bootstrap cluster 
Cluster default/nkpmgmt kubeconfig was written to to the filesystem.
You can now view resources in the new cluster by using the --kubeconfig flag with kubectl.
For example: kubectl --kubeconfig="/home/ubuntu/nkp/nkpmgmt.conf" get nodes
その後、Git OperatorやGatekeeperなど、NKPの管理系のサービスがデプロイされます。
最後にダッシュボードのアクセス情報を得るためのコマンドが表示されて終了です。
Cluster was created successfully! Get the dashboard details with:
nkp get dashboard --kubeconfig="/home/ubuntu/nkp/nkpmgmt.conf"
所要時間はネットワーク(コンテナイメージのPull)に依存しますが、だいたい10分ぐらいかな?
ワークロードクラスタのデプロイ
管理クラスタのデプロイ直後にダッシュボードにアクセスするとこういう状態です。
クラスタがひとつだけ。Kommander Hostというクラスタに Management というバッジがついています。このクラスタが管理クラスタということです。このダッシュボード自体も管理クラスタの上で動いています。
管理クラスタも普通のKubernetesクラスタなので、ユーザーワークロードをデプロイして動かすことももちろんできるのですが、今回は専任マネージャーとして働いてもらいます。
ここから先は nkp コマンドを使う必要はないので、このダッシュボードのGUIで操作していきます。
初期状態では、NKP Starterというライセンスが入っています。これはNCI Pro以上では無料で使えるライセンスです。

今回はNKP Ultimateを使用するので、Remove License でStarterのライセンスをいったん削除してからUltimateのライセンスキーを入れます。
Workspaceの作成
次にWorkspaceを作成します。Workspaceというのは、Kubernetesクラスタが所属する「組織」のようなものです。それぞれのWorkspaceに所属するクラスタ間で、展開するアプリケーションやRBACの同期などが行えます。また、KubeCostによりWorkspaceごとのコスト利用状況を可視化することもできます。
管理クラスタの中では、Workspaceはそれぞれに所属するクラスタのCluster APIリソースを格納するNamespaceとして存在します。

この画面右上の Create Workspace を押して名前を決めるだけです。ここでは aidemo というWorkspaceを作成しました。
Infrastructure Providerの登録
次にこのWorkspace(組織)が使用できるInfrastructure Providerを登録します。
左上のWorkspace Selectorで先ほど作った aidemo を選び、+ Add infrastructure を押します。
Nutanix(NCI)をInfrastructure Providerとして利用する場合は、Prism Centralの情報を入れます。

AWSを利用する場合は、適切な権限を設定したService Accountと紐づいたAccess KeyとSecret Keyを登録することにより、Cluster APIを使用してEKSクラスタをデプロイすることができます。AzureだとAKSクラスタ、vSphereやVCDの場合はノードの仮想マシンを展開してKubernetesクラスタとして構成します。
ワークロードクラスタのデプロイ
aidemoWorkspaceで右上の + Add Clusterを押します。

ここでCreate Clusterを選ぶと、先ほど登録したInfrastructure Providerを利用して、GUI上でパラメーターを入力してクラスタを作成します。
Upload YAML to Create Clusterは、あらかじめ作っておいたCluster APIリソースのYAMLを適用するやりかたです。つまり管理クラスタに対してkubectl applyをするのと同じです。
Attach Clusterは、既存のKubernetesクラスタのkubeconfigを与えることによって管理下に置くやりかたです。
ここではCreate Clusterを選択します。
入力が必要な情報は、管理クラスタをTUIからデプロイしたときとほぼ同じですが、こちらはNode Poolのサイズなどより細かく設定できるようになっています。
以下、見ての通りです。




Nutanix Infrastructure Providerの場合は、クラスタのデプロイはそれほど時間がかかりません。
今回は、同じaidemoというWorkspaceの中に、DifyやMilvusを動かすためのaidemoというクラスタと、Nutanix Enterprise AI(NAI)を動かすためのnaiというクラスタを作りました。

ちなみに管理クラスタのkubectlで見るとこのようになっています。
ubuntu@jyoshise-work:~/nkp$ kubectl -n aidemo-zj7fp-tt75j get cluster
NAME     CLUSTERCLASS   PHASE         AGE     VERSION
aidemo   nkp-nutanix    Provisioned   5d2h    v1.30.5
nai      nkp-nutanix    Provisioned   4d22h   v1.30.5
ubuntu@jyoshise-work:~/nkp$ kubectl -n aidemo-zj7fp-tt75j get machine
NAME                               CLUSTER   NODENAME                           PROVIDERID                                       PHASE         AGE     VERSION
aidemo-5cd6r-8sg99                 aidemo    aidemo-5cd6r-8sg99                 nutanix://b4ff3656-626f-4ac0-929a-bfa3258ba8ff   Running       5d2h    v1.30.5
aidemo-5cd6r-ghzlm                 aidemo    aidemo-5cd6r-ghzlm                 nutanix://a2a08142-d967-43be-9857-e9e42e291caa   Running       5d2h    v1.30.5
aidemo-5cd6r-nq92l                 aidemo    aidemo-5cd6r-nq92l                 nutanix://010ed0bf-6a6b-406b-8ec9-6b9e70f44aed   Running       5d2h    v1.30.5
aidemo-md-0-4svhx-qcjw8-4qjsr      aidemo    aidemo-md-0-4svhx-qcjw8-4qjsr      nutanix://e4e165bc-4fbc-4558-b1ff-1ac2b9dea921   Running       5d2h    v1.30.5
aidemo-md-0-4svhx-qcjw8-jv6rd      aidemo    aidemo-md-0-4svhx-qcjw8-jv6rd      nutanix://1a3e0742-8b72-4f97-b4de-1b7a59fb9011   Running       5d2h    v1.30.5
aidemo-md-0-4svhx-qcjw8-vspbv      aidemo    aidemo-md-0-4svhx-qcjw8-vspbv      nutanix://01b2c885-bb38-4efd-89ae-fd1083994cb9   Running       5d2h    v1.30.5
nai-6xvc7-5d499                    nai       nai-6xvc7-5d499                    nutanix://e2696507-0c69-4fba-b6fb-48b83390dcc9   Running       4d22h   v1.30.5
nai-6xvc7-btd2l                    nai       nai-6xvc7-btd2l                    nutanix://fe19bddf-0390-4088-b081-cdcd786cfa50   Running       4d22h   v1.30.5
nai-6xvc7-x8dwj                    nai       nai-6xvc7-x8dwj                    nutanix://cad9e81b-e441-43d9-b4d1-024475921c83   Running       4d22h   v1.30.5
nai-md-0-8l9bb-6mpqz-fqlkf         nai                                          nutanix://5959c692-0bf1-4b3b-9a04-c1c9d1165b8b   Provisioned   18s     v1.30.5
nai-md-0-8l9bb-fczz4-4ggqj         nai       nai-md-0-8l9bb-fczz4-4ggqj         nutanix://1e6ce21c-dee1-488e-bfc4-597c6bd270da   Running       4d22h   v1.30.5
nai-md-0-8l9bb-fczz4-cwhm5         nai       nai-md-0-8l9bb-fczz4-cwhm5         nutanix://98243c4c-fe21-44cc-8af1-20af8665cc34   Running       4d22h   v1.30.5
nai-md-0-8l9bb-fczz4-lt6qz         nai       nai-md-0-8l9bb-fczz4-lt6qz         nutanix://8d1c6b20-19bc-4724-9188-277dd5a03a7b   Running       4d22h   v1.30.5
nai-md-0-8l9bb-fczz4-wtjsk         nai       nai-md-0-8l9bb-fczz4-wtjsk         nutanix://c24eb904-ba4b-4f60-8686-a2d5c2733dd5   Running       4d22h   v1.30.5
nai-md-1-n8dqp-4df5f-4kbd7-g5mm9   nai       nai-md-1-n8dqp-4df5f-4kbd7-g5mm9   nutanix://d68f8014-966c-477d-b4e4-f478617058df   Running       3d6h    v1.30.5
nai-md-1-n8dqp-4df5f-4kbd7-llqgk   nai       nai-md-1-n8dqp-4df5f-4kbd7-llqgk   nutanix://d31c877b-5f9a-4dcc-9fde-a3eaff1f404d   Running       3d6h    v1.30.5
②Dify編につづく。
