ci / lint-compose (push) Successful in 4s
ci / lint-actionlint (push) Successful in 1s
ci / lint-shellcheck (push) Successful in 3s
ci / lint-prettier (push) Failing after 4s
ci / lint-ruff (push) Successful in 3s
ci / lint-yaml (push) Successful in 3s
ci / lint-dockerfiles (push) Successful in 2s
ci / scan-deps (push) Successful in 20s
ci / test-backend (push) Successful in 8s
ci / test-frontend (push) Successful in 14s
ci / validate (push) Successful in 3s
ci / build (push) Skipped
renovate-ci / validate-renovate (push) Successful in 11s
Server x2, machine learning, valkey and VectorChord postgres on local storage, Traefik routes for external and internal access.
139 lines
5.2 KiB
YAML
139 lines
5.2 KiB
YAML
# Immich's own database, separate from the shared postgres in the database
|
|
# namespace. It has to be separate: v3 checks the VectorChord version at startup
|
|
# and refuses to boot without it, VectorChord needs its .so in
|
|
# shared_preload_libraries, and that can only be read when postmaster starts.
|
|
# So the shared instance would have to be rebuilt on a custom image carrying
|
|
# vchord and restarted - for every consumer of it (authentik, gitea, netbox,
|
|
# netronome, penpot, statuspage). Not worth it for one photo library.
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: immich-postgres
|
|
namespace: immich
|
|
labels:
|
|
app: immich-postgres
|
|
spec:
|
|
selector:
|
|
app: immich-postgres
|
|
ports:
|
|
- name: postgres
|
|
port: 5432
|
|
targetPort: postgres
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: immich-postgres
|
|
namespace: immich
|
|
labels:
|
|
app: immich-postgres
|
|
spec:
|
|
serviceName: immich-postgres
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: immich-postgres
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: immich-postgres
|
|
spec:
|
|
containers:
|
|
- name: postgres
|
|
# v3.x expects vchord for its vector work and vectors (pgvecto.rs)
|
|
# for some index types. This image ships both and preloads them, plus
|
|
# its own shared_buffers and wal settings, through
|
|
# /etc/postgresql/postgresql.conf - which its entrypoint reaches via
|
|
# `postgres -c config_file=...` in the image CMD.
|
|
#
|
|
# So there is deliberately no `command:` here. Overriding it replaces
|
|
# that config_file, and it also loses the step where the entrypoint
|
|
# drops from root to the postgres user: postmaster then starts as
|
|
# root and refuses to run.
|
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
|
|
env:
|
|
- name: POSTGRES_USER
|
|
value: immich
|
|
- name: POSTGRES_DB
|
|
value: immich
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: immich-secrets
|
|
key: DB_PASSWORD
|
|
# Only read when the data directory is empty, so the checksums are
|
|
# decided here and never again.
|
|
- name: POSTGRES_INITDB_ARGS
|
|
value: --data-checksums
|
|
# The postgres-data volume lives on sdc, which is rotational. The
|
|
# SSD template is the default; HDD only changes the planner costs
|
|
# (effective_io_concurrency, random_page_cost), nothing structural.
|
|
- name: DB_STORAGE_TYPE
|
|
value: HDD
|
|
- name: TZ
|
|
valueFrom:
|
|
configMapKeyRef:
|
|
name: immich-config
|
|
key: TZ
|
|
ports:
|
|
- name: postgres
|
|
containerPort: 5432
|
|
volumeMounts:
|
|
- name: postgres-data
|
|
mountPath: /var/lib/postgresql/data
|
|
# The upstream compose file asks docker for 128mb of shm. Kubernetes
|
|
# gives every container 64mb, which is not what postmaster expects
|
|
# for parallel query workers and the WAL writer.
|
|
- name: shm
|
|
mountPath: /dev/shm
|
|
# Probes use a generous timeout on purpose: the data lives on a
|
|
# rotational disk on a loaded single node, and pg_isready can take
|
|
# seconds during WAL recovery. A 1s timeout kills the container
|
|
# mid-recovery and restarts the spiral.
|
|
startupProbe:
|
|
exec:
|
|
command: ["sh", "-c", "pg_isready -U immich -d immich"]
|
|
failureThreshold: 60
|
|
periodSeconds: 5
|
|
timeoutSeconds: 5
|
|
readinessProbe:
|
|
exec:
|
|
command: ["sh", "-c", "pg_isready -U immich -d immich"]
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
livenessProbe:
|
|
exec:
|
|
command: ["sh", "-c", "pg_isready -U immich -d immich"]
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 20
|
|
timeoutSeconds: 5
|
|
# The image template sets shared_buffers to 512MB, and the vchord and
|
|
# vectors workers are Rust binaries with a real RSS footprint on top
|
|
# of postmaster, checkpointer and friends. 1Gi was enough to start
|
|
# the server but the vectors worker kept dying in it, so the limit
|
|
# sits at 2Gi. The request stays at the idle cost.
|
|
resources:
|
|
requests:
|
|
cpu: "50m"
|
|
memory: "256Mi"
|
|
limits:
|
|
cpu: "1000m"
|
|
memory: "2Gi"
|
|
volumes:
|
|
- name: shm
|
|
emptyDir:
|
|
medium: Memory
|
|
sizeLimit: 128Mi
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: postgres-data
|
|
spec:
|
|
accessModes: ["ReadWriteOnce"]
|
|
# Retain: this is the metadata for a library that only exists in one
|
|
# place, and local-path cannot expand a bound volume, so this size has
|
|
# to hold until the library is rebuilt or dumped elsewhere.
|
|
storageClassName: local-path-retain
|
|
resources:
|
|
requests:
|
|
storage: 32Gi
|