feat(open-webui): HA deployment with CNPG, PDB, and session persistence
- Switch from SQLite/PVC to CNPG PostgreSQL (3 instances, low-resource) with a transaction-mode PgBouncer pooler (2 instances) - Raise open-webui replicas to 3 with priorityClassName: power - Add PodDisruptionBudget (minAvailable: 1) - Add Gateway API sessionPersistence (cookie) on the HTTPS HTTPRoute so WebSocket connections stick to the same backend pod - Add postgres-credentials VaultStaticSecret; DATABASE_URL must be added to kv/kubernetes/namespace/open-webui/default/open-webui-credentials
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
apiVersion: postgresql.cnpg.io/v1
|
||||||
|
kind: Cluster
|
||||||
|
metadata:
|
||||||
|
name: open-webui-postgres
|
||||||
|
namespace: open-webui
|
||||||
|
spec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinityType: preferred
|
||||||
|
bootstrap:
|
||||||
|
initdb:
|
||||||
|
database: open-webui
|
||||||
|
encoding: UTF8
|
||||||
|
localeCType: C
|
||||||
|
localeCollate: C
|
||||||
|
owner: open-webui
|
||||||
|
secret:
|
||||||
|
name: postgres-credentials
|
||||||
|
enablePDB: true
|
||||||
|
enableSuperuserAccess: false
|
||||||
|
failoverDelay: 0
|
||||||
|
imageName: ghcr.io/cloudnative-pg/postgresql:17-minimal-trixie
|
||||||
|
instances: 3
|
||||||
|
logLevel: info
|
||||||
|
maxSyncReplicas: 0
|
||||||
|
minSyncReplicas: 0
|
||||||
|
monitoring:
|
||||||
|
customQueriesConfigMap:
|
||||||
|
- key: queries
|
||||||
|
name: cnpg-default-monitoring
|
||||||
|
disableDefaultQueries: false
|
||||||
|
enablePodMonitor: false
|
||||||
|
postgresql:
|
||||||
|
parameters:
|
||||||
|
archive_mode: "on"
|
||||||
|
archive_timeout: 5min
|
||||||
|
dynamic_shared_memory_type: posix
|
||||||
|
effective_cache_size: 128MB
|
||||||
|
full_page_writes: "on"
|
||||||
|
log_destination: csvlog
|
||||||
|
log_directory: /controller/log
|
||||||
|
log_filename: postgres
|
||||||
|
log_rotation_age: "0"
|
||||||
|
log_rotation_size: "0"
|
||||||
|
log_truncate_on_rotation: "false"
|
||||||
|
logging_collector: "on"
|
||||||
|
max_connections: "100"
|
||||||
|
max_parallel_workers: "4"
|
||||||
|
max_replication_slots: "16"
|
||||||
|
max_worker_processes: "4"
|
||||||
|
shared_buffers: 64MB
|
||||||
|
shared_memory_type: mmap
|
||||||
|
ssl_max_protocol_version: TLSv1.3
|
||||||
|
ssl_min_protocol_version: TLSv1.3
|
||||||
|
wal_keep_size: 128MB
|
||||||
|
wal_level: logical
|
||||||
|
wal_log_hints: "on"
|
||||||
|
wal_receiver_timeout: 5s
|
||||||
|
wal_sender_timeout: 5s
|
||||||
|
syncReplicaElectionConstraint:
|
||||||
|
enabled: false
|
||||||
|
primaryUpdateMethod: restart
|
||||||
|
primaryUpdateStrategy: unsupervised
|
||||||
|
probes:
|
||||||
|
liveness:
|
||||||
|
isolationCheck:
|
||||||
|
connectionTimeout: 1000
|
||||||
|
enabled: true
|
||||||
|
requestTimeout: 1000
|
||||||
|
replicationSlots:
|
||||||
|
highAvailability:
|
||||||
|
enabled: true
|
||||||
|
slotPrefix: _cnpg_
|
||||||
|
synchronizeReplicas:
|
||||||
|
enabled: true
|
||||||
|
updateInterval: 30
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
smartShutdownTimeout: 180
|
||||||
|
startDelay: 3600
|
||||||
|
stopDelay: 1800
|
||||||
|
storage:
|
||||||
|
resizeInUseVolumes: true
|
||||||
|
size: 5Gi
|
||||||
|
storageClass: cephrbd-fast-delete
|
||||||
|
switchoverDelay: 3600
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
apiVersion: postgresql.cnpg.io/v1
|
||||||
|
kind: Pooler
|
||||||
|
metadata:
|
||||||
|
name: open-webui-postgres-pooler
|
||||||
|
namespace: open-webui
|
||||||
|
spec:
|
||||||
|
cluster:
|
||||||
|
name: open-webui-postgres
|
||||||
|
instances: 2
|
||||||
|
pgbouncer:
|
||||||
|
parameters:
|
||||||
|
default_pool_size: "50"
|
||||||
|
max_client_conn: "200"
|
||||||
|
paused: false
|
||||||
|
poolMode: transaction
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: pooler
|
||||||
|
spec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- pooler
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
containers: []
|
||||||
|
type: rw
|
||||||
@@ -5,12 +5,10 @@ metadata:
|
|||||||
name: open-webui
|
name: open-webui
|
||||||
namespace: open-webui
|
namespace: open-webui
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 3
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: open-webui
|
app: open-webui
|
||||||
strategy:
|
|
||||||
type: Recreate
|
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -18,6 +16,7 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: open-webui
|
app: open-webui
|
||||||
spec:
|
spec:
|
||||||
|
priorityClassName: power
|
||||||
containers:
|
containers:
|
||||||
- name: open-webui
|
- name: open-webui
|
||||||
image: ghcr.io/open-webui/open-webui:main
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
@@ -59,11 +58,4 @@ spec:
|
|||||||
requests:
|
requests:
|
||||||
cpu: 250m
|
cpu: 250m
|
||||||
memory: 512Mi
|
memory: 512Mi
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /app/backend/data
|
|
||||||
name: data
|
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: open-webui-data
|
|
||||||
|
|||||||
@@ -47,3 +47,7 @@ spec:
|
|||||||
- path:
|
- path:
|
||||||
type: PathPrefix
|
type: PathPrefix
|
||||||
value: /
|
value: /
|
||||||
|
sessionPersistence:
|
||||||
|
type: Cookie
|
||||||
|
cookieName: open-webui-backend
|
||||||
|
absoluteTimeout: 24h0m0s
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ kind: Kustomization
|
|||||||
|
|
||||||
resources:
|
resources:
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- pvc.yaml
|
- cnpg_cluster.yaml
|
||||||
|
- cnpg_pooler.yaml
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
|
- pdb.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
- gateway.yaml
|
- gateway.yaml
|
||||||
- httproute.yaml
|
- httproute.yaml
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
apiVersion: policy/v1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
name: open-webui
|
||||||
|
namespace: open-webui
|
||||||
|
spec:
|
||||||
|
minAvailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: open-webui
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: open-webui-data
|
|
||||||
namespace: open-webui
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 10Gi
|
|
||||||
storageClassName: cephrbd-fast-delete
|
|
||||||
@@ -1,6 +1,23 @@
|
|||||||
---
|
---
|
||||||
apiVersion: secrets.hashicorp.com/v1beta1
|
apiVersion: secrets.hashicorp.com/v1beta1
|
||||||
kind: VaultStaticSecret
|
kind: VaultStaticSecret
|
||||||
|
metadata:
|
||||||
|
name: postgres-credentials
|
||||||
|
namespace: open-webui
|
||||||
|
spec:
|
||||||
|
destination:
|
||||||
|
create: true
|
||||||
|
name: postgres-credentials
|
||||||
|
overwrite: true
|
||||||
|
hmacSecretData: true
|
||||||
|
mount: kv
|
||||||
|
path: kubernetes/namespace/open-webui/default/postgres-credentials
|
||||||
|
refreshAfter: 5m
|
||||||
|
type: kv-v2
|
||||||
|
vaultAuthRef: default
|
||||||
|
---
|
||||||
|
apiVersion: secrets.hashicorp.com/v1beta1
|
||||||
|
kind: VaultStaticSecret
|
||||||
metadata:
|
metadata:
|
||||||
name: open-webui-credentials
|
name: open-webui-credentials
|
||||||
namespace: open-webui
|
namespace: open-webui
|
||||||
|
|||||||
Reference in New Issue
Block a user