blob: ead3efe2de9062207e79facc9e6bfae3c21ee203 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
# shuriken: nightly regeneration of the irregular.ninja and alt.irregular.ninja
# static photo albums. The container entrypoint runs `shuriken --generate
# --config <conf>` once per /configs/*.conf (alphabetical), writing each site
# into /data/shuriken.sh/<site>/dist on the shared NFS export.
#
# Design:
# - concurrencyPolicy: Forbid -- a long generate run (large photo library,
# single image job) must not stack a second worker on top of it; shuriken's
# staging directories would race and the NFS write load would double.
# - backoffLimit: 0 -- a failed nightly run surfaces in the Job history and
# gets retried by the next night's schedule; spamming retries would just
# re-burn ImageMagick CPU on a persistent failure (e.g. NFS down).
# - activeDeadlineSeconds: 6h -- caps a runaway first-run backfill of a large
# library; steady state is far shorter.
# - runAsUser: 0 -- the syncthing source tree is mode 750 root:wheel on the
# NFS server, and the dist output is written as root to match the existing
# irregular.ninja layout.
# - Single image job by default (entrypoint --image-jobs 1); raise via the
# SHURIKEN_IMAGE_JOBS env if a faster one-off run is needed.
apiVersion: batch/v1
kind: CronJob
metadata:
name: shuriken
namespace: services
spec:
# 04:00 local daily -- off-peak, and doesn't collide with the beets-art
# noon sweep. timeZone is GA in k8s 1.27+; k3s 1.32 supports it.
schedule: "0 4 * * *"
timeZone: Europe/Sofia
concurrencyPolicy: Forbid
startingDeadlineSeconds: 300
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 0
activeDeadlineSeconds: 21600
template:
spec:
restartPolicy: Never
initContainers:
- name: nfs-check
image: busybox:stable
command:
- sh
- -c
- |
test -f /mnt/shuriken.sh/.nfs-sentinel || (
echo "ERROR: NFS sentinel missing at /mnt/shuriken.sh/.nfs-sentinel"
echo "refusing to start; node likely has NFS unmounted"
echo "pod would otherwise write into a stale local-XFS shadow"
exit 1
)
volumeMounts:
- name: data
mountPath: /mnt
readOnly: true
containers:
- name: shuriken
image: registry.lan.buetow.org:30001/shuriken:0.13.2
imagePullPolicy: Always
command: ["/bin/sh", "-c"]
args:
- |
set -e
# Hold the generation/sync mutex for the WHOLE multi-site run
# so the shuriken-sync CronJob can't publish mid-generation
# (and vice versa). flock auto-releases if the pod dies, so a
# crash never leaves a stale lock. Blocking acquire: if a sync
# is mid-publish, wait for it (it's short) then generate.
exec flock /data/shuriken.sh/.lock shuriken-entrypoint
env:
# Default 1 image job (single-threaded); override here if a
# faster one-off run is acceptable. The entrypoint passes this
# to shuriken as --image-jobs.
- name: SHURIKEN_IMAGE_JOBS
value: "1"
# ImageMagick 7 is Q16-HDRI and built with OpenMP. Pin OpenMP
# to a single thread: the pod is cpu-limited to 1 core anyway,
# and extra resample threads would only multiply the HDRI pixel
# buffer's memory pressure (the OOM trigger for large PNGs).
- name: OMP_NUM_THREADS
value: "1"
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
# 2 Gi: the ImageMagick policy (baked into the image) caps
# the in-RAM pixel cache at 512 MiB and spills oversized
# decodes to the /tmp disk cache, so this headroom covers the
# working set + bash + the HDRI buffers of one photo without
# the pod being OOM-killed on a multi-megapixel source image.
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
volumeMounts:
- name: data
mountPath: /data
- name: configs
mountPath: /configs
readOnly: true
- name: tmp
mountPath: /tmp
volumes:
- name: data
persistentVolumeClaim:
claimName: shuriken-data-pvc
- name: configs
configMap:
name: shuriken-config
# Disk-backed scratch for ImageMagick's disk pixel cache (the
# policy spills oversized HDRI decodes here instead of OOMing).
- name: tmp
emptyDir:
sizeLimit: 8Gi
|