Installation de Immich
- Ajout du helm :
immich-repo oci oci://ghcr.io/immich-app/immich-charts/immich - Création du Projet Immich et du namespace immich
- Affectation du PV : Nouveau PVC, taille 200G (la taille est extensible avec Longhorn) : pv-immich-data-claim
Création du service
- Création d'un service Headless dans Services Discovery / Services immich-db
- port name : postgre
- port : 5432
- Modifier le service en IPv4 : Éditer le YAML
spec:
clusterIP: None
ipFamilyPolicy: SingleStack
ipFamilies:
- IPv4
Note
On reviendra après pour définir le pod utilisant ce service
Création d'un secret
Storage -> Secret -> Create -> Opaque
- DB_DATABASE_NAME
- DB_HOSTNAME
- DB_PASSWORD
- DB_USERNAME
- POSTGRES_DB
- POSTGRES_PASSWORD
- POSTGRES_USER
Base de données
- Nouveau StateFullSet (pour des bases de données et pas Deployment).
- Choisir l'image
ghcr.io/tensorchord/cloudnative-vectorchord:17.5-0.4.3car immich-server ne supporte pas les dernières versions vector. - Créer dans le pod le pv-immich-pgsql-claim et l'attribuer à
/var/lib/postgresql/datadans le set. - Ajouter le Secret dans l'environment, et détail qui a son importance les variables
PGDATA:/var/lib/postgresql/data/pgdataPOSTGRES_INITDB_ARGS:"-c shared_preload_libraries=vchord"
- Créer le config map suivant pour l'init de la db :
apiVersion: v1
kind: ConfigMap
metadata:
name: immich-postgres-init
namespace: immich
data:
init.sql: |
CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
CREATE EXTENSION IF NOT EXISTS earthdistance CASCADE;
- Ajouter cette config map dans le pod
- Chose qui ne m'était pas encore arrivé, le pod n'avait pas les droits root, donc impossible d'écrire sur son volume, il a fallu rajouter le groupe 999 au contexte de sécurité du pod ET du set.
Attribution du service
- Dans les paramètres du pod dans le StateFullSet, ajouter un Label
[app:pgsql] - Dans les paramètres du service, ajouter le même Label
Installation du chart
Enfin... :p Enfin, il va surtout falloir configurer avant d'utiliser
Middleware Traefik
Note
On va se passer complétement de cette couche d'ingress, trop d'instabilités avec le reverse Ce chart est prévu pour un Ingress nginx, chose qui n'est plus supporté dans quelques mois, on va donc créer un middleware Traefik pour permettre de ne pas couper les upload de videos On va ajouter ce middleware avec upload YAML
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: immich-buffering
namespace: immich
spec:
buffering:
maxRequestBodyBytes: 0
Créer également le transport pour le timeout :
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
name: immich-transport
namespace: immich
spec:
serverName: ""
insecureSkipVerify: false
rootCAs: []
maxIdleConnsPerHost: 200
forwardingTimeouts:
dialTimeout: 30s
responseHeaderTimeout: 3600s
idleConnTimeout: 3600s
Adaptation du reverse proxy
Ici, on va différencier les WebSocket (utilisé par les uploads) et le http conventionnel.
# ------------------------------------------------------------
# Immich
# ------------------------------------------------------------
https://immich.dsvs.ddns.net {
# Compression (sauf WebSocket)
encode gzip
# Configuration spéciale pour WebSocket
@websocket {
header Connection *Upgrade*
header Upgrade websocket
}
# Route WebSocket (sans buffering ni timeout court)
reverse_proxy @websocket http://192.168.1.150:32283 http://192.168.1.151:32283 http://192.168.1.152:32283 {
transport http {
read_timeout 0 # Pas de timeout pour WebSocket
write_timeout 0
dial_timeout 30s
keepalive 0 # Pas de keepalive pour WS
}
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
flush_interval -1
}
# Route normale pour HTTP (uploads, etc.)
reverse_proxy http://192.168.1.150:32283 http://192.168.1.151:32283 http://192.168.1.152:32283 {
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
}
}
Immich App
- Apps -> Charts -> Immich, Install et bien cocher Customize
- Ajouter les secrets dans env :
env:
IMMICH_MACHINE_LEARNING_URL: '{{ printf "http://%s-machine-learning:3003" .Release.Name }}'
REDIS_HOSTNAME: '{{ printf "%s-valkey" .Release.Name }}'
image:
tag: v2.0.0
envFrom:
- secretRef:
name: immich-secret
- Ajouter le pv dans la section persistance :
immich:
configuration: {}
metrics:
enabled: false
persistence:
library:
existingClaim: pv-immich-data-claim
- Modifier l'Ingress et prendre en compte le middleware
Note
⚠️⚠️ On va se passer complétement de cette couche d'ingress, trop d'instabilités avec le reverse + ⚠️⚠️
ingress:
main:
enabled: true
hosts:
- host: immich.dsvs.ddns.net
paths:
- path: /
service:
identifier: main
tls: []
annotations:
traefik.ingress.kubernetes.io/router.middlewares: immich-immich-buffering@kubernetescrd
traefik.ingress.kubernetes.io/service.serverstransport: immich-immich-transport@kubernetescrd
Note
Voici le Node port retenu
ingress:
main:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: null
enabled: false
hosts: null
tls: []
service:
main:
ports:
http:
nodePort: 32283
port: 2283
protocol: TCP
type: NodePort
- Un peu bête mais le valkey n'était pas enabled, changer a
true
Divers
Pour éviter trop de redémarrages j'ai allongé la durée du ping check sur les Deployments Dans la section server : main :
probes:
liveness:
enabled: true
custom: true
spec:
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 60
periodSeconds: 60
timeoutSeconds: 10
failureThreshold: 5
readiness:
enabled: true
custom: true
spec:
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
Tip
Config définitive de l'app
controllers:
main:
containers:
main:
env:
IMMICH_MACHINE_LEARNING_URL: '{{ printf "http://%s-machine-learning:3003" .Release.Name }}'
REDIS_HOSTNAME: '{{ printf "%s-valkey" .Release.Name }}'
image:
tag: v2.0.0
envFrom:
- secretRef:
name: immich-secret
immich:
configuration: {}
metrics:
enabled: false
persistence:
library:
existingClaim: pv-immich-data-claim
machine-learning:
controllers:
main:
containers:
main:
env:
HF_XET_CACHE: /cache/huggingface-xet
MPLCONFIGDIR: /cache/matplotlib-config
TRANSFORMERS_CACHE: /cache
image:
pullPolicy: IfNotPresent
repository: ghcr.io/immich-app/immich-machine-learning
enabled: true
persistence:
cache:
accessMode: ReadWriteMany
enabled: true
size: 10Gi
type: emptyDir
server:
controllers:
main:
containers:
main:
image:
pullPolicy: IfNotPresent
repository: ghcr.io/immich-app/immich-server
probes:
liveness:
custom: true
enabled: true
spec:
failureThreshold: 5
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 60
periodSeconds: 60
timeoutSeconds: 10
readiness:
custom: true
enabled: true
spec:
failureThreshold: 5
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 10
enabled: true
ingress:
main:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: null
enabled: false
hosts: null
tls: []
service:
main:
ports:
http:
nodePort: 32283
port: 2283
protocol: TCP
type: NodePort
valkey:
controllers:
main:
containers:
main:
image:
pullPolicy: IfNotPresent
repository: docker.io/valkey/valkey
tag: >-
9.0-alpine@sha256:b4ee67d73e00393e712accc72cfd7003b87d0fcd63f0eba798b23251bfc9c394
enabled: true
persistence:
data:
accessMode: ReadWriteOnce
enabled: true
size: 1Gi
type: emptyDir
global:
cattle:
systemProjectId: p-vtsj2