From 5430c9ac016c93a869e7a8e9f36cb6497869e0f8 Mon Sep 17 00:00:00 2001 From: jenkins Date: Sat, 22 Aug 2026 22:06:39 -0300 Subject: [PATCH] jellyfin: prepare titan-22 media host --- .../core/node-prefer-noschedule-cronjob.yaml | 7 +- .../core/jellyfin-volume-policy-cronjob.yaml | 67 +++++++++++++++++++ .../longhorn/core/kustomization.yaml | 1 + .../base/priorityclass/kustomization.yaml | 1 + .../modules/base/priorityclass/media.yaml | 8 +++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 infrastructure/longhorn/core/jellyfin-volume-policy-cronjob.yaml create mode 100644 infrastructure/modules/base/priorityclass/media.yaml diff --git a/infrastructure/core/node-prefer-noschedule-cronjob.yaml b/infrastructure/core/node-prefer-noschedule-cronjob.yaml index e9c225c1..3e6c092d 100644 --- a/infrastructure/core/node-prefer-noschedule-cronjob.yaml +++ b/infrastructure/core/node-prefer-noschedule-cronjob.yaml @@ -61,7 +61,12 @@ spec: clear_worker titan-22 amd64 if k get node titan-22 >/dev/null 2>&1; then - k label node titan-22 atlas.bstein.dev/general-compute=last-resort --overwrite=true || true + k label node titan-22 \ + atlas.bstein.dev/general-compute=last-resort \ + atlas.bstein.dev/media-primary=true \ + --overwrite=true || true + # Keep spare capacity available without letting routine pods displace media service. + k taint node titan-22 atlas.bstein.dev/media-primary=true:PreferNoSchedule --overwrite=true || true fi if k get node titan-23 >/dev/null 2>&1; then diff --git a/infrastructure/longhorn/core/jellyfin-volume-policy-cronjob.yaml b/infrastructure/longhorn/core/jellyfin-volume-policy-cronjob.yaml new file mode 100644 index 00000000..25044d44 --- /dev/null +++ b/infrastructure/longhorn/core/jellyfin-volume-policy-cronjob.yaml @@ -0,0 +1,67 @@ +# infrastructure/longhorn/core/jellyfin-volume-policy-cronjob.yaml +apiVersion: batch/v1 +kind: CronJob +metadata: + name: jellyfin-volume-policy + namespace: longhorn-system +spec: + schedule: "* * * * *" + concurrencyPolicy: Forbid + startingDeadlineSeconds: 30 + successfulJobsHistoryLimit: 1 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + activeDeadlineSeconds: 120 + backoffLimit: 1 + ttlSecondsAfterFinished: 600 + template: + spec: + serviceAccountName: longhorn-service-account + restartPolicy: Never + containers: + - name: ensure + image: bitnami/kubectl@sha256:554ab88b1858e8424c55de37ad417b16f2a0e65d1607aa0f3fe3ce9b9f10b131 + command: + - /usr/bin/env + - bash + - -ceu + - | + ensure_volume() { + local pvc_name="${1}" + local replicas="${2}" + local disk_selector="${3}" + local pv_name + local volume_name + local current_replicas + local current_selector + + pv_name="$(kubectl -n jellyfin get pvc "${pvc_name}" -o jsonpath='{.spec.volumeName}')" + test -n "${pv_name}" + volume_name="$(kubectl get pv "${pv_name}" -o jsonpath='{.spec.csi.volumeHandle}')" + test -n "${volume_name}" + current_replicas="$(kubectl -n longhorn-system get volumes.longhorn.io "${volume_name}" -o jsonpath='{.spec.numberOfReplicas}')" + current_selector="$(kubectl -n longhorn-system get volumes.longhorn.io "${volume_name}" -o jsonpath='{.spec.diskSelector[0]}')" + + if [[ "${current_replicas}" != "${replicas}" || "${current_selector}" != "${disk_selector}" ]]; then + kubectl -n longhorn-system patch volumes.longhorn.io "${volume_name}" \ + --type=merge \ + --patch="{\"spec\":{\"numberOfReplicas\":${replicas},\"diskSelector\":[\"${disk_selector}\"]}}" + else + echo "${pvc_name}: ${replicas} replicas remain on ${disk_selector}" + fi + } + + ensure_volume jellyfin-config-astreae 3 astreae + ensure_volume jellyfin-media-asteria-new 2 asteria + + if kubectl -n longhorn-system get nodes.longhorn.io titan-22 >/dev/null 2>&1; then + allow_scheduling="$(kubectl -n longhorn-system get nodes.longhorn.io titan-22 -o jsonpath='{.spec.allowScheduling}')" + if [[ "${allow_scheduling}" != "false" ]]; then + kubectl -n longhorn-system patch nodes.longhorn.io titan-22 \ + --type=merge \ + --patch='{"spec":{"allowScheduling":false}}' + else + echo "titan-22: Longhorn replica scheduling remains disabled" + fi + fi diff --git a/infrastructure/longhorn/core/kustomization.yaml b/infrastructure/longhorn/core/kustomization.yaml index 1e899d36..8f610d1b 100644 --- a/infrastructure/longhorn/core/kustomization.yaml +++ b/infrastructure/longhorn/core/kustomization.yaml @@ -12,6 +12,7 @@ resources: - longhorn-settings-ensure-job.yaml - longhorn-csi-toleration-ensure-job.yaml - longhorn-disk-tags-ensure-job.yaml + - jellyfin-volume-policy-cronjob.yaml configMapGenerator: - name: longhorn-settings-ensure-script diff --git a/infrastructure/modules/base/priorityclass/kustomization.yaml b/infrastructure/modules/base/priorityclass/kustomization.yaml index a9b27e71..d83776b7 100644 --- a/infrastructure/modules/base/priorityclass/kustomization.yaml +++ b/infrastructure/modules/base/priorityclass/kustomization.yaml @@ -4,4 +4,5 @@ kind: Kustomization resources: - scavenger.yaml - cassandra.yaml + - media.yaml - veles.yaml diff --git a/infrastructure/modules/base/priorityclass/media.yaml b/infrastructure/modules/base/priorityclass/media.yaml new file mode 100644 index 00000000..79c67ac8 --- /dev/null +++ b/infrastructure/modules/base/priorityclass/media.yaml @@ -0,0 +1,8 @@ +# infrastructure/modules/base/priorityclass/media.yaml +apiVersion: scheduling.k8s.io/v1 +kind: PriorityClass +metadata: + name: media-core +value: 400 +globalDefault: false +description: "For interactive media workloads; below stateful database services"