{{tag>projects Linux Kubernetes k8s kubeadm installation setup}} [[kubernetes|What is Kubernetes ( k8s )?]] {{ :projects:network-file-system-nfs-thumbnail.png:?600 }} ==== Setup CSI Driver for NFS ==== Reference: [[https://docs.k0sproject.io/v1.35.4+k0s.0/storage/|K0s CSI Driver]] First, CSI stands for Container Storage Interface. It is an API for storage drivers to interact with kubernetes ( k0s ). Storage drivers are software that facilitate data storage. However, different types of storage require different drivers to work. Some drivers are generic while others are specific to their vendor's features. **Note: This document assumes you already have an NFS server with at least 1 share. If you don't, see [[https://www.redhat.com/en/blog/nfs-server-client|Red Hat's blog - Learning NFS through server and client configuration]]** == Install Helm ( if you don't already have it ) == The best way to install components and applications ( apps ) is with the helm app. - Download helm from the [[https://helm.sh/docs/intro/install/|Helm]] website wget https://get.helm.sh/helm-v4.2.0-linux-amd64.tar.gz - You should verify the download with the sha256sum command: sha256sum helm-v4.2.0-linux-amd64.tar.gz | grep 97dbeb971be4ac4b27e3839976d9564c0fb35c6f3b1da89dd1e292d236af4096 - Extract the tarball: tar zxf helm-v4.2.0-linux-amd64.tar.gz - Move the file to a directory in your path sudo mv linux-amd64/helm /usr/local/bin/helm - Delete the extracted files and directories ( optional ) rm -rf linux-amd64 - Verify the helm command works helm version == Install Helm Chart for NFS == - Add the helm repo to your system # Add the official Kubernetes CSI Helm repository helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts helm repo update - Install the driver with the custom k0s path # Install the driver with the customized k0s path sudo helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs \ --namespace kube-system \ --set kubeletDir=/var/lib/k0s/kubelet \ --kubeconfig /var/lib/k0s/pki/admin.conf - Watch the pods deployment for about 3 minutes. watch -n1 'k0s kubectl --namespace=kube-system get pods --selector="app.kubernetes.io/instance=csi-driver-nfs"' == Setup a PV & PVC for NEW data storage == - Create a YAML file to define a StorageClass and toggle dynamic provisioning. Save the following manifest as nfs-storageclass.yaml. Make sure to substitute server with your actual NFS host IP and share with your exported path apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-csi provisioner: nfs.csi.k8s.io parameters: server: 192.168.1.50 # Replace with your NFS Server IP share: /volume1/k8s # Replace with your exported NFS path reclaimPolicy: Delete volumeBindingMode: Immediate mountOptions: - nfsvers=3 - hard # Pods wait if the NFS server goes offline - nolock # Use '-o nolock' to keep locks local - Create a PVC ( Persistent Volume Claim ) YAML file that makes the share available to the pods apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-nfs-pvc spec: accessModes: - ReadWriteMany storageClassName: nfs-csi resources: requests: storage: 5Gi - Apply the config to your cluster sudo k0s kubctl apply -f manifest-nfs-pvc.yaml - Check your PVC. You should see "Bound" in the STATUS column sudo k0s kubectl get pvc == Setup a PV & PVC for access to EXISTING data storage == - Create a PV YAML file **WITHOUT** a storage class apiVersion: v1 kind: PersistentVolume metadata: name: existing-nfs-pv spec: capacity: storage: 100Gi # Match or exceed what your pods need volumeMode: Filesystem accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain # Retain ensures data isn't deleted if the PVC drops storageClassName: "" # Must be blank or use a custom name to skip automatic provisioning csi: driver: nfs.csi.k8s.io volumeHandle: existing-nfs-shared-volume # Must be a unique string in the cluster volumeAttributes: server: 192.168.1.50 # Replace with your NFS Server IP share: /volume1/existing-data # Replace with your exact existing path mountOptions: - nfsvers=4.1 - hard - nolock # Kept to prevent the rpc.statd error - Create the PV sudo k0s kubectl aply -f manifest-existing-nfs-pv.yaml - Check the PV ( optional ) sudo k0s kubectl get pv - Create a PVC YAML file apiVersion: v1 kind: PersistentVolumeClaim metadata: name: existing-nfs-pvc spec: accessModes: - ReadWriteMany storageClassName: "" # Must remain blank to match the PV's blank storageClassName volumeName: existing-nfs-pv # Forces binding to your specific PV above resources: requests: storage: 100Gi # Must be less than or equal to the PV size - Check the PVC ( optional ). You should see "Bound" in the STATUS colunn sudo k0s kubectl get pvc - Start a web server pod that mounts the nfs share to verify access ( optional ) - Create an app YAML file apiVersion: v1 kind: Pod metadata: name: nfs-app-pod labels: # <--- ADD THIS BLOCK SO THE SERVICE CAN FIND IT name: nfs-app-pod spec: containers: - name: web-server image: nginx:latest volumeMounts: - name: nfs-storage mountPath: /usr/share/nginx/html # Path inside the container where data appears volumes: - name: nfs-storage persistentVolumeClaim: claimName: existing-nfs-pvc # Must exactly match your PVC name - Deploy the app sudo k0s kubectl apply -f manifest-app-nfs-test.yaml - Get a shell inside the pod to look at the file system and verify the files exist sudo k0s kubectl exec -it nfs-app-pod -- bash ls -lh /usr/share/nginx/html == Expose the app outside the cluster == - Install MetalLB loadbalancer helm repo add metallb https://metallb.github.io/metallb helm repo update helm install metallb metallb/metallb \ --namespace metallb-system \ --create-namespace \ --kubeconfig /var/lib/k0s/pki/admin.conf - Create an MetalLB YAML file to setup an IP pool/range apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: local-pool namespace: metallb-system spec: addresses: - 192.168.1.200-192.168.1.210 # <--- Change to your free network IP range --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: local-advertisement namespace: metallb-system spec: ipAddressPools: - local-pool - Create an app service YAML file to expose the app outside the cluster apiVersion: v1 kind: Service metadata: name: nfs-web-service spec: type: LoadBalancer selector: name: nfs-app-pod # MUST match the label on your Pod ports: - protocol: TCP port: 80 # The port open to your network targetPort: 80 # The port Nginx is listening on inside the container - Apply the config to your cluster sudo k0s kubctl apply -f manifest-app-nfs-web-service-lb.yaml