Kubernetes - Deploy Services that use Longhorn#
625 words | 8 min read
In the previous post, we installed Longhorn, and configured external access to the Longhorn UI.
Now, we will utilize the Longhorn in-cluster storage.
1. Define a Storage Class#
We need to define a storage class before we can define volumes for storage.
1.1. Define a Storage Class#
Create a configuration file (longhorn-rwxclass.yaml) for the storage class, as shown below.
Note
If you want to define this storage class as the default, set the annotation “storageclass.kubernetes.io/is-default-class” to “true”. There should only be one default storage class in a cluster.
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: longhorn-rwx
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
numberOfReplicas: "3"
staleReplicaTimeout: "2880"
fromBackup: ""
fsType: "ext4"
nfsOptions: "vers=4.2,noresvport,softerr,timeo=600,retrans=5,rw,hard"
reclaimPolicy: Retain
1.2. Apply the configuration#
k apply -f longhorn-rwx.yaml
1.3. Check the Storage Classes in your cluster#
k get storageclass -A
2. Create a Persistent Volume Claim (PVC)#
2.1. Define a Persistent Volume Claim#
Create a configuration file (nginx-pvc.yaml) for the Persistent Volume Claim (PVC), as shown below:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-rwx
spec:
accessModes:
# - ReadWriteOnce
- ReadWriteMany
storageClassName: longhorn-rwx
resources:
requests:
storage: 1Gi
2.2. Apply the configuration#
k apply -f nginx-pvc.yaml
2.3. Check the PVCs in your cluster#
k get pvc -A
Note
Longhorn will automatically create a PersistentVolume (PV) when you create a PVC based on a Storage Class
2.4. Check the PVs in your cluster#
k get pv -A
3. Deploy NGinx in the cluster#
3.1. Define an NGinX pod#
Create a configuration file (nginx-pod.yaml) for the NGinX Webserver Pod.
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
app: nginx
name: nginx-webserver
namespace: default
spec:
containers:
- name: nginx-server
image: nginx:latest
volumeMounts:
- name: rwx-volume
mountPath: /usr/share/nginx/html
# mountPath: /data
volumes:
- name: rwx-volume
persistentVolumeClaim:
claimName: nginx-rwx
3.2. Apply The Configuration#
k apply -f nginx-pod.yaml
3.3 Define a Service for the NginX Pod#
Create a configuration file (nginx-svc.yaml) for the NGinX Service.
apiVersion: v1
kind: Service
metadata:
labels:
run: nginx
name: nginx-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: nginx
app: nginx
sessionAffinity: None
type: ClusterIP
3.4. Apply The Configuration#
k apply -f nginx-svc.yaml
3.5. Define The Gateway for the NGinX Webserver#
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx-gateway
spec:
gatewayClassName: cilium
listeners:
- protocol: HTTP
port: 80
name: nginx-web
allowedRoutes:
kinds:
- kind: HTTPRoute
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route
spec:
parentRefs:
- name: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
# - backendRefs:
# - kind: Service
- name: nginx-svc
port: 80
3.6. Apply The Gateway Configuration#
k apply -f nginx-gateway.yaml
3.7. Obtain the IP address of the NGinX Gateway#
k get svc -A -o wide
3.8. Connect to the NGinX Gateway#
Open a browser and connect to the IP address of the NGinX Gateway (in my case, it is http://10.44.0.3).
You will get an error (403 - Forbidden) because there are no files for the Webserver to serve.
4. Add a file into the persistent storage of the Webserver pod#
4.1. Connect to the Nginx pod#
k exec -it nginx-webserver -- /bin/bash
This should take you to a prompt that looks like this:
root@nginx-webserver:/#
4.2. Create the index.html file for testing#
Type the following at the command prompt
cat - > /usr/share/nginx/html/index.html
Now, paste the following HTML (or another one of your choice) and press CTRL+D to save the file.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Test By Lytn1ng</title>
</head>
<body lang="en-US">
<p>This is a test of NginX using Longhorn persistent in-cluster storage.</p>
</body>
</html>
4.3. Test the NGinX Webserver#
Open a browser and connect to http://10.44.0.3/. You should see the test HTML that we just created.
5. Test the persistence in Longhorn#
So far, so good. But what about the “persistent” part that we have been talking about for so long? How do we know that our data (i.e. the HTML file) will persist?
5.1. Destroy our deployed artifacts#
Destroy the Gateway, Service and pod that we deployed.
Important
Do NOT destroy the PV or the PVC that we created for NGinX in Longhorn. That’s where our data will be persisted even after the pod is destroyed.
k delete -f nginx-gateway.yaml
k delete -f nginx-svc.yaml
k delete -f nginx-pod.yaml
Now, our NGinX pod, Service and gateway have all been destroyed. You can check and verify with kubectl commands that our pod, Service and Gateway (Loadbalancer) are no longer running.
But has our data been persisted? Let’s find out.
5.2. Re-deploy the artifacts#
k apply -f nginx-pod.yaml
k apply -f nginx-svc.yaml
k apply -f nginx-gateway.yaml
5.3. Check the IP address of the re-deployed Gateway#
k get svc -A -o wide
5.4. Connect to the Gateway#
Open a browser and connect to the Gateway External-IP (http://10.44.0.3/).
You should see the HTML file that you created in Step 4.2 above.
So, although the pod running NGinX was destroyed and recreated, the index.html that was stored in the Longhorn PV survived, and was available to our newly created NGinX pod.
Conclusion#
This concludes the series of posts on
Installing Kubernetes on bare metal
Configuring BGP networking for Kubernetes
Configuring Cilium as the CNI and the Load Balancer using the Gateway API
Enabling Hubble Observability
Installing Longhorn
Enabling Access using the Gateway API
Creating a PersistentVolumeClaim (PVC)
Deploying an NginX pod, Service and Gateway
Deploying custom HTML in the NGinX pod
Destroying and Re-creating the NginX pod, Service and Gateway
Verifying that our custom data persisted the destruction/recreation.
I have tested these steps multiple times (mostly because something didn’t work, and I wanted to start over after fixing whatever mistake).
I hope you will benefit from this series on Kubernetes to set up your own cluster, and further your own knowledge and interest in this topic.
Comments
Comments powered by giscus, use a GitHub account to comment.