In the previous post, we set up a basic k3s cluster with MetalLB to handle LoadBalancer IPs. Now it’s time to enable dynamic, persistent storage using Longhorn. Longhorn provides highly available storage across your Kubernetes nodes, making it perfect for configuration files for applications. Local persistent volumes are great for databases as well which struggle in NFS.
Why Longhorn?
Longhorn is a lightweight, distributed block storage system designed specifically for Kubernetes. It works great in smaller setups like ours and supports features like snapshots, backups, and volume replicas across nodes.
Prerequisites
Each k3s node in your cluster should have:
- A second unformatted disk (we created a 50GB drive for this in Post 2)
- Ubuntu Server with NFS tools (
nfs-common
) installed - SSH access from the jumpbox
Step-by-Step Installation
Step 1: Label Your Nodes
We’ll label each node to enable scheduling of Longhorn pods:
kubectl label node cube1 longhorn=true
kubectl label node cube2 longhorn=true
kubectl label node cube3 longhorn=true
Step 2: Install Longhorn via Helm
Add the Longhorn Helm repo and install it into its own namespace:
helm repo add longhorn https://charts.longhorn.io
helm repo update
kubectl create namespace longhorn-system
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--set persistence.defaultClass=true \
--set defaultSettings.defaultDataPath="/mnt/longhorn"
⚠️ Important: Replace
/mnt/longhorn
with the mount path of your 50GB disk on each node. You’ll need to manually mount the drive and ensure it persists after reboots.
Step 3: Format and Mount the Second Disk
SSH into each node and run:
sudo mkfs.ext4 /dev/sdb
sudo mkdir -p /mnt/longhorn
sudo mount /dev/sdb /mnt/longhorn
To make it persistent:
echo "/dev/sdb /mnt/longhorn ext4 defaults 0 0" | sudo tee -a /etc/fstab
Step 4: Access the UI
Once deployed, the Longhorn UI should be available. You can expose it using a LoadBalancer service:
apiVersion: v1
kind: Service
metadata:
name: longhorn-frontend
namespace: longhorn-system
spec:
type: LoadBalancer
loadBalancerIP: 10.0.0.30
ports:
- port: 80
targetPort: 80
selector:
app: longhorn-ui
Apply with:
kubectl apply -f longhorn-service.yaml
Then access it at http://10.0.0.30
Step 5: Test It
Create a PersistentVolumeClaim using the longhorn
storage class:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1Gi
Apply with:
kubectl apply -f test-pvc.yaml
You should see the volume show up in the Longhorn dashboard.
With Longhorn up and running, we’re now ready to deploy apps that need persistent storage — like applications, dashboards, and databases. In the next post, we’ll cover setting up NFS access for large media files.
➡️ Stay tuned for Post 5: Configuring NFS Storage for Media Apps.