Skip to content
antalos

Odoo · Architecture

The source design places two Odoo 19 Community pods on distinct talos-worker-left and talos-worker-right nodes using required hostname anti-affinity. The Service routes requests to ready endpoints. A minAvailable: 1 PodDisruptionBudget protects voluntary eviction, and rolling updates use maxSurge: 0 and maxUnavailable: 1 to fit two workers. Traefik terminates HTTPS at odoo.antblu.net with the service-owned letsencrypt-prod certificate. Threaded HTTP and WebSocket traffic use port 8069. Native Odoo accounts provide login. The installed OCA auth_oidc addon adds OpenID Connect support; a provider must be separately configured and enabled. The local authentik_jit addon adds optional per-provider account linking and internal-user creation from verified claims, using an explicitly selected template. Its source and generated delivery ConfigMap belong to apps/odoo/; the operations guide defines installation and the manual login-test boundary.

CloudNativePG runs two PostgreSQL instances on those same two distinct workers, each with its own 10 GiB openebs-local volume. Required database pod anti-affinity prevents colocation. The operator promotes the surviving standby when needed, and odoo-db-rw routes clients to the writer. Synchronous replication requests one acknowledgement with preferred durability: writes may continue when the standby is unavailable, so degraded operation can lose recent writes on a subsequent failure. Application requests must reconnect during database promotion.

The OCA session_db server-wide addon stores shared HTTP sessions in the replicated Odoo database. The OCA S3 attachment addon stores new attachments in Garage at http://10.30.0.5:30188, region garage, bucket odoo, prefix attachments/. Small images and web assets use PostgreSQL. The bootstrap Job copies remaining legacy local attachments into PostgreSQL before enabling the serving pods. Their original files and the 20 GiB legacy PVC are retained for recovery; serving pods use only disposable local cache directories. No worker-local volume is required to serve an existing attachment or session.

Initialization runs once through odoo-bootstrap-ha-v1, with a PostgreSQL advisory lock and a database readiness marker. It initializes an empty database, secures its administrator, installs storage addons, configures S3, and imports legacy attachment files. Serving init containers generate their private runtime configuration, wait for this marker, and reconcile runtime storage settings under the same advisory lock; they do not run concurrent schema installation. Existing administrator credentials are preserved. Switching from filesystem sessions requires users to sign in again.

Daily backups run at 09:00 UTC without scaling down either serving replica. A consistent pg_dump snapshot includes database attachments and sessions; the subsequent S3 copy captures all immutable object versions with garbage collection disabled. COMPLETE.json marks a completed backup. The backup account has no Kubernetes mutation permissions. Do not enable attachment garbage collection or in-place object overwrite without revisiting this consistency model.

This design supports continued service through loss of one eligible worker while Garage, ingress, the Kubernetes API, and CNPG control remain available. Database promotion and interrupted requests can cause a brief error/retry period. Shared Garage, ingress, the API endpoint, host-level failures, and addon download availability remain dependencies. Copies of active objects and backups in the same Garage service do not provide an independent disaster-recovery destination. See service availability.

All resources belong to apps/odoo/; shared inputs belong to apps/variables.yaml, and credentials are namespace-bound SealedSecrets. This page describes source design. It does not establish live replication health, successful session or attachment failover, completed backups, or a measured recovery time.

The versioned odoo-commerce-v2 Job installs the optional medusa_bridge addon and its Product, Sales and Inventory dependencies at Sync wave 2. It takes the same advisory lock as other schema installers, scales serving to zero and waits for the old pods to terminate. Wave 3 restores the addon-equipped serving tier. This is an offline schema installation, with a temporary service interruption. The bridge adds atomic order receipts and an outbound fulfillment queue; it does not synchronize stock quantities. Its fulfillment cron starts inactive, and installing the schema does not activate external order export or configure business mappings. See the operations guide.