Nutanix Enterprise AI no NKPParte 2: Nutanix Files para o Kubernetes

Publicado
Leitura
20 min

Testado emNKP 2.19Nutanix Files 5.4.0.1Nutanix CSI 3.9.0Prism Central 7.6Lab em Em outra versão, confira a matriz de compatibilidade e as release notes antes de aplicar.

Read in English

Capa da série Nutanix Enterprise AI no NKP, com a parte 2, Nutanix Files, em destaque

Resumo: o Nutanix Enterprise AI guarda os modelos num volume ReadWriteMany (RWX), e a storage class padrão do NKP é a do Nutanix Volumes, ReadWriteOnce; o RWX vem do Nutanix Files. Nesta parte eu crio um Nutanix Files 5.4.0.1 pelo Prism Central (3 FSVMs, 5 TiB, 27 minutos), habilito NFS v3 e v4, testo a montagem numa VM e ligo o Files ao Kubernetes. Um detalhe de configuração que vale conhecer: o CSI do NKP 2.19 roda em modo Prism Central, e o Files dinâmico precisa de um secret próprio com um usuário de REST API do file server. No fim, um volume RWX fica pronto em 6 segundos, e dois pods em nós diferentes gravam no mesmo arquivo. Esta é a parte 2 de 4.

Onde estamos

A série acompanha a habilitação do Nutanix Enterprise AI (NAI) num lab com NKP 2.19 e cluster HCI Nutanix sem GPU.

ParteTema
1NAI: arquitetura, licenciamento e dimensionamento
2Nutanix Files para o Kubernetes: o RWX que o NAI exige (este post)
3Do catálogo ao primeiro token: cluster dedicado, NAI 2.8.1 e licença
4CPU, GPU e MCP: o NAI numa arquitetura híbrida

Antes de instalar o NAI, li o User Guide da versão 2.8.1 e os dois Nutanix Validated Designs que tratam dele. Os três concordam num pré-requisito que o NKP não entrega pronto: storage compartilhado em NFS. Esta parte resolve isso de ponta a ponta, e serve para qualquer aplicação no NKP que precise de RWX, não só para o NAI.


Por que o NAI precisa de RWX

Um volume no Kubernetes tem um modo de acesso. Os dois que importam aqui:

ModoSiglaQuem montaExemplo no NKP
ReadWriteOnceRWOUm nó por veznutanix-volume (Nutanix Volumes, iSCSI), a storage class padrão
ReadWriteManyRWXVários nós ao mesmo tempoPrecisa de NFS: Nutanix Files com o CSI

O NAI baixa cada modelo uma vez e o deixa num volume compartilhado. Quando um endpoint ganha uma segunda réplica, ou quando o pod é recriado em outro nó, ele lê os pesos do mesmo lugar, sem baixar tudo de novo. Por isso o volume dos modelos precisa ser RWX.

O que o User Guide do NAI 2.8.1 pede de storage:

ItemRequisitoPara quê
Block (RWO)≥ 150 GiBPostgreSQL, ClickHouse, Valkey, logs de auditoria
NFS (RWX)≥ 2 TiB, storage class com volumeBindingMode: ImmediateModelos validados ou custom
Export NFSv4Um share à parteImportar modelos custom ou baixados à mão
S31 TiB (opcional)Outra forma de importar modelos

Vale para além do NAI

JupyterHub com diretórios compartilhados, pipelines de ML que leem o mesmo dataset em vários pods, CMSs com uploads compartilhados: tudo que precisa de RWX no NKP passa pelo mesmo caminho deste post.

A arquitetura

O Nutanix Files roda como um conjunto de VMs no próprio cluster HCI, as FSVMs (File Server VMs). Elas servem NFS para os clientes e guardam os dados num storage container do cluster. Do lado do Kubernetes, o CSI da Nutanix faz duas coisas diferentes: pela API REST do Files, cria um share para cada volume pedido; pelo NFS, monta esse share no nó onde o pod roda.

PeçaPapel
FSVMVM do file server; com 3, um export continua no ar se uma FSVM cair
Rede clientOnde os clientes (nós do Kubernetes, VMs) montam o NFS
Rede storageInterna: FSVMs falando com as CVMs e entre si
Storage containerCriado pelo assistente só para o file server
CSI controllerFala com a API do Files para criar, expandir e apagar shares
CSI nodeMonta o NFS no nó, para o pod usar

Planejamento: as decisões antes do assistente

Tamanho

Os NVDs da Nutanix usam FSVMs de 12 vCPU e 64 GB em produção. Num lab, o recurso escasso é memória, então fui no mínimo suportado.

ItemNVD (produção)LabPor quê
FSVMs33Mínimo para alta disponibilidade do file server
vCPU / memória por FSVM12 / 64 GB4 / 12 GBMínimo suportado; dá para crescer depois, sem parar
Capacidade—5 TiBAcima dos 2 TiB que o NAI pede, com folga para modelos e outros apps

As 3 FSVMs somam 36 GB de RAM. Fiz a conta do cluster antes: o lab tem 3 hosts, e eu quero que tudo continue rodando se um host cair (N+1), o que limita o uso a cerca de dois terços da memória total.

Rede

O assistente pede duas redes. No lab existe uma só VLAN, gerenciada pelo IPAM do AHV, então as duas ficaram nela.

RedeIPs necessários (3 FSVMs)No lab
Client3 (um por FSVM)Mesma VLAN das VMs, IPs do IPAM
Storage4 (FSVMs + 1)Mesma VLAN, IPs do IPAM

O Files exige uma sub-rede com IPAM

O assistente só lista sub-redes gerenciadas (com IPAM). Os IPs saem do pool automaticamente; anote-os depois do deploy e registre no seu plano de endereçamento. Em produção, os NVDs recomendam a rede client numa sub-rede separada, por segurança; no lab, isso é um desvio consciente.

DNS e NTP

O Files pede servidores de DNS e NTP. O lab não tem DNS interno, e eu quis confirmar o que o gateway resolvia antes de preencher:

Terminal window
$ dig @192.0.2.1 pe.lab.exemplo.local
;; WARNING: .local is reserved for Multicast DNS
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN
;; AUTHORITY SECTION:
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. ...

NXDOMAIN com o SOA da raiz da internet: o gateway só encaminha consultas para fora e não conhece o domínio interno. Consequência prática: os clientes vão montar o Files pelo IP, não pelo nome. Funciona bem, e o CSI aceita IP normalmente.

Atenção

.local é reservado O próprio dig avisa: o sufixo .local é do mDNS (RFC 6762). Em ambiente de cliente, prefira um subdomínio de um domínio real, como lab.empresa.com.br.

Licença

O Files é licenciado pela Nutanix Unified Storage (NUS), medida em TiB utilizáveis. Antes de criar, conferi o que estava aplicado no cluster:

Licenças aplicadas ao cluster: NCI Ultimate e NCI Security, NCM Ultimate e duas linhas de NUS Pro, uma de 1 TiB incluída no NCI e outra de 50 TiB

LicençaQuantidadeObservação
NUS Pro incluída no NCI Ultimate1 TiBVem junto com o NCI Ultimate
NUS Pro50 TiBLicença do lab
NCI Security60 coresÉ o Flow Network Security

Para quem tem NCI Ultimate

O NCI Ultimate já traz 1 TiB de NUS Pro. Dá para começar um file server pequeno sem comprar nada a mais.


Criando o file server pelo Prism Central

Objetivo: um file server com 3 FSVMs, 5 TiB e NFS, criado pelo assistente do Prism Central (Files → File Servers → New File Server).

O ponto de partida, sem nenhum file server:

Prism Central, Files, File Servers: There are no File Servers available

1. Local: Prism Central ou Prism Element

A primeira tela pede o provider (Nutanix, AWS ou Azure) e já traz um aviso: alguns recursos não são suportados em file servers criados pelo Prism Central; para usá-los, crie pelo Prism Element.

Aviso do assistente: alguns recursos não são suportados em file servers criados pelo Prism Central

Segui pelo Prism Central. Esse aviso pesa na escolha da proteção (veja a seção de proteção).

2. Cluster e versão

O assistente lista só as versões compatíveis e disponíveis no LCM. Havia 13; escolhi a mais nova, a 5.4.0.1.

Escolha do cluster e da versão do file server: 13 versões compatíveis, 5.4.0.1 selecionada

3. Básico e dimensionamento

Nome (até 15 caracteres, sem ponto), domínio DNS, capacidade lógica e o tamanho das FSVMs.

Tela File Server Basics: nome files-lab, domínio, 5 TiB, 3 FSVMs de 4 vCPU e 12 GB

CampoValor
Namefiles-lab
DNS Domainlab.exemplo.local
File Server Size (Logical)5 TiB
Number of FSVMs3
vCPUs / Memory4 / 12 GB

4. Rede client e rede storage

As duas telas mostram a faixa do IPAM, quantos IPs estão livres e quantos o file server vai usar: 3 na client, 4 na storage.

Rede client: vlan-prod, prefixo e faixa do IPAM, 107 IPs livres, 3 necessários

Rede storage: mesma VLAN, 104 IPs livres, 4 necessários

5. Settings: DNS, NTP e dois interruptores para Kubernetes

Esta é a tela mais importante, porque nada aqui muda depois do deploy.

Tela Settings: DNS, NTP, perfil Default, Direct Attach e Containerized Workload ligados

O campo Deployment Profile tem três opções:

Perfis de deploy: Default, General Dedicated e AI/ML Dedicated

PerfilO que fazQuando usar
DefaultRecursos compartilhados, sem otimização especialUso geral (o do lab)
General DedicatedFSVM e CVM em nós NUMA separadosDesempenho mais previsível
AI/ML DedicatedDirect Attach + NUMA dedicado, um file server por clusterCargas de IA com alto throughput (veio desabilitado no lab)

E os dois interruptores:

OpçãoO que fazDecisão
Direct Attach modeLiga os volume groups direto às FSVMs, sem passar o tráfego de storage pela rede. Menos latência. Não funciona com Metro Availability nem com DR entre hypervisorsLigado (o lab não usa nenhum dos dois)
Containerized WorkloadPré-cria volume groups no deploy e no scale-out para acelerar a criação e a exclusão de shares pelo KubernetesLigado: é exatamente o uso do CSI

6. Resumo

Resumo antes do Create: FQDN, cluster, versão 5.4.0.1, 5 TiB, 3 FSVMs de 4 vCPU e 12 GB, redes, DNS, NTP, perfil e opções


O deploy: 27 minutos

O Prism Central criou as 3 FSVMs nos primeiros 90 segundos e depois montou a imagem do Files e configurou o cluster de file server.

Tarefa Create File Server a 5%, com as três FSVMs já criadas

Tarefa Create File Server concluída em 27 minutos e 18 segundos

HorárioEvento
22:11Início da tarefa Create File Server
22:123 FSVMs criadas (uma por host)
22:15Download dos artefatos e montagem da imagem 5.4.0.1
22:38Succeeded (27 min 18 s)
22:37 a 22:42Pré-criação dos volume groups (Containerized Workload)

Lista de file servers: files-lab, criado pelo Prism Central, 3 FSVMs, versão 5.4.0.1

O dashboard do file server já abriu Healthy, sem alertas e com os 5 TiB livres:

Dashboard do files-lab: Healthy, 0 alertas, 5 TiB livres, nenhum share e recursos como Smart DR e Smart Tiering desligados

Logo depois do Succeeded, o Files ainda rodou duas tarefas: FS Deploy VG Create e Volume Group Manage. É o Containerized Workload em ação, pré-criando os volume groups que os shares do Kubernetes vão usar.

Tarefas pós-deploy concluídas: Volume Group Manage com subtarefas de VG e FS Deploy VG Create

Espere as tarefas pós-deploy

Crie o primeiro share só depois que FS Deploy VG Create e Volume Group Manage chegarem a 100%. No lab, foram mais 5 minutos.

A rede do file server

A tela de rede mostra o desenho e os IPs que o IPAM entregou:

Diagrama do file server: clientes, NTP, DNS e AD na rede externa; três FSVMs; rede interna para o storage; container NTNX_files-lab_ctr

FSVMIP client (montagem NFS)IP storage
NTNX-files-lab-1192.0.2.128192.0.2.152
NTNX-files-lab-2192.0.2.132192.0.2.194
NTNX-files-lab-3192.0.2.129192.0.2.157

IPs client das três FSVMs

O quarto IP da rede storage (o “+1” do assistente) não aparece na tabela da interface. Ele existe; procure no IPAM da sub-rede se precisar registrar.

O container que o Files cria

O assistente cria um storage container só para o file server, NTNX_files-lab_ctr. Conferi as propriedades contra o NVD do GPT-in-a-Box:

Container NTNX_files-lab_ctr: RF2, compressão ligada com atraso de 60 minutos, deduplicação e erasure coding desligados

PropriedadeLabNVD
Replication Factor22
CompressãoLigada (atraso de 60 min)Ligada (60 min)
DeduplicaçãoDesligadaDesligada
Erasure CodingDesligadoDesligado

Igual ao recomendado, sem mexer em nada. Os 32 GiB já usados logo após o deploy são os volume groups pré-criados.


Habilitando o NFS

O file server nasce sem protocolo. Em Configuration → Authentication, habilitei só o NFS:

Protocolos: SMB desligado (exige Active Directory), NFS com gerenciamento Unmanaged; por padrão, só NFSv3 vem marcado

OpçãoValorPor quê
SMBDesligadoExige Active Directory; não é necessário para Kubernetes
User ManagementUnmanagedSem AD e sem LDAP; o acesso é controlado por IP do cliente, como o CSI espera
NFSv3Ligado (padrão)Compatibilidade
NFSv4LigadoVem desmarcado por padrão. Necessário para mount -t nfs4
NFS over TLSDesligadoRede interna do lab

Habilite o NFSv4 antes dos exports

O padrão de fábrica é só NFSv3. Marque Enable NFSv4 by default for all exports antes de criar os exports, ou cada export nasce sem v4.

Primeiro export e o teste manual

Antes de envolver o Kubernetes, testei o Files sozinho, com um export de 10 GiB montado numa VM Linux.

Standard ou Distributed

Tipo Standard: dados e conexões servidos por uma única FSVM

Tipo Distributed: diretórios de topo distribuídos entre as FSVMs

TipoComo funcionaQuando usar
StandardUma FSVM serve o export inteiroA maioria dos casos; é o que o CSI cria
DistributedOs diretórios de topo são distribuídos entre as FSVMsMuitos clientes ou muita capacidade, como homes de usuários

O squash e o sudo

Na tela de permissões, o padrão é Root Squash:

Resumo do export com Squash: Root squash

Com root squash, o root do cliente vira um usuário anônimo no servidor. Como o meu teste gravava com sudo, ele falharia com Permission denied. Para o teste, troquei para None:

Resumo do export com Squash: None, NFSV3V4, Read-write

Montando numa VM

Terminal window
$ sudo apt install -y nfs-common
$ sudo mount -t nfs4 192.0.2.128:/teste-nfs /mnt/teste-nfs
$ echo "ok $(date)" | sudo tee /mnt/teste-nfs/teste.txt
ok Fri Oct 30 01:56:55 AM UTC 2026
$ df -h /mnt/teste-nfs
Filesystem Size Used Avail Use% Mounted on
192.0.2.132:/teste-nfs 0 0 0 - /mnt/teste-nfs
$ mount | grep teste-nfs
192.0.2.132:/teste-nfs on /mnt/teste-nfs type nfs4 (rw,vers=4.2,proto=tcp,sec=sys,addr=192.0.2.132)

Três coisas para reparar:

  1. Montei pelo .128 e terminei no .132. Num export Standard, uma FSVM só atende o export inteiro, e o Files usa o redirecionamento do NFSv4 para mandar o cliente para ela. O cliente pode usar qualquer IP client.
  2. NFS 4.2, negociado sozinho.
  3. O df mostra tamanho 0. O Files não expõe a cota do export ao cliente NFS. Não é erro; vale saber para não estranhar.

O Kubernetes enxergando o Files

O que já existe no NKP

O NKP instala o CSI da Nutanix em todo cluster. O inventário do cluster de workload:

Terminal window
$ kubectl get sc
NAME PROVISIONER VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION
dkp-object-store <workspace>.ceph.rook.io/bucket Immediate false
nutanix-volume (default) csi.nutanix.com WaitForFirstConsumer true
$ kubectl get csidrivers
NAME ATTACHREQUIRED PODINFOONMOUNT MODES
csi.nutanix.com true true Persistent
$ kubectl -n ntnx-system get ds,deploy -o wide | grep csi
daemonset.apps/nutanix-csi-node 6 6 6 ... docker.io/nutanix/ntnx-csi:3.9.0
deployment.apps/nutanix-csi-controller 2/2 ... docker.io/nutanix/ntnx-csi:3.9.0

O driver é o 3.9.0, a storage class padrão é a de Volumes (RWO) e existe um único secret de credenciais, ntnx-system/nutanix-csi-credentials.

O detalhe: o CSI está em modo Prism Central

A documentação do CSI 3.x mostra o Files dinâmico com o driver falando com o Prism Element, e um secret com uma segunda chave, files-key. Antes de copiar o exemplo, verifiquei com quem o CSI do NKP fala, sem expor nenhuma senha:

Terminal window
# Só os nomes das chaves do secret
$ kubectl -n ntnx-system get secret nutanix-csi-credentials \
-o go-template='{{range $k,$v := .data}}{{$k}}{{"\n"}}{{end}}'
key
# Só host e porta da chave (o comando corta usuário e senha)
$ kubectl -n ntnx-system get secret nutanix-csi-credentials \
-o jsonpath='{.data.key}' | base64 -d | cut -d: -f1,2
192.0.2.88:9440
$ kubectl -n ntnx-system get deploy nutanix-csi-controller -o yaml \
| grep -iE 'usepc|use_pc|management-plane|mixed'
app.kubernetes.io/management-plane: PrismCentral
- name: USE_PC
- --use-mixed-mode=false

O endereço é o do Prism Central, e o controller tem USE_PC. O CSI do NKP 2.19 roda em modo PC.

Como o Files dinâmico funciona em modo PC

A documentação principal mostra o modo PE. O modo PC também aceita o Files dinâmico com um secret próprio que tenha a chave do Prism Central (key) e a do file server (files-key: <file server>:<usuário>:<senha>). O log do CSI confirma: “Using Files secrets available in PC Mode”.

Não edite o secret do NKP

O nutanix-csi-credentials é gerenciado pelo NKP. Crie um secret separado só para a storage class do Files.

1. Usuário de REST API no file server

O files-key usa um usuário da API do próprio file server, não do Prism. Ele é criado no console do file server, em Configuration → Manage Roles → REST API access users:

Manage Roles: usuário de REST API csi-nkp sendo adicionado, com a senha mascarada

Clique no ✓

A linha do usuário fica em modo de edição até você clicar no ✓ à direita. Sem isso, o usuário não é salvo.

2. Secret próprio

O script lê a chave do Prism Central do secret do NKP e monta o novo secret sem mostrar nada na tela:

Terminal window
read -rp "Usuário de REST API do file server: " FU
read -rsp "Senha (não aparece): " FP; echo
PCKEY=$(kubectl -n ntnx-system get secret nutanix-csi-credentials \
-o jsonpath='{.data.key}' | base64 -d)
kubectl -n ntnx-system create secret generic nutanix-files-csi \
--from-literal=key="$PCKEY" \
--from-literal=files-key="192.0.2.128:$FU:$FP"
unset PCKEY FP

Usei o IP client no files-key, e não o nome, porque os nós do lab não resolvem o domínio interno.

3. A storage class

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nai-nfs
provisioner: csi.nutanix.com
parameters:
storageType: NutanixFiles
dynamicProv: ENABLED
nfsServerName: files-lab # nome do file server no Prism
nfsServer: 192.0.2.128 # IP client: montagem e API
squashType: "none"
csi.storage.k8s.io/provisioner-secret-name: nutanix-files-csi
csi.storage.k8s.io/provisioner-secret-namespace: ntnx-system
csi.storage.k8s.io/node-publish-secret-name: nutanix-files-csi
csi.storage.k8s.io/node-publish-secret-namespace: ntnx-system
csi.storage.k8s.io/controller-expand-secret-name: nutanix-files-csi
csi.storage.k8s.io/controller-expand-secret-namespace: ntnx-system
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate # exigência do NAI
ParâmetroValorPor quê
dynamicProv: ENABLEDUm share novo por PVCCada volume isolado, apagado junto com o PVC
nfsServerNamefiles-labO CSI procura o file server pelo nome
nfsServerIP clientUsado para montar e, junto com o files-key, para a API
squashTypenoneLab; avalie root-squash em produção conforme as imagens que vão gravar
volumeBindingModeImmediateO NAI exige; o padrão do NKP é WaitForFirstConsumer

O teste RWX: dois nós, um arquivo

O teste cria um PVC RWX de 2 GiB e um deployment com 2 réplicas, obrigadas a cair em nós diferentes (podAntiAffinity). Cada réplica grava uma linha a cada 5 segundos no mesmo arquivo:

apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: rwx-teste }
spec:
accessModes: [ReadWriteMany]
storageClassName: nai-nfs
resources: { requests: { storage: 2Gi } }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: rwx-escritor }
spec:
replicas: 2
selector: { matchLabels: { app: rwx-escritor } }
template:
metadata: { labels: { app: rwx-escritor } }
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: { matchLabels: { app: rwx-escritor } }
topologyKey: kubernetes.io/hostname
containers:
- name: c
image: busybox:1.36
command: ["sh","-c","while true; do echo \"$(date -u +%H:%M:%S) $(hostname) no nó $NODE\" >> /dados/log.txt; sleep 5; done"]
env: [{ name: NODE, valueFrom: { fieldRef: { fieldPath: spec.nodeName } } }]
volumeMounts: [{ name: d, mountPath: /dados }]
volumes: [{ name: d, persistentVolumeClaim: { claimName: rwx-teste } }]

O resultado:

Terminal window
$ kubectl -n files-teste get pvc rwx-teste
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
rwx-teste Bound pvc-bc03c1b0-8456-4cda-a43c-3a5f70b446ea 2Gi RWX nai-nfs 6s
$ kubectl -n files-teste get pods -o wide
NAME READY STATUS NODE
rwx-escritor-68f798cf6d-v5s5s 1/1 Running worker-a
rwx-escritor-68f798cf6d-wrlph 1/1 Running worker-b
$ kubectl -n files-teste exec <pod> -- tail -6 /dados/log.txt
02:38:48 rwx-escritor-68f798cf6d-wrlph no nó worker-b
02:38:50 rwx-escritor-68f798cf6d-v5s5s no nó worker-a
02:38:53 rwx-escritor-68f798cf6d-wrlph no nó worker-b
02:38:55 rwx-escritor-68f798cf6d-v5s5s no nó worker-a
02:38:58 rwx-escritor-68f798cf6d-wrlph no nó worker-b
02:39:00 rwx-escritor-68f798cf6d-v5s5s no nó worker-a
linhas por pod:
5 rwx-escritor-68f798cf6d-v5s5s
5 rwx-escritor-68f798cf6d-wrlph
$ kubectl -n files-teste exec <pod> -- mount | grep /dados
192.0.2.128:/pvc-bc03c1b0-... on /dados type nfs4 (rw,vers=4.2,proto=tcp,...)

As linhas das duas réplicas se intercalam: dois nós gravando no mesmo arquivo. Isso é RWX.

O que o CSI fez por baixo

O log do controller mostra o caminho completo, em cerca de 2,6 segundos:

Using Files secrets available in PC Mode
GET https://192.0.2.128:9440/api/files/v4.0/config/file-servers
POST https://192.0.2.128:9440/api/files/v4.0/config/file-servers/<uuid>/mount-targets
Task completed with status: SUCCEEDED, progress: 100%
Setting cfg.volumePath with value: pvc-bc03c1b0-8456-4cda-a43c-3a5f70b446ea
ControllerPublishVolume called ... nfsServer:192.0.2.128 nfsServerName:files-lab provNFSShare:ENABLED
EtapaO que aconteceu
1O CSI encontrou o files-lab pela API v4 do Files, usando o files-key
2Criou um mount target (o share) com o nome do PV
3Esperou a tarefa terminar (SUCCEEDED)
4Publicou o volume nos dois nós, que montaram por NFS 4.2

Três mensagens informativas que vale conhecer:

MensagemO que significa
FailedScheduling ... pod has unbound immediate PersistentVolumeClaimsOs pods tentaram subir antes do PVC ficar Bound. Some em segundos
NutanixFiles: Unknown option "storageType"Log informativo; o parâmetro é ignorado nesse ponto
df com tamanho 0O Files não expõe a cota ao cliente NFS; o PV mostra os 2 GiB

O ciclo de vida, visto do Files

Com o teste rodando, o volume aparece no console do Files como um share com o nome do PV:

Shares & Exports: o share pvc-bc03c1b0 criado pelo CSI ao lado do nai-modelos

Apaguei o namespace do teste. Com reclaimPolicy: Delete, o CSI removeu o share sozinho:

Shares & Exports depois da limpeza: só o nai-modelos


O export dos modelos do NAI

O NAI também pede um export NFSv4 à parte, para importar modelos custom ou baixados à mão. Criei o nai-modelos: Standard, NFS v3 e v4, Read-Write, squash None, sem limite de tamanho.

Resumo do export nai-modelos: Standard, NFSV3V4, Read-write, squash None

Propriedades do share nai-modelos: caminho, descrição, mount path e tamanho máximo de 5 TiB

“Max Size 5 TiB” significa que o export pode usar o file server inteiro. O Mount Path aparece com o nome DNS; sem DNS interno, use o IP client.

Proteção: Protection Domain, Smart DR ou SSR

O console do file server oferece duas formas de proteção:

Data Protection: Protection Domain (Prism Element) e Smart DR, ambos desligados

Ao configurar o Protection Domain, a tela indica que ele vale para file servers criados pelo Prism Element:

Tooltip: o recurso é suportado apenas em file servers criados pelo Prism Element

OpçãoO que fazNo lab
Protection DomainSnapshot do file server inteiro, com replicação assíncrona opcionalNão se aplica ao lab: é para file servers criados pelo Prism Element
Smart DRReplicação por share para outro file server, com failover em um cliqueExige um segundo file server
Self Service RestoreSnapshots por share para o usuário recuperar arquivosPossível; pouco útil para modelos, que podem ser baixados de novo

Self Service Restore: nenhum share com SSR e a política Default, com intervalo mínimo de 1 hora, 38 snapshots e 4 agendas (24 horárias, 7 diárias, 4 semanais e 3 mensais)

No lab, decidi não proteger o file server: os modelos podem ser baixados de novo, e os dados que importam do NAI (banco, métricas, cache) ficam em volumes RWO, no Nutanix Volumes. A proteção desses volumes é assunto para o NDK e o Velero.

Decida no assistente: Prism Central ou Prism Element

Se o file server precisar de Protection Domain ou replicação assíncrona, crie pelo Prism Element. Pelo Prism Central, a proteção é o Smart DR, por share e com um segundo file server. Leia o link View Incompatible Features da primeira tela do assistente antes de decidir.


Lab × Nutanix Validated Design

TemaNVDLabSituação
FSVMs33Igual
Tamanho da FSVM12 vCPU / 64 GB4 vCPU / 12 GBDesvio consciente
Rede storageMesma sub-rede das CVMsMesma VLANIgual
Rede clientSub-rede separadaMesma VLANDesvio consciente
IPs4 storage + 3 client4 + 3Igual
ContainerSeparado, RF2, compressão, sem dedup e ECIgualIgual
Protocolo e CSINFS, provisionamento dinâmicoNFS, dinâmicoIgual
Export para modelos customSimnai-modelosIgual
Objects (S3)3 workers + 2 load balancersNão instaladoFica para depois (~104 GB de RAM)

Os números

MedidaValor
Deploy do file server27 min 18 s
Tarefas pós-deploy (volume groups)~5 min
Criação do share pelo CSI (API v4)~2,6 s
PVC RWX Bound6 s
Pods prontos (com pull da imagem)~22 s
Memória das 3 FSVMs36 GB
Capacidade5 TiB lógicos

O que aprendi

  1. O RWX do NKP vem do Nutanix Files. A storage class padrão é Nutanix Volumes (RWO); para o NAI, e para qualquer app com volume compartilhado, adicione o Files e uma storage class própria.
  2. O CSI do NKP 2.19 roda em modo Prism Central. O Files dinâmico funciona nesse modo com um secret próprio que tenha key (PC) e files-key (usuário de REST API do file server).
  3. Containerized Workload e Direct Attach são as opções certas para Kubernetes, e não mudam depois do deploy.
  4. Habilite o NFSv4 antes de criar exports. O padrão de fábrica é só NFSv3.
  5. Root squash e sudo não combinam no teste manual; decida o squash conscientemente na storage class.
  6. Para Protection Domain, crie o file server pelo Prism Element. Pelo Prism Central, a proteção é o Smart DR.
  7. Sem DNS interno, monte pelo IP. O Files redireciona o cliente para a FSVM certa.

Checklist: Nutanix Files para o NKP

  • Licença NUS aplicada ao cluster (o NCI Ultimate traz 1 TiB)
  • Memória para as FSVMs dentro do N+1 do cluster
  • Sub-rede com IPAM e IPs livres (FSVMs na client; FSVMs + 1 na storage)
  • DNS e NTP alcançáveis pela rede client
  • Decidido: Prism Central ou Prism Element (proteção)
  • Containerized Workload e Direct Attach ligados no assistente
  • Tarefas pós-deploy concluídas antes do primeiro share
  • NFSv4 habilitado
  • Usuário de REST API criado (e salvo com o ✓)
  • Secret próprio com key e files-key, sem tocar no secret do NKP
  • Storage class RWX com Immediate
  • Teste com 2 pods em nós diferentes e o share sumindo depois da limpeza
  • Export separado para modelos custom (se for usar o NAI)

O que ainda não testei

  • Nutanix Objects (S3), que o NVD usa no desenho: não instalei no lab e fica para depois (são ~104 GB de RAM).
  • Proteção do file server com Smart DR, que pede um segundo file server. No lab, decidi não proteger o Files, porque os modelos podem ser baixados de novo.
  • O tamanho de produção do NVD: FSVMs de 12 vCPU / 64 GB e rede client numa sub-rede separada. No lab, fiquei no mínimo suportado e numa VLAN só, como desvio consciente.

Próxima parte

Na Parte 3, o cluster dedicado ao NAI na NKP 2.19, as dependências do catálogo, o NAI 2.8.1 e a licença, que tem só 2 dias de trial depois da instalação.

Referências

Nutanix

Projetos e comunidade

Independentes

Comentários

Os comentários usam o GitHub Discussions; é preciso ter uma conta no GitHub.