feat(k8s): déployer Open WebUI + n8n sur namespace ai via ArgoCD

Open WebUI (openwebui.lab.local) :
- Connecté à LiteLLM (192.168.10.1:4000/v1) comme backend OpenAI-compatible
- PostgreSQL via storage-01 pour l'historique des conversations
- PVC 5Gi NFS pour les uploads, Traefik IngressRoute

n8n (n8n.lab.local) :
- PostgreSQL via storage-01, chiffrement des credentials
- PVC 2Gi NFS, Traefik IngressRoute
- Webhook URL interne : http://n8n.lab.local

Ansible : ajoute openwebui et n8n dans postgresql_databases/users
(vault_pg_openwebui_password + vault_pg_n8n_password à ajouter au vault)

Prérequis avant 1er déploiement :
  make vault-edit   # ajouter les 2 passwords
  make apply-storage --tags postgresql
  kubectl create secret generic open-webui-secret -n ai ...
  kubectl create secret generic n8n-secret -n ai ...

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
alkatrazz 2026-05-29 15:08:41 +02:00
parent 3cd374630d
commit bc137d13b4
11 changed files with 285 additions and 1 deletions

View file

@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: n8n
namespace: ai
spec:
replicas: 1
selector:
matchLabels:
app: n8n
template:
metadata:
labels:
app: n8n
spec:
containers:
- name: n8n
image: n8nio/n8n:latest
ports:
- containerPort: 5678
env:
# PostgreSQL
- name: DB_TYPE
value: "postgresdb"
- name: DB_POSTGRESDB_HOST
value: "192.168.10.1"
- name: DB_POSTGRESDB_PORT
value: "5432"
- name: DB_POSTGRESDB_DATABASE
value: "n8n"
- name: DB_POSTGRESDB_USER
value: "n8n"
- name: DB_POSTGRESDB_PASSWORD
valueFrom:
secretKeyRef:
name: n8n-secret
key: db-password
# Clé de chiffrement des credentials
- name: N8N_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: n8n-secret
key: encryption-key
# URLs
- name: N8N_HOST
value: "0.0.0.0"
- name: N8N_PORT
value: "5678"
- name: N8N_PROTOCOL
value: "http"
- name: WEBHOOK_URL
value: "http://n8n.lab.local"
- name: N8N_EDITOR_BASE_URL
value: "http://n8n.lab.local"
# Timezone
- name: GENERIC_TIMEZONE
value: "Europe/Paris"
- name: TZ
value: "Europe/Paris"
# Désactiver la télémétrie
- name: N8N_DIAGNOSTICS_ENABLED
value: "false"
volumeMounts:
- name: data
mountPath: /home/node/.n8n
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
readinessProbe:
httpGet:
path: /healthz
port: 5678
initialDelaySeconds: 20
periodSeconds: 10
volumes:
- name: data
persistentVolumeClaim:
claimName: n8n-data

14
k8s/apps/n8n/ingress.yaml Normal file
View file

@ -0,0 +1,14 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: n8n
namespace: ai
spec:
entryPoints:
- web
routes:
- match: Host(`n8n.lab.local`)
kind: Rule
services:
- name: n8n
port: 5678

12
k8s/apps/n8n/pvc.yaml Normal file
View file

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: n8n-data
namespace: ai
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs
resources:
requests:
storage: 2Gi

11
k8s/apps/n8n/service.yaml Normal file
View file

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: n8n
namespace: ai
spec:
selector:
app: n8n
ports:
- port: 5678
targetPort: 5678

View file

@ -0,0 +1,71 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: open-webui
namespace: ai
spec:
replicas: 1
selector:
matchLabels:
app: open-webui
template:
metadata:
labels:
app: open-webui
spec:
containers:
- name: open-webui
image: ghcr.io/open-webui/open-webui:latest
ports:
- containerPort: 8080
env:
# LiteLLM comme backend OpenAI-compatible
- name: OPENAI_API_BASE_URL
value: "http://192.168.10.1:4000/v1"
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: open-webui-secret
key: litellm-api-key
# PostgreSQL — migrations automatiques au démarrage
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: open-webui-secret
key: database-url
# Clé de session
- name: WEBUI_SECRET_KEY
valueFrom:
secretKeyRef:
name: open-webui-secret
key: webui-secret-key
# Désactiver Ollama (on passe par LiteLLM)
- name: ENABLE_OLLAMA_API
value: "false"
- name: OLLAMA_BASE_URL
value: ""
# Nom affiché dans l'interface
- name: WEBUI_NAME
value: "Funk AI"
- name: DEFAULT_LOCALE
value: "fr-FR"
volumeMounts:
- name: data
mountPath: /app/backend/data
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
volumes:
- name: data
persistentVolumeClaim:
claimName: open-webui-data

View file

@ -0,0 +1,14 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: open-webui
namespace: ai
spec:
entryPoints:
- web
routes:
- match: Host(`openwebui.lab.local`)
kind: Rule
services:
- name: open-webui
port: 8080

View file

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: open-webui-data
namespace: ai
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs
resources:
requests:
storage: 5Gi

View file

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: open-webui
namespace: ai
spec:
selector:
app: open-webui
ports:
- port: 8080
targetPort: 8080