66 lines
2.8 KiB
Markdown
66 lines
2.8 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.
|
|
|
|
Deploy with `./install.sh`. 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.
|
|
|
|
## Gitea CI/CD bootstrap
|
|
|
|
After initializing this directory as its own repository and creating the Gitea
|
|
repository, add the remote and perform the first push. Then run:
|
|
|
|
```sh
|
|
./create-ci-kubeconfig.sh
|
|
```
|
|
|
|
Store the single output line as `KUBE_CONFIG_BASE64`. The CI identity can only
|
|
update the already-created Plex resources named in `ci-deployer.yaml`; it
|
|
cannot read Secrets, run migration Jobs, or alter other workloads. Pull
|
|
requests validate, while pushes to `main` validate and deploy the pinned
|
|
upstream images.
|