Initial chart import from local infrastructure/
This commit is contained in:
15
Chart.yaml
Normal file
15
Chart.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v2
|
||||
name: instance-template-v3
|
||||
description: |
|
||||
OdooSky v3 — single Helm chart for every Odoo instance.
|
||||
Variation between instances is expressed via values.yaml only.
|
||||
No chart variants. No string-templating in Tower.
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "1.0"
|
||||
keywords:
|
||||
- odoo
|
||||
- erp
|
||||
- odoosky
|
||||
maintainers:
|
||||
- name: OdooSky platform
|
||||
36
templates/_helpers.tpl
Normal file
36
templates/_helpers.tpl
Normal file
@@ -0,0 +1,36 @@
|
||||
{{/*
|
||||
Per-instance fully-qualified name. Used as the prefix for every K8s
|
||||
object in the chart so instances in the same namespace can't collide.
|
||||
*/}}
|
||||
{{- define "instance.fullname" -}}
|
||||
{{- .Values.instance.code | trunc 40 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Standard labels applied to every K8s object. Keeps `kubectl get -l`
|
||||
queries by-instance trivial.
|
||||
*/}}
|
||||
{{- define "instance.labels" -}}
|
||||
app.kubernetes.io/name: odoo
|
||||
app.kubernetes.io/instance: {{ .Values.instance.code | quote }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
app.kubernetes.io/version: {{ .Values.odoo.tag | quote }}
|
||||
odoosky.io/component: instance
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Postgres password. Looks up the existing Secret on upgrades; uses
|
||||
.Values.postgres.password if set; otherwise generates a 32-char
|
||||
random string on first install. The lookup ensures `helm upgrade`
|
||||
does NOT silently rotate the password.
|
||||
*/}}
|
||||
{{- define "instance.pgPassword" -}}
|
||||
{{- $existing := lookup "v1" "Secret" .Release.Namespace (printf "%s-pg" .Values.instance.code) -}}
|
||||
{{- if and $existing $existing.data $existing.data.POSTGRES_PASSWORD -}}
|
||||
{{- index $existing.data "POSTGRES_PASSWORD" | b64dec -}}
|
||||
{{- else if .Values.postgres.password -}}
|
||||
{{- .Values.postgres.password -}}
|
||||
{{- else -}}
|
||||
{{- randAlphaNum 32 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
21
templates/ingressroute.yaml
Normal file
21
templates/ingressroute.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
entryPoints:
|
||||
- {{ .Values.ingress.entryPoint }}
|
||||
routes:
|
||||
- match: Host(`{{ .Values.instance.domain }}`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: {{ include "instance.fullname" . }}-odoo
|
||||
port: 8069
|
||||
tls:
|
||||
# Shared wildcard cert for *.tenants.odoosky.org. The Secret is
|
||||
# provisioned ONCE per cluster (see infrastructure/cluster/) and
|
||||
# mirrored into the chart's release namespace by the cluster
|
||||
# operator. Instances do NOT issue their own certs.
|
||||
secretName: {{ .Values.ingress.tlsSecret }}
|
||||
69
templates/odoo-deployment.yaml
Normal file
69
templates/odoo-deployment.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-odoo
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: 1
|
||||
# ReadWriteOnce filestore volume + Odoo's session locks rule out
|
||||
# rolling deploys with two pods overlapping. Recreate is safe and
|
||||
# only causes brief downtime.
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: {{ .Values.instance.code | quote }}
|
||||
odoosky.io/role: odoo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 8 }}
|
||||
odoosky.io/role: odoo
|
||||
spec:
|
||||
containers:
|
||||
- name: odoo
|
||||
image: "{{ .Values.odoo.image }}:{{ .Values.odoo.tag }}"
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8069
|
||||
env:
|
||||
- name: HOST
|
||||
value: {{ include "instance.fullname" . }}-pg
|
||||
- name: PORT
|
||||
value: "5432"
|
||||
- name: USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
key: POSTGRES_USER
|
||||
- name: PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
key: POSTGRES_PASSWORD
|
||||
volumeMounts:
|
||||
- name: filestore
|
||||
mountPath: /var/lib/odoo
|
||||
resources:
|
||||
{{- toYaml .Values.odoo.resources | nindent 12 }}
|
||||
# /web/login is the most stable health endpoint across Odoo
|
||||
# 16/17/18/19 — /web/health is 17+. Use login HTTP 200 as
|
||||
# readiness signal.
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /web/login
|
||||
port: 8069
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 8069
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
volumes:
|
||||
- name: filestore
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ include "instance.fullname" . }}-odoo
|
||||
11
templates/odoo-pvc.yaml
Normal file
11
templates/odoo-pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-odoo
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes: [ReadWriteOnce]
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.odoo.filestoreSize | quote }}
|
||||
15
templates/odoo-service.yaml
Normal file
15
templates/odoo-service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-odoo
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/instance: {{ .Values.instance.code | quote }}
|
||||
odoosky.io/role: odoo
|
||||
ports:
|
||||
- name: http
|
||||
port: 8069
|
||||
targetPort: 8069
|
||||
type: ClusterIP
|
||||
11
templates/postgres-secret.yaml
Normal file
11
templates/postgres-secret.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
POSTGRES_USER: {{ .Values.postgres.user | quote }}
|
||||
POSTGRES_PASSWORD: {{ include "instance.pgPassword" . | quote }}
|
||||
POSTGRES_DB: {{ .Values.postgres.database | quote }}
|
||||
16
templates/postgres-service.yaml
Normal file
16
templates/postgres-service.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/instance: {{ .Values.instance.code | quote }}
|
||||
odoosky.io/role: postgres
|
||||
ports:
|
||||
- name: pg
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
# Headless service — required for StatefulSet stable DNS.
|
||||
clusterIP: None
|
||||
58
templates/postgres-statefulset.yaml
Normal file
58
templates/postgres-statefulset.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
serviceName: {{ include "instance.fullname" . }}-pg
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: {{ .Values.instance.code | quote }}
|
||||
odoosky.io/role: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 8 }}
|
||||
odoosky.io/role: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: "{{ .Values.postgres.image }}:{{ .Values.postgres.tag }}"
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: pg
|
||||
containerPort: 5432
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
env:
|
||||
# PGDATA in a sub-dir so the mount-point itself isn't the
|
||||
# data dir — postgres refuses to init when `lost+found`
|
||||
# exists at the root of the volume.
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: pgdata
|
||||
mountPath: /var/lib/postgresql/data
|
||||
resources:
|
||||
{{- toYaml .Values.postgres.resources | nindent 12 }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["sh", "-c", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["sh", "-c", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 15
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: pgdata
|
||||
spec:
|
||||
accessModes: [ReadWriteOnce]
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.postgres.storage | quote }}
|
||||
59
values.yaml
Normal file
59
values.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
# OdooSky v3 instance-template-v3 — default values.
|
||||
#
|
||||
# Per-tenant overlay repos override only the keys that differ from these
|
||||
# defaults. Keep this file as the single source of truth for what an
|
||||
# Odoo instance looks like by default; do not duplicate defaults in the
|
||||
# overlay schema or in Tower-Go.
|
||||
|
||||
instance:
|
||||
# Short slug used in K8s object names + as the Helm release name.
|
||||
# Must be DNS-safe (lowercase, no underscores, <= 40 chars).
|
||||
code: demo
|
||||
# The full HTTPS hostname this instance answers on.
|
||||
# Tenants live under *.tenants.odoosky.org (covered by wildcard DNS A).
|
||||
domain: demo.tenants.odoosky.org
|
||||
|
||||
odoo:
|
||||
image: odoo
|
||||
tag: "18.0"
|
||||
# Filestore PVC size (Odoo's /var/lib/odoo).
|
||||
filestoreSize: 10Gi
|
||||
resources:
|
||||
requests:
|
||||
memory: 512Mi
|
||||
cpu: 250m
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: "2"
|
||||
|
||||
postgres:
|
||||
image: postgres
|
||||
tag: "16-alpine"
|
||||
user: odoo
|
||||
database: postgres
|
||||
# If empty, the chart auto-generates on first install and re-reads
|
||||
# the existing Secret on subsequent upgrades (lookup pattern).
|
||||
password: ""
|
||||
storage: 10Gi
|
||||
resources:
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
limits:
|
||||
memory: 1Gi
|
||||
cpu: "1"
|
||||
|
||||
ingress:
|
||||
# Traefik entrypoint name (set on the Traefik install in the
|
||||
# `traefik` namespace).
|
||||
entryPoint: websecure
|
||||
# The pre-provisioned wildcard cert for *.tenants.odoosky.org —
|
||||
# one Certificate resource issued ONCE in the chart's release
|
||||
# namespace, then every instance's IngressRoute references the
|
||||
# resulting Secret. Avoids Let's Encrypt's per-week certificate
|
||||
# issuance ceiling (50/week/registered-domain) as we scale to
|
||||
# many tenants.
|
||||
#
|
||||
# See infrastructure/cluster/wildcard-cert.yaml for the
|
||||
# provisioning manifest.
|
||||
tlsSecret: tenants-wildcard-tls
|
||||
Reference in New Issue
Block a user