# Install and run Longhorn on a single-node Kubernetes cluster

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/)
- [Understand Longhorn on Azure Cobalt 100](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/background/)
- [Create an Arm64 Azure virtual machine powered by Azure Cobalt 100](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/instance/)
- [Allow network access to the Longhorn Web UI on Azure](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/firewall/)
- [Install and run Longhorn on a single-node Kubernetes cluster](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/install-longhorn/)
- [Validate persistent Kubernetes storage and benchmark Longhorn with fio](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/longhorn-storage-validation-and-benchmark/)
- [Next Steps](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/_next-steps/)

## Set up the Kubernetes environment for Longhorn
Before you can deploy Longhorn, you need to set up a Kubernetes environment on the virtual machine (VM) that you created earlier. For steps to install kubectl, see the [kubectl install guide](https://learn.arm.com/install-guides/kubectl/).

### Update your system
Start by updating the package index and installing the latest available package updates on the VM:
```
sudo apt update && sudo apt upgrade -y
```

### Install required dependencies
Longhorn requires iSCSI utilities for block storage attachment, along with common tools used for downloading files, checking services, and managing the environment.

Install the iSCSI utilities and required tools:
```
sudo apt install -y \
open-iscsi \
nfs-common \
curl \
wget \
vim \
git
```

### Enable iSCSI service
Longhorn uses iSCSI to attach block volumes to Kubernetes workloads. Enable the iSCSI service before installing Longhorn:
```
sudo systemctl enable iscsid
```
After enabling the iSCSI service, start it:
```
sudo systemctl start iscsid
```
Verify that the service is running:
```
sudo systemctl status iscsid
```
The output is similar to:
```
__output__ Loaded: loaded (/usr/lib/systemd/system/iscsid.service; enabled; preset: enabled)
__output__ Active: active (running)
```

### Install K3s
K3s is a lightweight Kubernetes distribution suitable for a single-node Arm64 Azure VM powered by Azure Cobalt 100.

Install K3s:
```
curl -sfL https://get.k3s.io | sh -
```

### Verify Kubernetes installation
Wait a few seconds for K3s to fully initialize, then check that the Kubernetes node is ready:
```
sudo kubectl get nodes
```
The output is similar to:
```
__output__ NAME             STATUS   ROLES                  AGE   VERSION
__output__ longhorn-Arm64   Ready    control-plane,master   1m    v1.35.5+k3s1
```
If the ROLES column shows `<none>` immediately after installation, wait 30 to 60 seconds and run the command again. Role labels are applied after the node completes initialization.

### Configure kubectl access
Create the Kubernetes configuration directory for the current user:
```
mkdir -p ~/.kube
```
Copy the K3s kubeconfig file to your user profile:
```
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
```
Update ownership so that kubectl can access the configuration without sudo:
```
sudo chown $USER:$USER ~/.kube/config
```
Set the Kubernetes configuration environment variable:
```
export KUBECONFIG=$HOME/.kube/config
```
Persist the configuration for future terminal sessions:
```
echo 'export KUBECONFIG=$HOME/.kube/config' >> ~/.bashrc
source ~/.bashrc
```
Verify kubectl access:
```
kubectl get nodes
```
The output is similar to:
```
__output__ NAME             STATUS   ROLES           AGE   VERSION
__output__ longhorn-Arm64   Ready    control-plane   5s    v1.35.5+k3s1
```

### Check available disk space
By default, Longhorn stores volume replicas in `/var/lib/longhorn`. Verify that enough disk space is available on the VM before creating Longhorn volumes:
```
df -h
```

## Install Longhorn on Kubernetes
After setting up the Kubernetes environment, install Longhorn on the Kubernetes cluster using the official Longhorn manifest:

> **Note**  
> The following command uses Longhorn version 1.10.0. The same approach works with other versions. Replace the version in the URL with your version of choice that’s compatible with your K3s version. To find the latest version, see [Longhorn releases on GitHub](https://github.com/longhorn/longhorn/releases).

```
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.10.0/deploy/longhorn.yaml
```

### Verify Longhorn installation
Longhorn deploys several components including the manager, driver, UI, and CSI controllers. These components can take several minutes to fully start. Monitor the pod rollout in the `longhorn-system` namespace:
```
kubectl rollout status deployment/longhorn-driver-deployer -n longhorn-system
```
After the deployment is ready, check that all Longhorn pods are running:
```
kubectl get pods -n longhorn-system
```
The output is similar to:
```
__output__ NAME                                                READY   STATUS    RESTARTS   AGE
__output__ csi-attacher-65c5dd9586-dplk2                       1/1     Running   0          19s
__output__ csi-attacher-65c5dd9586-krglp                       1/1     Running   0          19s
__output__ csi-attacher-65c5dd9586-lnt7n                       1/1     Running   0          19s
__output__ csi-provisioner-c4f7f9c79-6mgtd                     1/1     Running   0          19s
__output__ csi-provisioner-c4f7f9c79-jcfnq                     1/1     Running   0          19s
__output__ csi-provisioner-c4f7f9c79-rbnlz                     1/1     Running   0          19s
__output__ csi-resizer-d4b7d97c7-d26xx                         1/1     Running   0          19s
__output__ csi-resizer-d4b7d97c7-mw44r                         1/1     Running   0          19s
__output__ csi-resizer-d4b7d97c7-nvgnf                         1/1     Running   0          19s
__output__ csi-snapshotter-5c96f555f9-7cmdb                    1/1     Running   0          19s
__output__ csi-snapshotter-5c96f555f9-l8dzk                    1/1     Running   0          19s
__output__ csi-snapshotter-5c96f555f9-wkt2g                    1/1     Running   0          19s
__output__ engine-image-ei-26bab25d-9w2r2                      1/1     Running   0          72s
__output__ instance-manager-949b7e7f84f3ef321c4078941b7dac4e   1/1     Running   0          42s
__output__ longhorn-driver-deployer-5889c569cf-88hwk           1/1     Running   0          94s
__output__ longhorn-manager-ptwb5                              2/2     Running   0          94s
__output__ longhorn-ui-77cdc466b5-8vlrl                        1/1     Running   0          94s
__output__ longhorn-ui-77cdc466b5-dbsx5                        1/1     Running   0          94s
```

## Access the Longhorn UI
After installation completes, you need to expose the Longhorn frontend service using port forwarding. Run the following command in a dedicated terminal session, as it must remain active while you use the dashboard:
```
kubectl -n longhorn-system port-forward --address 0.0.0.0 service/longhorn-frontend 8080:80
```
> **Note**  
> The port-forward connection closes when the terminal session ends. If you lose access to the dashboard, run the command again in a new terminal.

Open the Longhorn web UI in your browser. Replace `<PUBLIC_IP>` with the public IP address of your Azure VM.
```
http://<PUBLIC_IP>:8080
```
![Longhorn UI Dashboard with storage and node summary](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/images/longhorn-ui.png)  
*Longhorn UI Dashboard with storage and node summary*

In the Longhorn dashboard, you can view the number of volumes, available schedulable storage, node status, and overall storage health.

## Configure Longhorn for a single-node cluster
By default, Longhorn expects multiple nodes and uses a higher replica count. Because you’re using a single VM in this Learning Path, configure the replica count to `1` so that volumes can be scheduled on a single node.

To configure the replica count, follow these steps:
1. In the Longhorn UI, select **Settings**.
2. Find the **Default Replica Count** setting and set both **V1 Data Engine** and **V2 Data Engine** to `1`.
3. Select **Save**.

![Longhorn Replica configuration for single-node Kubernetes cluster](https://learn.arm.com/learning-paths/servers-and-cloud-computing/longhorn-cobalt/images/longhorn-replica.png)  
*Longhorn Replica configuration for single-node Kubernetes cluster*

This configuration allows Longhorn volumes to be scheduled successfully on a single-node Kubernetes cluster.

### Verify that Longhorn is available for persistent volume provisioning
Check the Kubernetes storage classes created by K3s and Longhorn:
```
kubectl get storageclass
```
The output is similar to:
```
__output__ NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
__output__ local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  8m48s
__output__ longhorn (default)     driver.longhorn.io      Delete          Immediate              true                   6m29s
__output__ longhorn-static        driver.longhorn.io      Delete          Immediate              true                   6m26s
```
The `longhorn` StorageClass confirms that Longhorn is available for dynamic persistent volume provisioning.

## What you’ve accomplished and what’s next
You’ve now installed required dependencies, enabled iSCSI, installed Longhorn, accessed the Longhorn Web UI, and configured the replica count for a single-node Kubernetes environment.

Next, you’ll create persistent volume claims, deploy an application using Longhorn storage, validate data persistence, and benchmark storage performance using fio.
