Saltar al contenido principal

K8s + NFS (CentOS)

· 4 min de lectura
Rei Izumi

La mentalidad de los contenedores es que sus datos se pierden tras borrarse, así que los datos que necesitamos que no se pierdan, deberán ir en volumenes.

En caso de tener un Kubernetes desplegado en una Cloud, lo recomendable es utilizar el sistema de estos, pero si tenemos nuestro propio sistema, nos tendremos que apañar con lo que podamos.

El más sencillo de todos es asociar el volumen a una carpeta compartida por NFS.

Explicación

Lo primero a tener en cuenta es que compartiremos una carpeta de un servidor utilizando NFS, cualquier nodo que despliegue el pod, montará la unidad con NFS, en caso de que el servidor NFS se caiga o no sea posible conectar con él, la carpeta del contenedor dejará de funcionar, así que nuestro pod funcionará, no llegará a caerse por defecto, pero no funcionará correctamente. Tener en cuenta esto es muy importante, ya que si nuestro pod está bien configurado y Kubernetes detecta esta caída del servicio, es posible que intente volver a desplegar un nuevo pod para matar al anterior, pero este nuevo pod fallará por no poder conectar al servidor NFS, y así una y otra vez.

El otro punto importante es que NFS únicamente comparte la unidad, no se encarga de replicas, así que, si los datos del servidor se pierden, se perdería todo, con lo que sería altamente recomendable tener un sistema de copias de seguridad.

Este artículo está planteado para ser una base de cómo preparar un servidor NFS y desplegar un Nginx que lo utilice, para ello utilizaré servidores CentOS y un Kubernetes.

1- NFS Server

Necesitamos un servidor que haga de servidor, así que instalamos todo.

dnf install nfs-utils nfs4-acl-tools -y
systemctl enable --now nfs-server
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --permanent --add-service=mountd
firewall-cmd --reload

Ahora creamos una carpeta y la compartimos

mkdir -p /mnt/nfsShare/storage1
vi /etc/exports

En CentOS 8 es necesario añadir el no_root_squash para poder escribir en la carpeta compartida sin problemas.

/mnt/nfsShare/storage1 192.168.1.0/24(rw,sync,no_root_squash)

Exportamos la unidad

exportfs -rav

Podemos mostrar la lista de todas las carpetas compartidas.

exportfs  -v

2- NFS Client en nodos

En cada nodo de Kubernetes hay que instalar las aplicaciones necesarias para que puedan montar carpetas compartidas, si un nodo no lo tiene, al revisar los logs del pod, veremos un error montando la partición.

dnf install nfs-utils nfs4-acl-tools -y

3- Desplegar Nginx con NFS

Lo primero será preparar el PersistentVolume donde se indicará la ruta hacia el servidor, la ruta y el tamaño del storage, nfs-pv.yaml:

apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-storage
spec:
storageClassName: storage-nfs
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: nfsServer.domain.intranet
path: "/mnt/nfsShare/storage1"

Lo siguiente será conectar el PersistentVolumeClaim que utilizaremos en el despliegue, nfs-pvc-nginx.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-nginx
spec:
storageClassName: storage-nfs
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

Utilizando el ejemplo de la documentación oficial, con la pequeña modificación de que se anclará su carpeta de publicación a la carpeta compartida por NFS, nginx-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-nfs-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nfs-storage
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs-storage
persistentVolumeClaim:
claimName: nfs-nginx

Una vez tenemos los 3 ficheros, los aplicamos.

kubectl create -f nfs-pv.yaml
kubectl create -f nfs-pvc-nginx.yaml
kubectl create -f nginx-deployment.yaml

Podemos comprobar que el PersistentVolume esté creado.

kubectl get pv

Resultado:

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS        REASON   AGE
nfs-storage 1Gi RWX Retain Bound default/nfs-nginx storage-nfs 106s

El PersistentVolumeClaim.

kubectl get pvc

Resultado:

NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
nfs-nginx Bound nfs-storage 1Gi RWX storage-nfs 2m5s

Y finalmente, los pods.

kubectl get pods -o wide -l app=nginx

Resultado:

NAME                                    READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
nginx-nfs-deployment-559d6cb454-9h6vg 1/1 Running 0 28s 10.244.93.4 temp101 <none> <none>
nginx-nfs-deployment-559d6cb454-gzrgd 1/1 Running 0 28s 10.244.173.200 temp102 <none> <none>

Para hacer la prueba, podemos acceder dentro de uno de los pods, crear un index.html y confirmar que podemos verlo.

kubectl exec -it nginx-nfs-deployment-559d6cb454-9h6vg -- bash
cd /usr/share/nginx/html
echo "Hello NFS" > index.html
curl localhost

Lo que nos devolverá el contenido del index.html

Si modificamos este fichero desde el host de NFS, veremos el cambio inmediatamente.

Final

Partiendo de este ejemplo, podremos desplegar cualquier contenedor conectando sus volumenes a un NFS, así no nos tendremos que preocupar de replicas entre diferentes nodos o pérdida de datos.

Aun así, hay que tener en cuenta los problemas de rendimiento que puede tener la red.