immich mergerfs
This commit is contained in:
@@ -13,6 +13,66 @@ spec:
|
||||
values:
|
||||
controllers:
|
||||
server:
|
||||
strategy: Recreate
|
||||
podDisruptionBudget:
|
||||
maxUnavailable: "0"
|
||||
initContainers:
|
||||
fix-permissions:
|
||||
image:
|
||||
repository: hectorm/nfs-ganesha
|
||||
tag: v10
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- chmod -R a+rwX /disks/library-recent /disks/library-archive
|
||||
# native sidecar (restartPolicy: Always): mounts the two library
|
||||
# disks and exposes their union at /disks/merged-library via
|
||||
# FUSE. It must be up and actually mounted *before* the "app"
|
||||
# container is created, since HostToContainer propagation only
|
||||
# relays mounts made *after* the receiving container's own mount
|
||||
# exists - it won't retroactively pick up a FUSE mount that's
|
||||
# already there. Running it as a restartPolicy:Always init
|
||||
# container (started, gated on the startupProbe below, before
|
||||
# regular containers) guarantees that ordering; a regular sidecar
|
||||
# container racing "app" on every pod start does not. Same
|
||||
# pattern as clusters/base/apps/nfs-photo.
|
||||
mergerfs:
|
||||
dependsOn:
|
||||
- fix-permissions
|
||||
restartPolicy: Always
|
||||
image:
|
||||
repository: ghcr.io/hotio/mergerfs
|
||||
tag: release-v2.42.0
|
||||
args:
|
||||
- "-o"
|
||||
# library-recent listed first: category.create=ff means new
|
||||
# files created through the merged mount (i.e. new immich
|
||||
# uploads going forward) land on library-recent by default,
|
||||
# which is exactly what's wanted for freshly-uploaded photos.
|
||||
- "allow_other,use_ino,func.create=ff,category.action=all,category.create=ff,category.search=newest"
|
||||
- "/disks/library-recent:/disks/library-archive"
|
||||
- "/disks/merged-library"
|
||||
securityContext:
|
||||
privileged: true
|
||||
probes:
|
||||
startup:
|
||||
enabled: true
|
||||
custom: true
|
||||
spec:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- grep -q fuse.mergerfs /proc/mounts
|
||||
periodSeconds: 1
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 30
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
memory: 512Mi
|
||||
containers:
|
||||
app:
|
||||
image:
|
||||
@@ -54,10 +114,12 @@ spec:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
# one-shot migration copy from the old NAS-hosted docker install
|
||||
# into this install's own library volume (see "library" below).
|
||||
# into this install's own volumes (see "persistence" below).
|
||||
# rsync is idempotent, so a pod restart mid-copy just resumes
|
||||
# cleanly; once done it sleeps forever instead of exiting, so the
|
||||
# container doesn't restart-loop and the status page stays up.
|
||||
# (starts after all initContainers - fix-permissions and the
|
||||
# mergerfs sidecar's startupProbe - complete, same as "app")
|
||||
rsync:
|
||||
image:
|
||||
repository: python
|
||||
@@ -68,10 +130,10 @@ spec:
|
||||
- apk add --no-cache rsync >/dev/null && python3 /app/rsync.py
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
memory: 1Gi
|
||||
rsync-web:
|
||||
image:
|
||||
repository: nginx
|
||||
@@ -141,16 +203,71 @@ spec:
|
||||
- rsync.photo.aggtaa.com
|
||||
|
||||
persistence:
|
||||
# brand new, dedicated library - deliberately not reusing the old
|
||||
# docker-compose install's NAS data, and not nfs-photo either.
|
||||
library:
|
||||
# Immich's "library" folder, mergerfs-merged from two disks: recent
|
||||
# files (per the rsync migration's cutoff) and everything else.
|
||||
# New uploads going forward land on library-recent (see mergerfs
|
||||
# category.create above). Not reusing the old single 800Gi library
|
||||
# PVC/PV - this replaces it (that PVC becomes orphaned, retained,
|
||||
# and unused; clean it up separately if no longer wanted).
|
||||
library-recent:
|
||||
type: persistentVolumeClaim
|
||||
accessMode: ReadWriteOnce
|
||||
size: 800Gi
|
||||
size: 200Gi
|
||||
storageClass: longhorn-single-replica
|
||||
retain: true
|
||||
globalMounts:
|
||||
- path: /data
|
||||
advancedMounts:
|
||||
server:
|
||||
mergerfs:
|
||||
- path: /disks/library-recent
|
||||
fix-permissions:
|
||||
- path: /disks/library-recent
|
||||
rsync:
|
||||
- path: /disks/library-recent
|
||||
library-archive:
|
||||
type: persistentVolumeClaim
|
||||
accessMode: ReadWriteOnce
|
||||
size: 500Gi
|
||||
storageClass: longhorn-single-replica
|
||||
retain: true
|
||||
advancedMounts:
|
||||
server:
|
||||
mergerfs:
|
||||
- path: /disks/library-archive
|
||||
fix-permissions:
|
||||
- path: /disks/library-archive
|
||||
rsync:
|
||||
- path: /disks/library-archive
|
||||
merged-library:
|
||||
type: emptyDir
|
||||
advancedMounts:
|
||||
server:
|
||||
mergerfs:
|
||||
- path: /disks/merged-library
|
||||
mountPropagation: Bidirectional
|
||||
app:
|
||||
- path: /data/library
|
||||
mountPropagation: HostToContainer
|
||||
dev-fuse:
|
||||
type: hostPath
|
||||
hostPath: /dev/fuse
|
||||
advancedMounts:
|
||||
server:
|
||||
mergerfs:
|
||||
- path: /dev/fuse
|
||||
# everything immich keeps outside "library" (backups, encoded-video,
|
||||
# profile, thumbs, upload) - plain volume, no mergerfs involved.
|
||||
other:
|
||||
type: persistentVolumeClaim
|
||||
accessMode: ReadWriteOnce
|
||||
size: 100Gi
|
||||
storageClass: longhorn-single-replica
|
||||
retain: true
|
||||
advancedMounts:
|
||||
server:
|
||||
app:
|
||||
- path: /data
|
||||
rsync:
|
||||
- path: /data
|
||||
nas-source:
|
||||
type: persistentVolumeClaim
|
||||
existingClaim: immich-nas-source
|
||||
|
||||
Reference in New Issue
Block a user