Plex deployment on K3s
Preface
Historically I used xbmc/kodi, LibreELEC, OpenELEC for years on different media boxes, then several years ago (when Docker became popular) I’ve discovered that Plex can be run as container so I’ve switched to it. Then my journey with Kubernetes has started and natural movement was to move Plex inside Kubernetes cluster.
Important moments
To run Plex as container the following things should be addressed:
- you have to have at least free Plex account to generate plex_claim. It is used to view and manage apps, servers, and other tools that are linked to it.
- media data (movies, tv shows, music, pictures and so on) should be accessible for Plex container as folder from local file system
- Plex configuration/library data should be stored on persistent volume to have ability to make backups and possible migrations in future
- default network port for Plex is 32400, but it can be exposed as any other (tcp/80) for instance. There are more ports which can be configured but it depends on specific functionality which you plan to switch on Plex.
- it’s better to have Plex running on its own ip-address (with a help of LoadBalancer) in that case it will be easier to make it discoverable on local network (for AppleTV Plex client for instance)
Prerequisites for Plex in K3s
- PLEX_CLAIM - the claim token for the server to obtain a real server token. If not provided, server will not be automatically logged in. If server is already logged in, this parameter is ignored. You can obtain a claim token to login your server to your Plex account by visiting https://www.plex.tv/claim
- media data as local directory should be mounted on all k3s-nodes
- metallb as LoadBalancer should be ready to provide ip-address for plex
- nfs-subdir-external-provisioner should be installed and configured as Plex config/library will be stored on nfs persistent volume
Installation
-
Media data Make sure that media data folder is added into /etc/fstab on each k3s node and mounted as local folder (in example below /mnt/data is used for that)
- Create namespace
kubectl create namespace plex
- Create persistent volume for Plex Media (data)
cat > plex-data-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: plex-data-pv
spec:
capacity:
storage: 1Ti
accessModes:
- ReadOnlyMany
hostPath:
path: /mnt/data
kubectl apply -f plex-data-pv.yaml
- Create persistent volume claim for Plex Media (data)
cat > plex-data-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: plex
name: plex-data-pvc
spec:
accessModes:
- ReadOnlyMany
volumeName: plex-data-pv
resources:
requests:
storage: 1Ti
storageClassName: ""
- Create persistent volume claim for Plex Library (config)
cat > plex-config-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: "plex"
name: "plex-config-pvc"
annotations:
volume.beta.kubernetes.io/storage-class: nfs-client
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "10Gi"
- Add k8s-at-home helm repo
helm repo add k8s-at-home https://k8s-at-home.com/charts/
- Prepare values-file Go to https://www.plex.tv/claim to get generated PLEX_CLAIM and then prepare values-file.
cat > plex-values.yaml
image:
repository: linuxserver/plex
tag: latest
pullPolicy: IfNotPresent
env:
PLEX_CLAIM: "claim-ne3xhadLMsxRpy4567890"
TZ: "Europe/Vilnius"
service:
type: LoadBalancer
annotations:
# if multiple ports are used, all of them will be used on one ip-address that to that
metallb.universe.tf/allow-shared-ip: plex-svc
port:
port: 80
targetPort: 32400
persistence:
data:
enabled: true
existingClaim: "plex-data-pvc"
config:
enabled: true
existingClaim: "plex-config-pvc"
# Enable devices to be discoverable
hostNetwork: true
resources: {}
podAnnotations: {}
proxy:
enable: false
- Install Plex helm chart based on values-file
helm install plex --values plex-values.yml -n plex k8s-at-home/plex
How to migrate Plex Library
If you had Plex Library before and want to migrate it to new new cluster/container, just install new Plex, wait until it’s started and then stop it
kubectl scale --replicas=0 deployment/plex -n plex
deployment.apps/plex scaled
Check what user:group is used for Library in new container (use it in next step)
ls -l /mnt/kubcluster/plex-plex-config-pvc-pvc-53abef0c-2b2d-461d-9a81-eb64034ac111/
total 12
drwxr-xr-x 4 911 911 4096 Jan 17 20:28 Library
Replace new Library by old one and change ownership recursively there
rm -rf /mnt/kubcluster/plex-plex-config-pvc-pvc-53abef0c-2b2d-461d-9a81-eb64034ac111/Library
mv /mnt/kubcluster/old-plex/Library /mnt/kubcluster/plex-plex-config-pvc-pvc-53abef0c-2b2d-461d-9a81-eb64034ac111/
cd /mnt/kubcluster/plex-plex-config-pvc-pvc-53abef0c-2b2d-461d-9a81-eb64034ac111
chown -R 911:911 Library
Start Plex container back
kubectl scale --replicas=1 deployment/plex -n plex
deployment.apps/plex scaled