Adding Longhorn Storage to a k0s Cluster
After setting up our k0s cluster and configuring ingress in the previous posts, let’s add persistent storage capabilities using Longhorn. Longhorn is a lightweight and reliable distributed block storage system, perfect for our k0s cluster.
This is a continuation of the previous posts, Setting up a k0s cluster on netcup and Adding an ingress controller to a k0s cluster.
Why Longhorn?
Longhorn is an excellent choice for our k0s cluster because:
- Distributed storage with data replication
- Backup and restore capabilities
- Simple installation and management
- Low resource overhead
- Perfect for small to medium clusters
Prerequisites
The nodes we have from netcup have sufficient disk space (for some small experiments at least).
However, we need to make sure that each node has the package open-iscsi
installed, which is needed for Longhorn to work.
# On each node:
apt-get update
apt-get install -y open-iscsi
We will also need a DNS entry for the Longhorn UI, for example using the name longhorn.helmuth.at
.
I create this entry in the DNS provider as a CNAME pointing to k0s-cluster.helmuth.at
.
Installing Longhorn
We’ll use the helm chart to install Longhorn:
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn --namespace longhorn-system
This will create the longhorn-system
namespace and deploy all necessary components. Monitor the deployment:
kubectl -n longhorn-system get pods
Wait until all pods are running.
Accessing the Longhorn UI
To access the Longhorn UI securely, we’ll create an ingress resource. First, let’s create a Basic Auth secret:
# Generate auth file
USER=admin # replace with your desired username
PASSWORD=secret-password # replace with your desired password
echo "${USER}:$(openssl passwd -stdin -apr1 <<< ${PASSWORD})" > auth
# Create secret
kubectl -n longhorn-system create secret generic basic-auth --from-file=auth
It’s important to have the secret key named “auth” - this is the name of the file we created.
Now create the ingress resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: longhorn-ingress
namespace: longhorn-system
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required '
nginx.ingress.kubernetes.io/proxy-body-size: 10000m
spec:
rules:
- host: longhorn.helmuth.at
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: longhorn-frontend
port:
number: 80
tls:
- hosts:
- longhorn.helmuth.at
secretName: longhorn-tls
Save this as longhorn-ingress.yaml
and apply:
kubectl apply -f longhorn-ingress.yaml
Testing Longhorn
Let’s create a test deployment using Longhorn storage. For this, I will deploy MySQL with persistent storage. First the PVC (Persistent Volume Claim):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 10Gi
Then the deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:8.0.23
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: test@123
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pvc
And finally the service:
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
selector:
app: mysql
ports:
- protocol: TCP
port: 3306
targetPort: 3306
Apply these configurations:
kubectl apply -f mysql-pvc.yaml
kubectl apply -f mysql-deployment.yaml
kubectl apply -f mysql-service.yaml
Now we can access the MySQL database from the cluster.
kubectl run mysql-client --image=mysql:5.7 -it --rm --restart=Never -- mysql -h mysql -u root -p
# No prompt visible - enter password: test@123
mysql> show databases;
mysql> quit
Next Steps
We have a Kubernetes cluster with an ingress controller, a cert-manager setup, and persistent storage using Longhorn. We are ready for some experiments!
Thanks for reading!