Volume com NFS no Kubernetes

Photo by Timelab Pro on Unsplash

Volume com NFS no Kubernetes

Primeiramente, o assunto dessa publicação não é definir qual é a melhor opção. Portanto, aos comentaristas com ânsia em apontar a melhor ou a pior alternativa, estejam cientes desde já.

O assunto dessa publicação é, simplesmente, contribuir para quem precisa de provisionar um volume Kubernetes usando um serviço Network File System (NFS) como backend.

Vamos lá?

A priori, a Google Cloud (GCP) não disponibiliza Persistent Volume com ReadWriteMany de maneira nativa. Atualmente, é necessário contratar uma solução gerenciada chamada Filestore.

O ReadWriteMany é útil quando mais de um workload precisa ler e escrever num mesmo volume, mesmo estando em nós diferentes. Por exemplo, se você tem um Deployment com cinco réplicas e cada Pod precisa de escrever no mesmo volume.

Dito isso, a criação de um serviço NFS para disponibilizar um share é um meio disponível. Na prática, o custo de uma VM e um disco persistente. Ou até mesmo um serviço no próprio cluster.

Nessa publicação, espera-se que você já tenha um share de NFS pronto e disponível.

Crie os seguintes objetos Kubernetes:

PersistentVolume (PV)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: share
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""
  mountOptions:
    - nfsvers=4.2
  nfs:
    server: "nfs.domain.tld"
    path: "/my-share"
    readOnly: false
  # Se você quiser tornar esse PV exclusivo ao PVC
  # claimRef:
  #   name: 
  #   namespace:

PersistentVolumeClaim (PVC)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: share
  namespace: default
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: ""
  volumeName: share

Perceba que ambos possuem storageClassName com uma string vazia. Isso acontece para evitar que ele adote por um armazenamento diferente do que estamos buscando.

E, além disso, o PVC buscará pelo PV através de volumeName. Sendo parte da técnica de binding.

Por sua vez, o PV também pode fazer binding ao PVC através de claimRef. Isso seria a técnica completa. Se preferir, pode definir o claimRef para o nome e namespace do PVC. Nesse exemplo, não foi necessário.

O PV precisa do bloco nfs configurado com server e path com o serviço NFS disponível. Ou seja, defina o endereço IP ou nome DNS no campo spec.nfs.server e defina o caminho do share no campo spec.nfs.path.

Essa é a configuração de utilizar um serviço NFS por trás de um PV.

Assim, é possível você definir o volume no seu Deployment por exemplo:

  ...
  containers:
  - image: busybox
    name: teste
    volumeMounts:
    - mountPath: /opt/teste
      name: volume-compartilhado
  volumes:
  - name: volume-compartilhado
    persistentVolumeClaim:
      claimName: share

Simples?

Em caso de problemas, verifique se o serviço NFS tem regras de firewall permitindo a rede do nó, ou se há alguma restrição com permissão de usuários sobre o diretório utilizado no servidor.