Longhorn: Cloud-Native Distributed Block Storage for Kubernetes
In the dynamic world of Kubernetes, managing persistent storage for stateful applications remains a critical challenge. While ephemeral storage is easy, ensuring data availability, durability, and performance across distributed nodes requires a robust solution. Traditional storage arrays can be complex and costly, often lacking the cloud-native agility that Kubernetes champions. This is where Longhorn steps in – a powerful, open-source, distributed block storage system designed specifically for Kubernetes.
Longhorn transforms local storage on your Kubernetes nodes into a highly available, distributed block storage solution. It’s built on a microservices architecture, leveraging existing Kubernetes primitives like Custom Resource Definitions (CRDs), StatefulSets, and DaemonSets. This deep integration means you can manage your storage directly within Kubernetes, using familiar tools and workflows. Whether you’re running databases, message queues, or any other stateful workload, Longhorn provides the reliability and flexibility needed to keep your applications running smoothly, even in the face of node failures.
This guide will walk you through the process of deploying Longhorn, provisioning storage, and demonstrating its key features. By the end, you’ll have a solid understanding of how to leverage Longhorn to provide resilient and scalable persistent storage for your Kubernetes clusters, enhancing your cloud-native infrastructure with a truly distributed solution.
TL;DR: Longhorn Cloud-Native Distributed Block Storage
Longhorn provides highly available, distributed block storage for Kubernetes, turning local storage into network-attached storage. It’s fully integrated with Kubernetes, offering features like snapshots, backups, and cross-cluster disaster recovery.
Key Commands:
- Install Longhorn via Helm:
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace
kubectl -n longhorn-system port-forward svc/longhorn-frontend 8080:80
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn
provisioner: driver.longhorn.io
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
parameters:
numberOfReplicas: "3"
staleReplicaTimeout: "30" # seconds
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-longhorn-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
name: longhorn-test-pod
spec:
containers:
- name: test-container
image: busybox
command: ["sh", "-c", "echo 'Hello Kubezilla' > /data/testfile.txt; sleep 3600"]
volumeMounts:
- name: longhorn-volume
mountPath: /data
volumes:
- name: longhorn-volume
persistentVolumeClaim:
claimName: my-longhorn-pvc
Prerequisites
Before diving into Longhorn, ensure you have the following:
* **Kubernetes Cluster:** A running Kubernetes cluster (v1.18 or newer). This can be a local cluster like Kind or Minikube for testing, or a cloud-managed cluster (EKS, GKE, AKS) for production.
* **kubectl:** The Kubernetes command-line tool, configured to connect to your cluster. Refer to the official Kubernetes documentation for installation instructions.
* **Helm:** The Kubernetes package manager, version 3 or newer. Install it from the official Helm website.
* **Disk Space:** Each node where Longhorn replicas will reside needs sufficient free disk space. A minimum of 10GB is recommended for testing, but more for production. Longhorn uses a dedicated directory on each node for storage.
* **iSCSI Initiator:** The iSCSI initiator must be installed on all nodes that will be used by Longhorn. Most Linux distributions have this pre-installed or easily installable.
* **Ubuntu/Debian:** `sudo apt-get update && sudo apt-get install open-iscsi`
* **CentOS/RHEL/Fedora:** `sudo yum install iscsi-initiator-utils`
* **`bash` shell:** For executing the commands provided in this guide.
Step-by-Step Guide: Deploying and Using Longhorn
Step 1: Install Longhorn using Helm
Longhorn is a CNCF project and its installation is streamlined using Helm. We’ll add the Longhorn Helm repository, update it, and then install Longhorn into its own namespace. This ensures all Longhorn components are isolated and easily manageable.
The `longhorn-system` namespace will house all the necessary deployments, daemonsets, and services that make up the Longhorn control plane and data plane. This includes the Longhorn manager, UI, and various engines that handle the actual storage operations.
# 1. Add the Longhorn Helm repository
helm repo add longhorn https://charts.longhorn.io
# 2. Update your Helm repositories to fetch the latest chart information
helm repo update
# 3. Install Longhorn into the 'longhorn-system' namespace
# The --create-namespace flag ensures the namespace is created if it doesn't exist.
helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace
**Verify:**
After running the installation command, Helm will output the release status. You can verify the deployment by checking the pods in the `longhorn-system` namespace. All pods should eventually reach the `Running` state. This might take a few minutes as images are pulled and components initialize.
kubectl get pods -n longhorn-system
**Expected Output:**
(Output may vary slightly based on your cluster size and Longhorn version)
NAME READY STATUS RESTARTS AGE
longhorn-admission-webhook-7f8976c76-5h7z9 1/1 Running 0 2m30s
longhorn-backend-7c986c78-z9x2b 1/1 Running 0 2m30s
longhorn-csi-attacher-67c46d97c-k7l8v 1/1 Running 0 2m30s
longhorn-csi-provisioner-78768798d-j6m5l 1/1 Running 0 2m30s
longhorn-csi-resizer-6b66d7c7b-p7m9s 1/1 Running 0 2m30s
longhorn-driver-deployer-7d9f67c7d-x2m5n 1/1 Running 0 2m30s
longhorn-manager-27r7f 1/1 Running 0 2m30s
longhorn-manager-5d8f6 1/1 Running 0 2m30s
longhorn-manager-q4t8p 1/1 Running 0 2m30s
longhorn-ui-5f78b87c7b-c2v3g 1/1 Running 0 2m30s
instance-manager-r-c867d7b-s4c6g 1/1 Running 0 2m30s
instance-manager-e-f7d8c7b-x3y5z 1/1 Running 0 2m30s
engine-image-ei-v1.5.1-6c7d8f-m7n8p 1/1 Running 0 2m30s
csi-snapshotter-5f78b87c7b-c2v3g 1/1 Running 0 2m30s
Step 2: Access the Longhorn UI
The Longhorn UI provides a graphical interface to manage your storage volumes, nodes, and settings. It’s a powerful tool for monitoring and operating your Longhorn installation. To access it, we’ll use `kubectl port-forward` to expose the `longhorn-frontend` service to your local machine.
This allows you to securely access the UI without exposing it directly to the internet, which is ideal for initial setup and management. The UI will provide insights into the health of your Longhorn system, available storage, and the status of your volumes and replicas.
kubectl -n longhorn-system port-forward svc/longhorn-frontend 8080:80
**Verify:**
Open your web browser and navigate to http://localhost:8080. You should see the Longhorn dashboard. The dashboard provides an overview of your cluster’s storage resources, including nodes, volumes, and their health.
**Expected Output:**
A web browser displaying the Longhorn dashboard. Look for the “Node” and “Volume” sections to ensure your cluster nodes are registered and healthy.
Step 3: Configure Default Storage Paths and Disks (Optional but Recommended)
By default, Longhorn uses `/var/lib/longhorn` on each node for storage. While this works, it’s often better to dedicate specific disks or partitions for Longhorn to ensure performance and prevent conflicts with the operating system. You can configure this via the Longhorn UI or by patching the `nodes` custom resources.
For demonstration, we’ll configure a custom path using the UI. This step is crucial for production environments to ensure storage is properly isolated and managed. For more advanced node management, including taints and tolerations, refer to the Kubernetes documentation on taints and tolerations.
1. In the Longhorn UI, navigate to **Node** in the left sidebar.
2. Click on a node name.
3. Click **Edit Node and Disks**.
4. You can disable the default `/var/lib/longhorn` disk if you prefer.
5. Click **Add Disk**.
6. Provide a name (e.g., `longhorn-data`) and a path (e.g., `/mnt/longhorn`). Ensure this path exists and has sufficient permissions on your node(s).
7. Click **Save**.
8. Repeat for all nodes you want to contribute storage. You’ll need to manually create the `/mnt/longhorn` directory on each node:
# On each Kubernetes node:
sudo mkdir -p /mnt/longhorn
sudo chmod 777 /mnt/longhorn # Adjust permissions as needed for your setup
**Verify:**
After configuring, the Longhorn UI should show the new disk path on the respective nodes, and the “Schedulable” status should be “True”. The “Used” and “Free” space should also update.
Step 4: Create a Longhorn StorageClass
To provision volumes dynamically, Kubernetes uses StorageClasses. We’ll create a StorageClass named `longhorn` that tells Kubernetes to use the `driver.longhorn.io` provisioner. This StorageClass will define the default behavior for volumes created through it, such as the number of replicas.
The `numberOfReplicas` parameter is critical for high availability. Setting it to `3` means each piece of data will have three copies distributed across different nodes. This ensures that if one or even two nodes fail, your data remains accessible. The `staleReplicaTimeout` dictates how long a replica can be offline before Longhorn considers it “stale” and attempts to rebuild it.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn
provisioner: driver.longhorn.io
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
parameters:
numberOfReplicas: "3" # Recommended for production for high availability
staleReplicaTimeout: "30" # seconds, how long to wait before rebuilding a stale replica
# dataLocality: "disabled" # Can be "disabled" (default) or "best-effort"
# replicaAutoBalance: "least-effort" # Can be "disabled", "least-effort", "best-effort"
# fsType: "ext4" # Default filesystem type, can be ext4 or xfs
# backingImage: "" # Optional: specify a backing image for volume creation
kubectl apply -f longhorn-storageclass.yaml
**Verify:**
Confirm that the StorageClass has been created successfully.
kubectl get storageclass longhorn
**Expected Output:**
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
longhorn driver.longhorn.io Delete Immediate true 10s
Step 5: Provision a PersistentVolumeClaim (PVC) and Mount it to a Pod
Now that Longhorn is installed and a StorageClass is defined, we can request storage using a PersistentVolumeClaim (PVC). This PVC will dynamically provision a Longhorn volume. We’ll then create a simple Pod that mounts this PVC and writes some data to it.
This process demonstrates the standard Kubernetes workflow for stateful applications. The `ReadWriteOnce` access mode means the volume can be mounted as read-write by a single node. The `storage: 5Gi` requests a 5 Gigabyte volume. The Pod then mounts this volume at `/data` and writes a simple text file.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-longhorn-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
name: longhorn-test-pod
spec:
containers:
- name: test-container
image: busybox
command: ["sh", "-c", "echo 'Hello Kubezilla' > /data/testfile.txt; sleep 3600"]
volumeMounts:
- name: longhorn-volume
mountPath: /data
volumes:
- name: longhorn-volume
persistentVolumeClaim:
claimName: my-longhorn-pvc
kubectl apply -f longhorn-pvc-pod.yaml
**Verify:**
Check the status of the PVC and the Pod. The PVC should transition to `Bound`, and the Pod should be `Running`. You can also exec into the pod to verify the data.
kubectl get pvc my-longhorn-pvc
kubectl get pod longhorn-test-pod
kubectl exec -it longhorn-test-pod -- cat /data/testfile.txt
**Expected Output:**
# kubectl get pvc my-longhorn-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-longhorn-pvc Bound pvc-12345678-abcd-efgh-ijkl-1234567890ab 5Gi RWO longhorn 30s
# kubectl get pod longhorn-test-pod
NAME READY STATUS RESTARTS AGE
longhorn-test-pod 1/1 Running 0 20s
# kubectl exec -it longhorn-test-pod -- cat /data/testfile.txt
Hello Kubezilla
You can also observe the newly created volume in the Longhorn UI under the “Volume” section. It will show its status, replicas, and associated Pod.
Step 6: Test Data Persistence and High Availability
One of Longhorn’s core strengths is its high availability. Let’s simulate a node failure and observe how Longhorn handles it. This demonstrates the resilience of your stateful applications. For more advanced network configurations that support high availability across different network zones, consider exploring solutions like Cilium WireGuard Encryption.
1. **Identify the node running the Pod:**
kubectl get pod longhorn-test-pod -o wide
Note the `NODE` column.
2. **Drain the node (simulating maintenance or failure):**
Replace `
kubectl drain --ignore-daemonsets --delete-emptydir-data --force
*Note: `–force` and `–delete-emptydir-data` are used here for a quick simulation. In a real scenario, you’d carefully consider these flags.*
3. **Observe the Pod and Volume:**
The `longhorn-test-pod` will go into a `Pending` or `ContainerCreating` state as Kubernetes tries to reschedule it. If you look at the Longhorn UI, you’ll see the volume detach from the drained node and reattach to a healthy node. Longhorn will automatically detect the node failure and initiate a recovery process, promoting one of the healthy replicas to primary.
Once the pod is rescheduled and running on a new node, verify the data is still there.
kubectl get pod longhorn-test-pod -o wide # See new node
kubectl exec -it longhorn-test-pod -- cat /data/testfile.txt
**Expected Output:**
The `longhorn-test-pod` will eventually become `Running` on a *different* node, and the `cat` command will still output:
Hello Kubezilla
This confirms data persistence and Longhorn’s ability to recover from node failures.
Step 7: Create a Snapshot and Restore
Snapshots are crucial for data protection and recovery. Longhorn allows you to create point-in-time snapshots of your volumes, which can then be used to restore the volume to a previous state or create new volumes from the snapshot.
1. **Create a new file in the volume:**
kubectl exec -it longhorn-test-pod -- sh -c "echo 'New data after snapshot' >> /data/newfile.txt"
kubectl exec -it longhorn-test-pod -- cat /data/newfile.txt
**Expected Output:** `New data after snapshot`
2. **Create a snapshot:**
In the Longhorn UI, navigate to **Volume** -> `my-longhorn-pvc` -> **Create Snapshot**. Give it a meaningful name (e.g., `before-new-data`).
3. **Simulate data loss/corruption:**
Delete the `newfile.txt` from the pod.
kubectl exec -it longhorn-test-pod -- rm /data/newfile.txt
kubectl exec -it longhorn-test-pod -- ls /data/ # newfile.txt should be gone
4. **Restore from snapshot:**
In the Longhorn UI, navigate to **Volume** -> `my-longhorn-pvc` -> **Snapshot** tab. Select the snapshot you just created and click **Revert**. You will need to stop the pod using the volume first.
kubectl delete pod longhorn-test-pod
# Wait for the pod to terminate
kubectl get pod longhorn-test-pod
After reverting in the UI, recreate the pod:
apiVersion: v1
kind: Pod
metadata:
name: longhorn-test-pod
spec:
containers:
- name: test-container
image: busybox
command: ["sh", "-c", "echo 'Hello Kubezilla' > /data/testfile.txt; sleep 3600"]
volumeMounts:
- name: longhorn-volume
mountPath: /data
volumes:
- name: longhorn-volume
persistentVolumeClaim:
claimName: my-longhorn-pvc
kubectl apply -f longhorn-pvc-pod.yaml
5. **Verify restored data:**
Once the new pod is running, check for the `newfile.txt`.
kubectl exec -it longhorn-test-pod -- cat /data/newfile.txt
**Expected Output:**
New data after snapshot
This demonstrates that the volume was successfully reverted to the state at the time of the snapshot.
Production Considerations
Deploying Longhorn in a production environment requires careful planning beyond the basic installation.
1. **Node Affinity and Taints/Tolerations:** For better performance and isolation, consider using node affinity to ensure stateful applications run on nodes with local Longhorn replicas (data locality). You might also use taints and tolerations to dedicate specific nodes for storage or compute.
2. **Dedicated Storage Disks:** Always use dedicated physical disks or partitions for Longhorn data, separate from the OS disk. This prevents I/O contention and improves performance. For cloud environments, use high-performance block storage like AWS EBS gp3 or io2, or GCP Persistent Disk SSD.
3. **Network Performance:** Longhorn relies heavily on network connectivity for replication and data transfer. Ensure your cluster’s network has high bandwidth and low latency. For specialized networking needs, projects like Cilium can provide advanced networking capabilities.
4. **Backup and Disaster Recovery:** While snapshots provide point-in-time recovery, external backups are essential for true disaster recovery. Longhorn supports backing up volumes to S3-compatible object storage or NFS. Regularly test your backup and restore procedures.
5. **Monitoring and Alerting:** Integrate Longhorn metrics into your existing monitoring system (Prometheus, Grafana). Longhorn exposes detailed metrics about volume health, replica status, I/O performance, and more. For advanced eBPF-based observability, consider tools like eBPF Observability with Hubble.
6. **Resource Allocation:** Pay attention to CPU and memory requests/limits for Longhorn components, especially the instance managers. Over-provisioning can lead to resource contention, while under-provisioning can impact performance.
7. **StorageClass Parameters:** Carefully choose `numberOfReplicas` (3 is recommended for production), `dataLocality`, and `replicaAutoBalance` based on your availability and performance requirements.
8. **Security:** Implement Kubernetes Network Policies to restrict traffic to and from Longhorn components, ensuring only authorized services can communicate with the storage system. For comprehensive supply chain security, explore solutions like Sigstore and Kyverno.
9. **Cost Optimization:** While Longhorn uses existing infrastructure, optimizing node utilization is key. Tools like Karpenter can help manage node lifecycles efficiently, ensuring you only pay for the resources you need.
10. **Upgrade Strategy:** Plan your Longhorn upgrades carefully. Always review the official Longhorn upgrade documentation for specific instructions and potential breaking changes.
Troubleshooting
1. **Issue:** Longhorn pods are stuck in `Pending` or `CrashLoopBackOff`.
* **Solution:**
* Check pod logs: `kubectl logs -n longhorn-system
* Check events: `kubectl describe pod -n longhorn-system
* Common causes include insufficient resources (CPU/memory), incorrect iSCSI initiator setup on nodes, or network issues. Ensure iSCSI is installed and running on all nodes.
* Verify node health and resource availability.
2. **Issue:** Volumes are stuck in `Detaching` or `Faulted` state.
* **Solution:**
* This often indicates a problem with the node where the volume was last attached, or a network issue.
* Check the node’s status in the Longhorn UI (Node tab). If a node is down or unhealthy, Longhorn might be waiting for it to recover or for a timeout to expire before automatically detaching and reattaching the volume.
* If a node is permanently lost, you might need to manually remove it from Longhorn (via UI: Node -> Edit -> Disable Scheduling, then Delete).
* Ensure no Pod is still trying to use the volume on a non-existent node.
3. **Issue:** `kubectl exec` into a pod with a Longhorn volume fails with “input/output error” or “transport endpoint not connected”.
* **Solution:**
* This usually means the underlying Longhorn volume is having issues.
* Check the volume status in the Longhorn UI. Is it healthy? Are all replicas healthy?
* Check the instance manager logs on the node where the volume is attached.
* Restarting the pod might resolve transient issues. If not, investigate network connectivity between the node and other nodes hosting replicas.
4. **Issue:** Longhorn UI is inaccessible (`localhost:8080` connection refused).
* **Solution:**
* Ensure the `longhorn-frontend` service is running: `kubectl get svc -n longhorn-system longhorn-frontend`.
* Verify the `port-forward` command is still active and hasn’t timed out or been terminated.
* Check the logs of the `longhorn-ui` pod for errors: `kubectl logs -n longhorn-system
5. **Issue:** Volume creation fails with “failed to create volume: failed to get volume access mode for volume
* **Solution:**
* This error can occur if the StorageClass parameters are incorrect or if there’s a problem with the Longhorn provisioner.
* Double-check your `longhorn-storageclass.yaml` for typos or missing parameters.
* Ensure the `longhorn-csi-provisioner` pod is running and healthy in the `longhorn-system` namespace.
* Review the logs of the `longhorn-csi-provisioner` pod.
6. **Issue:** Performance is poor (slow I/O).
* **Solution:**
* **Network:** Check network latency and bandwidth between nodes. Longhorn’s performance is heavily dependent on the network for replication.
* **Disk I/O:** Are you using dedicated disks for Longhorn? Are they fast enough (e.g., SSDs)? Avoid using the OS disk or slow HDDs.
* **Replicas:** More replicas increase durability but can slightly increase write latency due to data synchronization.
* **Node Resources:** Ensure nodes have sufficient CPU and memory, especially for the `instance-manager` pods and the applications using the volumes.
* **Longhorn UI:** Check the “Node” and “Volume” dashboards for I/O metrics and potential bottlenecks.
7. **Issue:** Longhorn UI shows nodes as “Disconnected” or “Down”.
* **Solution:**
* This typically means the Longhorn manager on that node is not communicating with the rest of the cluster.
* Check the node’s status in Kubernetes: `kubectl get nodes`. Is it `Ready`?
* SSH into the affected node and check the status of the `longhorn-manager` daemonset pod running on it: `kubectl logs -n longhorn-system
* Verify network connectivity from the node to the Kubernetes API server and other nodes.
* Ensure the iSCSI initiator is running and healthy on the node.
8. **Issue:** Expanding a volume fails or doesn’t reflect the new size.
* **Solution:**
* Ensure `allowVolumeExpansion: true` is set in your Longhorn StorageClass.
* The Pod using the volume must be restarted for the filesystem inside the container to recognize the expanded size. Longhorn itself expands the block device, but the filesystem still needs to be resized.
* After restarting the Pod, `df -h` inside the Pod should show the new size. If not, check the `longhorn-csi-resizer` logs.
FAQ Section
1. **What is the difference between Longhorn and other Kubernetes storage solutions like Ceph or Portworx?**
Longhorn is designed to be lightweight and easy to deploy, leveraging existing Kubernetes primitives and local storage. Ceph is a more comprehensive and complex distributed storage system that can provide block, object, and file storage, often requiring dedicated hardware and significant operational overhead. Portworx is a commercial solution offering enterprise-grade features and support, often with a higher cost. Longhorn strikes a balance, providing robust features with a lower barrier to entry for Kubernetes users.
2. **Can Longhorn be used in production?**
Yes, Longhorn is production-ready and used by many organizations. It’s a CNCF Sandbox project, indicating its growing maturity and community support. However, like any storage solution, proper planning, monitoring, and backup strategies are crucial for production deployments.
3. **Does Longhorn support ReadWriteMany (RWX) access mode?**
Longhorn primarily provides block storage with `ReadWriteOnce` (RWO) access mode, meaning a volume can only be attached to a single node at a time. For `ReadWriteMany` (RWX) access, you would typically need a shared filesystem solution like NFS or a distributed file system like CephFS. Longhorn does not natively provide an RWX block storage solution, though you can expose a Longhorn volume via NFS within a Pod if needed.
4. **How does Longhorn handle node failures?**
Longhorn uses a distributed replica mechanism. When a node fails, Longhorn automatically detects the failure. If the failed node was hosting the primary replica, one of the healthy secondary replicas is promoted to primary. The volume then detaches from the failed node and reattaches to a healthy node, allowing the application pod to reschedule and continue operating with minimal downtime.
5. **What are the recommended hardware requirements for Longhorn nodes?**
* **CPU/Memory:** Sufficient resources for both Longhorn components and the applications using the storage. At least 2-4 vCPUs and 8GB RAM per node is a good starting point for a small cluster.
* **Disk:** Dedicated SSDs are highly recommended for performance. Avoid using the OS disk. Allocate ample space as Longhorn uses it for replicas.
* **Network:** High-speed (10Gbps or more) and low-latency network connectivity between nodes is crucial for replication and I/O performance.
Cleanup Commands
To remove all Longhorn components and associated resources from your cluster, follow these steps. Be extremely careful, as this will delete all Longhorn volumes and their data.
1. **Delete all Longhorn volumes:**
You can do this via the Longhorn UI or by deleting all PVCs.
# Delete the test pod and PVC
kubectl delete -f longhorn-pvc-pod.yaml
# If you have other PVCs provisioned by Longhorn, delete them too.
# For example, to delete all PVCs in a namespace:
# kubectl delete pvc --all -n
2. **Uninstall Longhorn via Helm:**
Was this article helpful?
Thanks for your feedback.
