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: replicas: 1 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: - containerPort: 8181 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 port: 8181 targetPort: 8181 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: number: 8181
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: replicas: 1 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: - containerPort: 25 --- kind: Service apiVersion: v1 metadata: name: smtp-service spec: selector: app: smtp ports: - protocol: TCP port: 25 targetPort: 25 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.