We are now at a point where we can build our first application that requires some persistence. We are going to start with Tautulli, an application that provides statistics about your Plex server.
We assume that you only have a single server. The state of kubernetes storage is interesting. The easiest way is to simply pass a host path in to the pod, but that doesn’t work when you have multiple nodes. Incidentally, what I do for my day job (Portworx Cloud Architect) is solving these problems for customers. More on that later.
We first need to specify a location to store configuration data. I will use /opt/plexstack/tautulli as an example.
mkdir -p /opt/plexstack/tautulli
Next, let’s take a look at the manifest to install tautulli:
apiVersion apps/v1
kind Deployment
metadata
name tautulli-deployment
labels
app tautulli
spec
replicas1
selector
matchLabels
app tautulli
template
metadata
labels
app tautulli
spec
containers
name tautulli
image ghcr.io/linuxserver/tautulli
env
name PUID
value"999"
name PGID
value"999"
name TZ
value"America/Los_Angeles"
ports
containerPort8181
volumeMounts
mountPath /config
name tautulli-config
volumes
name tautulli-config
hostPath
path /opt/plexstack/tautulli
---
kind Service
apiVersion v1
metadata
name tautulli-service
spec
selector
app tautulli
ports
protocol TCP
port8181
targetPort8181
type LoadBalancer
---
kind Ingress
apiVersion networking.k8s.io/v1
metadata
name ingress-tautulli
namespace plexstack
annotations
cert-manager.io/cluster-issuer letsencrypt-prod
kubernetes.io/ingress.class nginx
spec
tls
hosts
tautulli.ccrow.org
secretName tautulli-tls
rules
host tautulli.ccrow.org
http
paths
path /
pathType Prefix
backend
service
name tautulli-service
port
number8181
There is a lot to unpack here:
- The first section is the deployment. It defines the application that will run. Line 19 specifies the image.
- Lines 21 – 26 are environment variables that configure tautulli
- We can see where we specify the /config directory inside the container to be mapped to a host path (lines 29 – 35).
- The next section is the service, which looks for pods with an app selector of tautulli.
- We are also going to provision a load balancer IP address to help with troubleshooting. This could be changed to ClusterIP to be internal only. After all, why go to an ip address when we can use an ingress.
- Tautulli.ccrow.org must resolve to our rancher node through the firewall (a step we already did in the last blog.
Let’s apply the manifest with:
# create the namespace
kubectl create namespace plexstack
# apply the manifest
kubectl -n plexstack apply -f tautulli.yaml
# check on the deployment
kubectl -n plexstack get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/tautulli-deployment-b4d5485df-f28px 1/1 Running 0 45s 10.42.2.30 rke04 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/tautulli-service LoadBalancer 10.43.36.8 10.0.1.55 8181:31154/TCP 45s app=tautulli
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/tautulli-deployment 1/1 1 1 45s tautulli ghcr.io/linuxserver/tautulli app=tautulli
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/tautulli-deployment-b4d5485df 1 1 1 45s tautulli ghcr.io/linuxserver/tautulli app=tautulli,pod-template-hash=b4d5485df
Notice the external IP address that was created for the tautulli-service. You can connect to the app from that IP (be sure to add the 8181 port!) instead of the DNS name.
All configuration data will be stored under /opt/plexstack/tautulli on your node.
Bonus Appplication: smtp
In order for tautulli to send email, we need to set up an SMTP server. This will really show off the power of kubernetes configurations. Take a look at this manifest:
---
apiVersion apps/v1
kind Deployment
metadata
name smtp-deployment
labels
app smtp
spec
replicas1
selector
matchLabels
app smtp
template
metadata
labels
app smtp
spec
containers
name smtp
image pure/smtp-relay
env
name SMTP_HOSTNAME
value"mail.ccrow.org"
name RELAY_NETWORKS
value"10.0.0.0/8"
ports
containerPort25
---
kind Service
apiVersion v1
metadata
name smtp-service
spec
selector
app smtp
ports
protocol TCP
port25
targetPort25
type ClusterIP
You can apply the above manifest. Be sure to change lines 24 and 26 to match your network. Please note: “Your network” really means your internal kubernetes network. After all, why would we send an email from an external source (well, unless you want to, in which case, change line 41 to loadBalancer).
kubectl -n plexstack apply -f smtp.yaml
We now have a working SMTP server! The coolest part of kubernetes service discovery is being able to simply use the name of our service for any application in the same namespace:

Using the service name means that this configuration is portable, no need to actually plug in the cluster IP address that was assigned.