74 lines
3.4 KiB
Markdown
74 lines
3.4 KiB
Markdown
# Plex on Kubernetes
|
|
|
|
This project runs the existing Plex server as a single high-performance Pod on
|
|
`arschrock` in its dedicated `plex` namespace. It is intentionally not highly
|
|
available and can never fail over to an ODROID. CPU and memory have scheduling
|
|
requests but no limits.
|
|
|
|
The 500 TB media tree stays on the host and is mounted read-only from
|
|
`/komposthaufen/multimedia`. The Pod also requires the existing `Videos`
|
|
directory and an init container verifies that the path is backed by bcachefs.
|
|
If the encrypted filesystem has not been unlocked and mounted, Plex does not
|
|
start. The Deployment also requires the explicit
|
|
`media.brunner.ninja/multimedia-ready=true` node label. The shared
|
|
`../media-storage-offline.sh` helper removes it and stops the media Pods before
|
|
unmounting; `../media-storage-online.sh` validates the mount before restoring
|
|
the label.
|
|
|
|
Persistent Plex configuration, metadata, preview images, and SQLite databases
|
|
live on the retained 160 GiB `plex-config` RBD PVC. Transcodes use node-local
|
|
ephemeral storage. The official Plex image is pinned to the same version as the
|
|
migrated Arch installation.
|
|
|
|
## One-time migration
|
|
|
|
`migrate.sh` stops the Arch service, confirms no Plex process remains, checks
|
|
both source SQLite databases, creates the PVC, and starts a one-shot copy Job:
|
|
|
|
```sh
|
|
./migrate.sh
|
|
kubectl -n plex logs -f job/plex-archlinux-migration
|
|
kubectl -n plex wait --for=condition=complete \
|
|
job/plex-archlinux-migration --timeout=12h
|
|
```
|
|
|
|
The Job refuses to overwrite a non-empty destination and compares regular-file
|
|
counts and byte totals before writing its completion marker. Copy I/O is
|
|
deliberately duty-cycle throttled so the migration cannot monopolize bcachefs
|
|
and Ceph. Do not delete the source `/var/lib/plex` tree until the Kubernetes
|
|
server has been verified and a separate backup exists.
|
|
|
|
The historical migration scripts remain for recovery; routine deployment is
|
|
owned by Argo CD. Plex remains available at
|
|
`https://plex.brunner.ninja` and directly on `192.168.0.2:32400`.
|
|
|
|
## Monitoring
|
|
|
|
The Pod contains a rootless Plex exporter. Its token is read from the migrated
|
|
`Preferences.xml` into a memory-backed volume; it is not duplicated in a
|
|
Kubernetes Secret or environment variable. A `ServiceMonitor` and alerts cover
|
|
the exporter, Plex API access, restart loops, and PVC capacity. Existing
|
|
Tautulli, node-exporter, Netdata, SMART, and bcachefs monitoring remain in use.
|
|
|
|
## Helm and GitOps
|
|
|
|
This repository owns the Plex chart: Deployment, Service, media guard,
|
|
exporter, ingress option, and monitoring. The chart preserves the existing
|
|
Deployment selector used by `media-storage-offline.sh` and
|
|
`media-storage-online.sh`. The homelab's node pin, guarded hostPath, existing
|
|
PVC, public host and resource requests are selected in the
|
|
[GitOps values](https://code.brunner.ninja/feedc0de/homelab-gitops/src/branch/main/apps/plex).
|
|
|
|
```sh
|
|
helm repo add brunner.ninja https://brunner.ninja/charts
|
|
helm repo update brunner.ninja
|
|
helm upgrade --install plex brunner.ninja/plex --namespace plex --create-namespace
|
|
```
|
|
|
|
To install this checkout manually, run `./install.sh -f my-values.yaml` with
|
|
the target namespace and media mount configured. Main-branch CI validates,
|
|
publishes the chart using the upstream application Git tag plus `git describe`,
|
|
then promotes its exact version to GitOps. CI needs `PACKAGE_USERNAME`,
|
|
`PACKAGE_TOKEN`, and `GITOPS_TOKEN`, but no kubeconfig. The Plex image is the
|
|
official upstream image and is selected by `Chart.yaml.appVersion`.
|