From bdb840e895357aa88bae75d02240a7bfff02ffcb Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 12:25:12 +0200 Subject: [PATCH 1/8] Refactor ingress configurations and remove deprecated settings for improved clarity and compatibility --- docs/stac-auth-proxy.md | 21 ------- docs/unified-ingress.md | 2 - .../eoapi/samples/values-with-nginx.yaml | 20 ++++++ .../templates/pgstacbootstrap/configmap.yaml | 4 -- .../templates/services/ingress-browser.yaml | 53 ++++++++++++++++ .../eoapi/templates/services/ingress.yaml | 33 ++++------ .../services/traefik-middleware.yaml | 3 - .../eoapi/test-gcp-unittest-values.yaml | 62 ------------------- helm-chart/eoapi/tests/ingress_tests.yaml | 2 - helm-chart/eoapi/values.schema.json | 9 --- helm-chart/eoapi/values.yaml | 7 +-- .../postgrescluster/templates/postgres.yaml | 1 + helm-chart/postgrescluster/values.yaml | 3 + 13 files changed, 92 insertions(+), 128 deletions(-) create mode 100644 helm-chart/eoapi/samples/values-with-nginx.yaml create mode 100644 helm-chart/eoapi/templates/services/ingress-browser.yaml delete mode 100644 helm-chart/eoapi/test-gcp-unittest-values.yaml diff --git a/docs/stac-auth-proxy.md b/docs/stac-auth-proxy.md index f0fd9602..2c06d925 100644 --- a/docs/stac-auth-proxy.md +++ b/docs/stac-auth-proxy.md @@ -23,27 +23,6 @@ raster: enabled: true ``` -### 2. Template Changes - -The ingress template now checks service-specific settings: - -```yaml -{{- if and .Values.stac.enabled (or (not (hasKey .Values.stac "ingress")) .Values.stac.ingress.enabled) }} -- pathType: {{ .Values.ingress.pathType }} - path: /stac{{ .Values.ingress.pathSuffix }} - backend: - service: - name: stac - port: - number: {{ .Values.service.port }} -{{- end }} -``` - -This ensures: -- Service paths are only included if the service and its ingress are enabled -- Backward compatibility is maintained (ingress enabled by default) -- Clean separation of service configurations - ## Deployment Guide ### 1. Configure EOAPI-K8S diff --git a/docs/unified-ingress.md b/docs/unified-ingress.md index 77157ddc..24d6391d 100644 --- a/docs/unified-ingress.md +++ b/docs/unified-ingress.md @@ -23,8 +23,6 @@ ingress: # ingressClassName: "nginx" or "traefik" className: "nginx" # Path configuration - pathType: "Prefix" # Can be "Prefix" or "ImplementationSpecific" based on controller - pathSuffix: "" # Add a suffix to service paths (e.g. "(/|$)(.*)" for nginx regex) rootPath: "" # Root path for doc server # Host configuration host: "" diff --git a/helm-chart/eoapi/samples/values-with-nginx.yaml b/helm-chart/eoapi/samples/values-with-nginx.yaml new file mode 100644 index 00000000..53acce3b --- /dev/null +++ b/helm-chart/eoapi/samples/values-with-nginx.yaml @@ -0,0 +1,20 @@ +ingress: + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$2 + className: nginx + enabled: true + host: eoapi.local + tls: + certManager: false + enabled: true + secretName: eoapi-tls +namespace: eoapi +postgrescluster: + enabled: true +resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 200m + memory: 256Mi \ No newline at end of file diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml index 2459bf22..98feb836 100644 --- a/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml +++ b/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml @@ -50,10 +50,6 @@ apiVersion: v1 kind: ConfigMap metadata: name: initdb - annotations: - helm.sh/hook: "post-install,post-upgrade" - helm.sh/hook-weight: "-6" - helm.sh/hook-delete-policy: "before-hook-creation,hook-succeeded" data: initdb.sql: | \c {{ .Values.pgstacBootstrap.settings.database }} diff --git a/helm-chart/eoapi/templates/services/ingress-browser.yaml b/helm-chart/eoapi/templates/services/ingress-browser.yaml new file mode 100644 index 00000000..ea799012 --- /dev/null +++ b/helm-chart/eoapi/templates/services/ingress-browser.yaml @@ -0,0 +1,53 @@ +# We need a separate ingress because browser has the prefix /browser hardcoded in the code +{{- if and .Values.browser.enabled .Values.ingress.enabled }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }} +apiVersion: networking.k8s.io/v1beta1 +{{- else }} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: eoapi-ingress-browser-{{ .Release.Name }} + labels: + app: eoapi-{{ .Release.Name }} + annotations: + {{- if .Values.ingress.annotations }} +{{ toYaml .Values.ingress.annotations | indent 4 }} + {{- end }} + {{- if eq .Values.ingress.className "nginx" }} + nginx.ingress.kubernetes.io/rewrite-target: /browser/$2 + nginx.ingress.kubernetes.io/use-regex: "true" + {{- end }} + # Temporary annotations for Traefik until uvicorn support real prefix in ASGI: https://github.com/encode/uvicorn/discussions/2490 + {{- if eq .Values.ingress.className "traefik" }} + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.middlewares: {{ $.Release.Namespace }}-strip-prefix-middleware-{{ $.Release.Name }}@kubernetescrd + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + rules: + - {{- if .Values.ingress.host }} + host: {{ .Values.ingress.host }} + {{- end }} + http: + paths: + {{- if and .Values.browser.enabled (or (not (hasKey .Values.browser "ingress")) .Values.browser.ingress.enabled) }} + - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} + path: "/browser{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }}" + backend: + service: + name: browser-{{ $.Release.Name }} + port: + number: 8080 + {{- end }} + {{- if and .Values.ingress.host .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} +{{- end }} diff --git a/helm-chart/eoapi/templates/services/ingress.yaml b/helm-chart/eoapi/templates/services/ingress.yaml index 3ddfa596..16093175 100644 --- a/helm-chart/eoapi/templates/services/ingress.yaml +++ b/helm-chart/eoapi/templates/services/ingress.yaml @@ -12,6 +12,10 @@ metadata: labels: app: eoapi-{{ .Release.Name }} annotations: + {{- if eq .Values.ingress.className "nginx" }} + nginx.ingress.kubernetes.io/rewrite-target: /$2 + nginx.ingress.kubernetes.io/use-regex: "true" + {{- end }} {{- if .Values.ingress.annotations }} {{ toYaml .Values.ingress.annotations | indent 4 }} {{- end }} @@ -31,8 +35,8 @@ spec: http: paths: {{- if and .Values.raster.enabled (or (not (hasKey .Values.raster "ingress")) .Values.raster.ingress.enabled) }} - - pathType: {{ .Values.ingress.pathType }} - path: /raster{{ .Values.ingress.pathSuffix }} + - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} + path: /raster{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} backend: service: name: raster-{{ $.Release.Name }} @@ -41,8 +45,8 @@ spec: {{- end }} {{- if and .Values.stac.enabled (or (not (hasKey .Values.stac "ingress")) .Values.stac.ingress.enabled) }} - - pathType: {{ .Values.ingress.pathType }} - path: /stac{{ .Values.ingress.pathSuffix }} + - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} + path: /stac{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} backend: service: name: stac-{{ $.Release.Name }} @@ -51,8 +55,8 @@ spec: {{- end }} {{- if and .Values.vector.enabled (or (not (hasKey .Values.vector "ingress")) .Values.vector.ingress.enabled) }} - - pathType: {{ .Values.ingress.pathType }} - path: /vector{{ .Values.ingress.pathSuffix }} + - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} + path: /vector{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} backend: service: name: vector-{{ $.Release.Name }} @@ -61,8 +65,8 @@ spec: {{- end }} {{- if and .Values.multidim.enabled (or (not (hasKey .Values.multidim "ingress")) .Values.multidim.ingress.enabled) }} - - pathType: {{ .Values.ingress.pathType }} - path: /multidim{{ .Values.ingress.pathSuffix }} + - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} + path: /multidim{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} backend: service: name: multidim-{{ $.Release.Name }} @@ -70,19 +74,8 @@ spec: number: {{ .Values.service.port }} {{- end }} - {{- if and .Values.browser.enabled (or (not (hasKey .Values.browser "ingress")) .Values.browser.ingress.enabled) }} - # We need a separate path because browser does not play well with nginx rewrite_path directive - - pathType: {{ .Values.ingress.pathType }} - path: "/browser" - backend: - service: - name: browser-{{ $.Release.Name }} - port: - number: 8080 - {{- end }} - {{- if .Values.docServer.enabled }} - - pathType: {{ $.Values.ingress.pathType | default "Prefix" }} + - pathType: Prefix path: "/{{ $.Values.ingress.rootPath | default "" }}" backend: service: diff --git a/helm-chart/eoapi/templates/services/traefik-middleware.yaml b/helm-chart/eoapi/templates/services/traefik-middleware.yaml index 0c9718c8..2e252cce 100644 --- a/helm-chart/eoapi/templates/services/traefik-middleware.yaml +++ b/helm-chart/eoapi/templates/services/traefik-middleware.yaml @@ -19,7 +19,4 @@ spec: {{- if .Values.multidim.enabled }} - /multidim {{- end }} - # {{- if .Values.browser.enabled }} - # - /browser - # {{- end }} {{- end }} diff --git a/helm-chart/eoapi/test-gcp-unittest-values.yaml b/helm-chart/eoapi/test-gcp-unittest-values.yaml deleted file mode 100644 index dd2f4b88..00000000 --- a/helm-chart/eoapi/test-gcp-unittest-values.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# used in GH Actions `.github/workflows/helm-tests.yml.jobs.integration-tests` -testing: true - -ingress: - enabled: true - className: "nginx" - annotations: - kubernetes.io/ingress.class: nginx - ingress.kubernetes.io/ssl-redirect: "true" - nginx.ingress.kubernetes.io/ssl-redirect: "true" - # NOTE: for these integration tests `ingress.host` - # is unique and passed during helm install using --set - # host: $RELEASE_NAME.k8s.labs.ds.io - tls: - enabled: true - certManager: true - secretName: eoapi-tls - -pgstacBootstrap: - enabled: true - settings: - resources: - requests: - cpu: "256m" - memory: "1024Mi" - limits: - cpu: "512m" - memory: "1024Mi" -raster: - enabled: true - settings: - resources: - limits: - cpu: "768m" - memory: "4096Mi" - requests: - cpu: "256m" - memory: "1024Mi" -stac: - enabled: true - settings: - resources: - limits: - cpu: "1280m" - memory: "1536Mi" - requests: - cpu: "512m" - memory: "1024Mi" -vector: - enabled: true - settings: - resources: - limits: - cpu: "768m" - memory: "1536Mi" - requests: - cpu: "256m" - memory: "1024Mi" - envVars: - # needs to on so we can call /refresh for integration tests - TIPG_DEBUG: "True" - TIPG_CATALOG_TTL: "30" diff --git a/helm-chart/eoapi/tests/ingress_tests.yaml b/helm-chart/eoapi/tests/ingress_tests.yaml index a7f799fe..01f50704 100644 --- a/helm-chart/eoapi/tests/ingress_tests.yaml +++ b/helm-chart/eoapi/tests/ingress_tests.yaml @@ -5,8 +5,6 @@ tests: - it: "vector ingress with nginx controller" set: ingress.className: "nginx" - ingress.pathType: "ImplementationSpecific" - ingress.pathSuffix: "(/|$)(.*)" ingress.annotations: nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 diff --git a/helm-chart/eoapi/values.schema.json b/helm-chart/eoapi/values.schema.json index 7d7f7a71..2f3cd58e 100644 --- a/helm-chart/eoapi/values.schema.json +++ b/helm-chart/eoapi/values.schema.json @@ -65,15 +65,6 @@ "enum": ["nginx", "traefik"], "description": "Ingress controller class name" }, - "pathType": { - "type": "string", - "enum": ["Prefix", "ImplementationSpecific"], - "description": "Ingress path type" - }, - "pathSuffix": { - "type": "string", - "description": "Suffix to add to service paths" - }, "rootPath": { "type": "string", "description": "Root path for doc server" diff --git a/helm-chart/eoapi/values.yaml b/helm-chart/eoapi/values.yaml index 96ef7c8e..144989c4 100644 --- a/helm-chart/eoapi/values.yaml +++ b/helm-chart/eoapi/values.yaml @@ -41,11 +41,6 @@ ingress: enabled: true # ingressClassName: "nginx" or "traefik" className: "nginx" - # Path configuration - pathType: "Prefix" # Can be "Prefix" or "ImplementationSpecific" based on controller - # NOTE: When using nginx ingress controller with regex in pathSuffix, - # you must set pathType to "ImplementationSpecific". See issue #189 for more context. - pathSuffix: "" # Add a suffix to service paths (e.g. "(/|$)(.*)" for nginx regex) rootPath: "" # Root path for doc server # Host configuration host: "" @@ -103,6 +98,8 @@ postgresql: # this is declared as a dependency of eoapi in helm-chart/eoapi/Chart.yaml postgrescluster: enabled: true + # The name of the postgres cluster + name: pgstac postgresVersion: 16 postGISVersion: "3.4" pgBouncerReplicas: 1 diff --git a/helm-chart/postgrescluster/templates/postgres.yaml b/helm-chart/postgrescluster/templates/postgres.yaml index f668f99f..d875587f 100644 --- a/helm-chart/postgrescluster/templates/postgres.yaml +++ b/helm-chart/postgrescluster/templates/postgres.yaml @@ -2,6 +2,7 @@ apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: name: {{ default .Release.Name .Values.name }} + namespace: {{ default .Release.Namespace .Values.namespace }} spec: postgresVersion: {{ required "You must set the version of Postgres to deploy." .Values.postgresVersion }} {{- if .Values.postGISVersion }} diff --git a/helm-chart/postgrescluster/values.yaml b/helm-chart/postgrescluster/values.yaml index 4843b3df..93c1b88b 100644 --- a/helm-chart/postgrescluster/values.yaml +++ b/helm-chart/postgrescluster/values.yaml @@ -10,6 +10,9 @@ # name is the name of the cluster. This defaults to the name of the Helm # release. # name: hippo +# namespace is the namespace that the cluster will be deployed in. This defaults +# to the namespace of the Helm release. +# namespace: hippo # postgresVersion sets the version to deploy. This version number needs to be # available as one of the "RELATED_IMAGE_POSTGRES_..." images as part of the PGO From ff728beb9bea1a6ee318c7b962ba90ea52d060eb Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 13:26:56 +0200 Subject: [PATCH 2/8] Update PostgreSQL secret references to use custom cluster name and add tests for cluster name fallback --- helm-chart/eoapi/templates/_helpers.tpl | 30 ++++---- helm-chart/eoapi/tests/ingress_tests.yaml | 2 - helm-chart/eoapi/tests/postgres_tests.yaml | 70 +++++++++++++++++++ helm-chart/eoapi/values.yaml | 2 +- .../postgrescluster/templates/postgres.yaml | 1 - 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 helm-chart/eoapi/tests/postgres_tests.yaml diff --git a/helm-chart/eoapi/templates/_helpers.tpl b/helm-chart/eoapi/templates/_helpers.tpl index ebb38e69..df3c20af 100644 --- a/helm-chart/eoapi/templates/_helpers.tpl +++ b/helm-chart/eoapi/templates/_helpers.tpl @@ -85,80 +85,80 @@ PostgreSQL cluster secrets - name: PGUSER valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: user - name: PGPORT valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: port - name: PGHOST valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: host - name: PGPASSWORD valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: password - name: PGDATABASE valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: dbname - name: PGBOUNCER_URI valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: pgbouncer-uri # Legacy variables for backward compatibility - name: POSTGRES_USER valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: user - name: POSTGRES_PORT valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: port - name: POSTGRES_HOST valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: host - name: POSTGRES_HOST_READER valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: host - name: POSTGRES_HOST_WRITER valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: host - name: POSTGRES_PASS valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: password - name: POSTGRES_DBNAME valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: dbname - name: DATABASE_URL valueFrom: secretKeyRef: - name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} key: uri {{- end }} {{- end }} - name: PGADMIN_URI valueFrom: secretKeyRef: - name: {{ .Release.Name }}-pguser-postgres + name: {{ .Values.postgrescluster.name | default .Release.Name }}-pguser-postgres key: uri {{- end }} diff --git a/helm-chart/eoapi/tests/ingress_tests.yaml b/helm-chart/eoapi/tests/ingress_tests.yaml index 01f50704..ae5e6657 100644 --- a/helm-chart/eoapi/tests/ingress_tests.yaml +++ b/helm-chart/eoapi/tests/ingress_tests.yaml @@ -6,8 +6,6 @@ tests: set: ingress.className: "nginx" ingress.annotations: - nginx.ingress.kubernetes.io/use-regex: "true" - nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/enable-access-log: "true" raster.enabled: false diff --git a/helm-chart/eoapi/tests/postgres_tests.yaml b/helm-chart/eoapi/tests/postgres_tests.yaml new file mode 100644 index 00000000..3a60d981 --- /dev/null +++ b/helm-chart/eoapi/tests/postgres_tests.yaml @@ -0,0 +1,70 @@ +suite: postgresql tests +templates: + - templates/services/stac/deployment.yaml +tests: + - it: should use custom cluster name for secret references when specified + set: + postgresql: + type: postgrescluster + postgrescluster: + enabled: true + name: custom-cluster + users: + - name: postgres + databases: ["postgres"] + - name: my-user + databases: ["my-db"] + stac: + enabled: true + raster: + enabled: false + vector: + enabled: false + multidim: + enabled: false + template: templates/services/stac/deployment.yaml + asserts: + - isKind: + of: Deployment + - contains: + path: spec.template.spec.containers[0].env + content: + name: PGUSER + valueFrom: + secretKeyRef: + name: custom-cluster-pguser-my-user + key: user + + - it: should fallback to release name when no custom cluster name is specified + release: + name: test-release + set: + postgresql: + type: postgrescluster + postgrescluster: + enabled: true + users: + - name: postgres + databases: ["postgres"] + - name: my-user + databases: ["my-db"] + stac: + enabled: true + raster: + enabled: false + vector: + enabled: false + multidim: + enabled: false + template: templates/services/stac/deployment.yaml + asserts: + - isKind: + of: Deployment + - contains: + path: spec.template.spec.containers[0].env + content: + name: PGUSER + valueFrom: + secretKeyRef: + name: test-release-pguser-my-user + key: user diff --git a/helm-chart/eoapi/values.yaml b/helm-chart/eoapi/values.yaml index 144989c4..0b2031d9 100644 --- a/helm-chart/eoapi/values.yaml +++ b/helm-chart/eoapi/values.yaml @@ -99,7 +99,7 @@ postgresql: postgrescluster: enabled: true # The name of the postgres cluster - name: pgstac + # name: pgstac postgresVersion: 16 postGISVersion: "3.4" pgBouncerReplicas: 1 diff --git a/helm-chart/postgrescluster/templates/postgres.yaml b/helm-chart/postgrescluster/templates/postgres.yaml index d875587f..f668f99f 100644 --- a/helm-chart/postgrescluster/templates/postgres.yaml +++ b/helm-chart/postgrescluster/templates/postgres.yaml @@ -2,7 +2,6 @@ apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: name: {{ default .Release.Name .Values.name }} - namespace: {{ default .Release.Namespace .Values.namespace }} spec: postgresVersion: {{ required "You must set the version of Postgres to deploy." .Values.postgresVersion }} {{- if .Values.postGISVersion }} From c45412e109af20b9d8f04153f3958d85a61ac1c5 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 14:04:44 +0200 Subject: [PATCH 3/8] Add upgrade job for database permissions and update schema for previous version --- CHANGELOG.md | 3 + .../eoapi/samples/values-with-nginx.yaml | 1 + .../eoapiuser-permissions-upgrade.yaml | 83 +++++++++++++++++++ .../eoapi/templates/pgstacbootstrap/job.yaml | 2 +- helm-chart/eoapi/values.schema.json | 4 + helm-chart/eoapi/values.yaml | 7 ++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 helm-chart/eoapi/templates/pgstacbootstrap/eoapiuser-permissions-upgrade.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index aa5b0df4..adb2a2cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking Changes - Remove hard-coded cert-manager configuration from ingress template [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) +### Added +- Add upgrade job to handle database permissions for migrations from pre-0.7.0 versions + ### Changed - Simplify TLS configuration to allow user-controlled certificate management [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) - Update documentation with comprehensive cert-manager setup guide [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) diff --git a/helm-chart/eoapi/samples/values-with-nginx.yaml b/helm-chart/eoapi/samples/values-with-nginx.yaml index 53acce3b..737639e8 100644 --- a/helm-chart/eoapi/samples/values-with-nginx.yaml +++ b/helm-chart/eoapi/samples/values-with-nginx.yaml @@ -11,6 +11,7 @@ ingress: namespace: eoapi postgrescluster: enabled: true + name: pgstac resources: limits: cpu: 1000m diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/eoapiuser-permissions-upgrade.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/eoapiuser-permissions-upgrade.yaml new file mode 100644 index 00000000..badb4ca2 --- /dev/null +++ b/helm-chart/eoapi/templates/pgstacbootstrap/eoapiuser-permissions-upgrade.yaml @@ -0,0 +1,83 @@ +{{- if and .Values.postgrescluster.enabled .Values.pgstacBootstrap.enabled .Release.IsUpgrade (semverCompare "< 0.7.0" .Values.previousVersion) }} +--- +# This job is part of the upgrade process from pre-0.7.0 versions. +# Prior to 0.7.0, database schema updates were run with superuser privileges. +# This job ensures proper permissions are granted to the eoapi user during upgrade. +apiVersion: batch/v1 +kind: Job +metadata: + name: pgstac-eoapiuser-permissions-upgrade + labels: + app: pgstac-eoapiuser-permissions-upgrade + annotations: + helm.sh/hook: "post-upgrade" + helm.sh/hook-weight: "-7" + helm.sh/hook-delete-policy: "before-hook-creation" +spec: + template: + metadata: + labels: + app: pgstac-eoapiuser-permissions-upgrade + spec: + restartPolicy: Never + containers: + - name: pgstac-eoapiuser-permissions + image: {{ .Values.pgstacBootstrap.image.name }}:{{ .Values.pgstacBootstrap.image.tag }} + command: + - "/bin/sh" + - "-c" + args: + - | + # Exit immediately if a command exits with a non-zero status + set -e + + # Run permission setup with superuser + echo "Applying superuser permissions for upgrade from version {{ .Values.previousVersion }}..." + PGUSER=postgres psql -f /opt/sql/initdb.sql + + echo "Permissions upgrade complete" + resources: + {{- toYaml .Values.pgstacBootstrap.settings.resources | nindent 12 }} + volumeMounts: + - mountPath: /opt/sql + name: initdb-config + env: + - name: PGUSER + valueFrom: + secretKeyRef: + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-postgres + key: user + - name: PGPORT + valueFrom: + secretKeyRef: + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-postgres + key: port + - name: PGHOST + valueFrom: + secretKeyRef: + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-postgres + key: host + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-postgres + key: password + - name: PGDATABASE + valueFrom: + secretKeyRef: + name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-postgres + key: dbname + volumes: + - name: initdb-config + configMap: + name: initdb + {{- with .Values.pgstacBootstrap.settings.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.pgstacBootstrap.settings.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + backoffLimit: 1 +{{- end }} diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml index fa9b60f0..473ef949 100644 --- a/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml +++ b/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml @@ -154,5 +154,5 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} - backoffLimit: 1 + backoffLimit: 3 {{- end }} diff --git a/helm-chart/eoapi/values.schema.json b/helm-chart/eoapi/values.schema.json index 2f3cd58e..03af3473 100644 --- a/helm-chart/eoapi/values.schema.json +++ b/helm-chart/eoapi/values.schema.json @@ -6,6 +6,10 @@ "gitSha" ], "properties": { + "previousVersion": { + "type": "string", + "description": "Previous version when upgrading. Used for migrations (e.g., when upgrading from pre-0.7.0 versions)" + }, "gitSha": { "type": "string", "description": "Git SHA of the deployment" diff --git a/helm-chart/eoapi/values.yaml b/helm-chart/eoapi/values.yaml index 0b2031d9..0472c0c0 100644 --- a/helm-chart/eoapi/values.yaml +++ b/helm-chart/eoapi/values.yaml @@ -467,3 +467,10 @@ browser: docServer: enabled: true + +# Version being upgraded from, used for migration purposes +# Dont set the value in the values.yaml file +# prefer to set it in the command line +# helm upgrade --set previousVersion=$PREVIOUS_VERSION +# or in the CI/CD pipeline +previousVersion: "" \ No newline at end of file From 31ea64c504ac7b6f276c904b927003bbbcfa4db2 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 14:08:52 +0200 Subject: [PATCH 4/8] Add upgrade guide and important notice for database permission changes --- README.md | 3 ++ docs/upgrade.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 docs/upgrade.md diff --git a/README.md b/README.md index 7e9edd9e..8b343c1b 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,9 @@ For cloud-based deployments, refer to our detailed setup guides: * [Autoscaling and Monitoring](./docs/autoscaling.md) * [Health Checks](./docs/health.md) * [Unified Ingress Configuration](./docs/unified-ingress.md) +* [Upgrade Guide](./docs/upgrade.md) + +> **Important Notice**: If you're upgrading from a version prior to 0.7.0, please read the [upgrade guide](./docs/upgrade.md) for important database permission changes. ## Contributing diff --git a/docs/upgrade.md b/docs/upgrade.md new file mode 100644 index 00000000..e86397e2 --- /dev/null +++ b/docs/upgrade.md @@ -0,0 +1,113 @@ +# Upgrading eoAPI + +## General Upgrade Process + +To upgrade your eoAPI installation, use the standard Helm upgrade command: + +```bash +helm upgrade eoapi devseed/eoapi +``` + +## Special Considerations for Pre-0.7.0 Versions + +### Database Permission Changes + +When upgrading from a version prior to 0.7.0, there are important database permission changes that need to be handled. In versions before 0.7.0, database schema updates were run with superuser privileges. Starting from 0.7.0, these operations are performed with the eoapi user account. + +### Using the PostgreSQL Subchart + +If you're using the built-in PostgreSQL cluster (default setup), follow these steps: + +1. Specify your current version during the upgrade: +```bash +helm upgrade eoapi devseed/eoapi --set previousVersion=0.6.0 +``` + +This will trigger a special upgrade job that: +- Runs with superuser privileges +- Grants necessary permissions to the eoapi user +- Ensures database schema permissions are properly configured + +### Using an External Database + +If you're using an external PostgreSQL database (postgresql.type set to "external-plaintext" or "external-secret"), you'll need to apply the permission changes manually. Connect to your database with superuser privileges and execute the following SQL: + +```sql +\c your_database_name +CREATE EXTENSION IF NOT EXISTS postgis; +CREATE EXTENSION IF NOT EXISTS btree_gist; +CREATE EXTENSION IF NOT EXISTS unaccent; +CREATE ROLE pgstac_admin; +CREATE ROLE pgstac_read; +CREATE ROLE pgstac_ingest; +ALTER DATABASE your_database_name OWNER TO your_eoapi_user; +ALTER USER your_eoapi_user SET search_path TO pgstac, public; +ALTER DATABASE your_database_name set search_path to pgstac, public; +GRANT CONNECT ON DATABASE your_database_name TO your_eoapi_user; +GRANT ALL PRIVILEGES ON TABLES TO your_eoapi_user; +GRANT ALL PRIVILEGES ON SEQUENCES TO your_eoapi_user; +GRANT pgstac_read TO your_eoapi_user WITH ADMIN OPTION; +GRANT pgstac_ingest TO your_eoapi_user WITH ADMIN OPTION; +GRANT pgstac_admin TO your_eoapi_user WITH ADMIN OPTION; +``` + +Replace: +- `your_database_name` with your database name (default: eoapi) +- `your_eoapi_user` with your eoapi user name (default: eoapi) + +### Upgrade Steps + +1. First, check your current version: +```bash +helm list -n eoapi +``` + +2. If you're running a version earlier than 0.7.0: + - For subchart users: + ```bash + export CURRENT_VERSION=$(helm list -n eoapi -o json | jq -r '.[].app_version') + helm upgrade eoapi devseed/eoapi \ + --set previousVersion=$CURRENT_VERSION \ + --namespace eoapi + ``` + - For external database users: + Execute the SQL script shown above with superuser privileges. + +3. Verify the upgrade: +```bash +# Check that all pods are running +kubectl get pods -n eoapi + +# For subchart users, check the upgrade job status: +kubectl get jobs -n eoapi | grep eoapiuser-permissions-upgrade +``` + +### Troubleshooting + +If you encounter issues during the upgrade: + +1. For subchart users, check the upgrade job logs: +```bash +kubectl logs -n eoapi -l app=pgstac-eoapiuser-permissions-upgrade +``` + +2. Verify database permissions: +```bash +# Connect to your database (method varies based on setup) +psql -U your_superuser -d your_database_name + +# Check role permissions +\du + +# Verify extensions +\dx + +# Check database owner +\l +``` + +For external databases, ensure: +- You have superuser privileges when executing the permission script +- All extensions are properly installed +- The database owner is correctly set +- The eoapi user has all necessary role memberships From 5980bc2b78c0ddc8c822ad51acadc02b67c5474e Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 14:17:36 +0200 Subject: [PATCH 5/8] Update changelog and upgrade documentation for version 0.7.1 enhancements --- CHANGELOG.md | 6 + docs/unified-ingress.md | 94 ++++----- docs/upgrade.md | 17 ++ helm-chart/eoapi/diff | 437 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 507 insertions(+), 47 deletions(-) create mode 100644 helm-chart/eoapi/diff diff --git a/CHANGELOG.md b/CHANGELOG.md index adb2a2cf..acaef3b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking Changes - Remove hard-coded cert-manager configuration from ingress template [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) +- Remove `pathType` and `pathSuffix` configurations in favor of controller-specific defaults ### Added - Add upgrade job to handle database permissions for migrations from pre-0.7.0 versions +- Add separate ingress configuration for STAC browser +- Support custom cluster naming via `postgrescluster.name` ### Changed +- Improve Nginx and Traefik support with controller-specific rewrites +- Increase bootstrap job retry limit to 3 attempts +- Enhance secret handling with custom PostgreSQL cluster names - Simplify TLS configuration to allow user-controlled certificate management [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) - Update documentation with comprehensive cert-manager setup guide [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) diff --git a/docs/unified-ingress.md b/docs/unified-ingress.md index 24d6391d..2b58d5ce 100644 --- a/docs/unified-ingress.md +++ b/docs/unified-ingress.md @@ -4,17 +4,16 @@ This document describes the unified ingress approach implemented in the eoAPI He ## Overview -As of version 0.7.0, eoAPI uses a consolidated, controller-agnostic ingress configuration. This approach: +As of version 0.7.0, eoAPI uses an even more streamlined ingress configuration with smart defaults for different controllers. This approach: -- Eliminates code duplication between different ingress controller implementations -- Provides consistent behavior across controllers -- Simplifies testing and maintainability -- Removes artificial restrictions on using certain ingress controllers in specific environments -- Makes it easier to add support for additional ingress controllers in the future +- Eliminates manual pathType and suffix configurations +- Uses controller-specific optimizations for NGINX and Traefik +- Provides separate configuration for STAC browser +- Maintains backward compatibility while improving usability ## Configuration -The ingress configuration has been streamlined and generalized in the `values.yaml` file: +The ingress configuration has been simplified in the `values.yaml` file: ```yaml ingress: @@ -22,8 +21,8 @@ ingress: enabled: true # ingressClassName: "nginx" or "traefik" className: "nginx" - # Path configuration - rootPath: "" # Root path for doc server + # Root path for doc server + rootPath: "" # Host configuration host: "" # Custom annotations to add to the ingress @@ -34,54 +33,57 @@ ingress: secretName: eoapi-tls ``` -## Controller-Specific Configurations +## Controller-Specific Behavior ### NGINX Ingress Controller -For NGINX, use the following configuration: +For NGINX, the system automatically: +- Uses `ImplementationSpecific` pathType +- Adds regex-based path matching +- Sets up proper rewrite rules +Basic NGINX configuration: ```yaml ingress: enabled: true className: "nginx" - pathType: "Prefix" annotations: - nginx.ingress.kubernetes.io/use-regex: "true" + # Additional custom annotations if needed nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/enable-access-log: "true" ``` ### Traefik Ingress Controller -When using Traefik, the system automatically includes the Traefik middleware to strip prefixes (e.g., `/stac`, `/raster`) from requests before forwarding them to services. This is handled by the `traefik-middleware.yaml` template. - -For basic Traefik configuration: +For Traefik, the system: +- Uses `Prefix` pathType by default +- Automatically configures strip-prefix middleware +- Handles path-based routing appropriately +Basic Traefik configuration: ```yaml ingress: enabled: true className: "traefik" - pathType: "Prefix" - # When using TLS, setting host is required to avoid "No domain found" warnings - host: "example.domain.com" # Required to work properly with TLS + # When using TLS, setting host is required + host: "example.domain.com" annotations: traefik.ingress.kubernetes.io/router.entrypoints: web ``` -For Traefik with TLS: +## STAC Browser Configuration +The STAC browser now uses a separate ingress configuration to handle its unique requirements: +- Fixed `/browser` path prefix +- Special rewrite rules for browser-specific routes +- Maintains compatibility with both NGINX and Traefik + +The browser-specific ingress is automatically configured when browser is enabled: ```yaml -ingress: +browser: enabled: true - className: "traefik" - pathType: "Prefix" - # Host is required when using TLS with Traefik - host: "example.domain.com" - annotations: - traefik.ingress.kubernetes.io/router.entrypoints: websecure - tls: - enabled: true - secretName: eoapi-tls + ingress: + enabled: true # Can be disabled independently ``` ## Setting up TLS with cert-manager @@ -143,31 +145,29 @@ ingress: className: "nginx" # or "traefik" host: "eoapi.example.com" annotations: - # Add cert-manager annotations cert-manager.io/cluster-issuer: "letsencrypt-prod" tls: enabled: true secretName: eoapi-tls # cert-manager will create this secret ``` -The certificate will be automatically obtained and renewed by cert-manager. The process typically takes a few minutes. You can check the certificate status with: -```bash -kubectl get certificate -``` - -## Migration - -If you're migrating from a version 0.6.0 or earlier, follow these guidelines: +## Migration from 0.7.0 -1. Update your values to use the new unified configuration -2. Ensure your ingress controller-specific annotations are set correctly -3. Set the appropriate `pathType` for your controller -4. Test the configuration before deploying to production +If you're upgrading from version 0.7.0: -## Note for Traefik Users +1. Remove any `pathType` and `pathSuffix` configurations from your values +2. The system will automatically use the appropriate settings for your chosen controller +3. For NGINX users, regex path matching is now enabled by default +4. For Traefik users, strip-prefix middleware is automatically configured -Traefik is now fully supported in all environments, including production. The previous restriction limiting Traefik to testing environments has been removed. +## Path Structure -## Document Server +Default service paths are: +- `/stac` - STAC API +- `/raster` - Raster API +- `/vector` - Vector API +- `/multidim` - Multi-dimensional API +- `/browser` - STAC Browser (separate ingress) +- `/` - Documentation server (when enabled) -The document server implementation has also been unified. It now works with both NGINX and Traefik controllers using the same configuration. +These paths are automatically configured with the appropriate rewrites for each controller. diff --git a/docs/upgrade.md b/docs/upgrade.md index e86397e2..f7607f16 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -8,6 +8,23 @@ To upgrade your eoAPI installation, use the standard Helm upgrade command: helm upgrade eoapi devseed/eoapi ``` +### Notable Changes in 0.7.1 + +#### Ingress Configuration Changes +- Removed `pathType` and `pathSuffix` configurations in favor of controller-specific defaults +- Added separate ingress configuration for STAC browser +- Improved Nginx and Traefik support with controller-specific rewrites + +#### PostgreSQL Cluster Updates +- Added ability to specify cluster name via `postgrescluster.name` +- Improved handling of database secrets with custom cluster names +- Job retry limit increased to 3 attempts for better reliability + +For example, to use a custom cluster name: +```bash +helm upgrade eoapi devseed/eoapi --set postgrescluster.name=my-pgstac +``` + ## Special Considerations for Pre-0.7.0 Versions ### Database Permission Changes diff --git a/helm-chart/eoapi/diff b/helm-chart/eoapi/diff new file mode 100644 index 00000000..b5e0b478 --- /dev/null +++ b/helm-chart/eoapi/diff @@ -0,0 +1,437 @@ + + +diff --git a/docs/stac-auth-proxy.md b/docs/stac-auth-proxy.md +index f0fd960..2c06d92 100644 +--- a/docs/stac-auth-proxy.md ++++ b/docs/stac-auth-proxy.md +@@ -23,27 +23,6 @@ raster: + enabled: true + ``` + +-### 2. Template Changes +- +-The ingress template now checks service-specific settings: +- +-```yaml +-{{- if and .Values.stac.enabled (or (not (hasKey .Values.stac "ingress")) .Values.stac.ingress.enabled) }} +-- pathType: {{ .Values.ingress.pathType }} +- path: /stac{{ .Values.ingress.pathSuffix }} +- backend: +- service: +- name: stac +- port: +- number: {{ .Values.service.port }} +-{{- end }} +-``` +- +-This ensures: +-- Service paths are only included if the service and its ingress are enabled +-- Backward compatibility is maintained (ingress enabled by default) +-- Clean separation of service configurations +- + ## Deployment Guide + + ### 1. Configure EOAPI-K8S +diff --git a/docs/unified-ingress.md b/docs/unified-ingress.md +index 77157dd..24d6391 100644 +--- a/docs/unified-ingress.md ++++ b/docs/unified-ingress.md +@@ -23,8 +23,6 @@ ingress: + # ingressClassName: "nginx" or "traefik" + className: "nginx" + # Path configuration +- pathType: "Prefix" # Can be "Prefix" or "ImplementationSpecific" based on controller +- pathSuffix: "" # Add a suffix to service paths (e.g. "(/|$)(.*)" for nginx regex) + rootPath: "" # Root path for doc server + # Host configuration + host: "" + +diff --git a/helm-chart/eoapi/samples/values-with-nginx.yaml b/helm-chart/eoapi/samples/values-with-nginx.yaml +new file mode 100644 +index 0000000..737639e +--- /dev/null ++++ b/helm-chart/eoapi/samples/values-with-nginx.yaml +@@ -0,0 +1,21 @@ ++ingress: ++ annotations: ++ nginx.ingress.kubernetes.io/rewrite-target: /$2 ++ className: nginx ++ enabled: true ++ host: eoapi.local ++ tls: ++ certManager: false ++ enabled: true ++ secretName: eoapi-tls ++namespace: eoapi ++postgrescluster: ++ enabled: true ++ name: pgstac ++resources: ++ limits: ++ cpu: 1000m ++ memory: 1Gi ++ requests: ++ cpu: 200m ++ memory: 256Mi +\ No newline at end of file +diff --git a/helm-chart/eoapi/templates/_helpers.tpl b/helm-chart/eoapi/templates/_helpers.tpl +index ebb38e6..df3c20a 100644 +--- a/helm-chart/eoapi/templates/_helpers.tpl ++++ b/helm-chart/eoapi/templates/_helpers.tpl +@@ -85,80 +85,80 @@ PostgreSQL cluster secrets + - name: PGUSER + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: user + - name: PGPORT + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: port + - name: PGHOST + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: host + - name: PGPASSWORD + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: password + - name: PGDATABASE + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: dbname + - name: PGBOUNCER_URI + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: pgbouncer-uri + # Legacy variables for backward compatibility + - name: POSTGRES_USER + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: user + - name: POSTGRES_PORT + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: port + - name: POSTGRES_HOST + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: host + - name: POSTGRES_HOST_READER + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: host + - name: POSTGRES_HOST_WRITER + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: host + - name: POSTGRES_PASS + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: password + - name: POSTGRES_DBNAME + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: dbname + - name: DATABASE_URL + valueFrom: + secretKeyRef: +- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} ++ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} + key: uri + {{- end }} + {{- end }} + - name: PGADMIN_URI + valueFrom: + secretKeyRef: +- name: {{ .Release.Name }}-pguser-postgres ++ name: {{ .Values.postgrescluster.name | default .Release.Name }}-pguser-postgres + key: uri + {{- end }} + +diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml +index 2459bf2..98feb83 100644 +--- a/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml ++++ b/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml +@@ -50,10 +50,6 @@ apiVersion: v1 + kind: ConfigMap + metadata: + name: initdb +- annotations: +- helm.sh/hook: "post-install,post-upgrade" +- helm.sh/hook-weight: "-6" +- helm.sh/hook-delete-policy: "before-hook-creation,hook-succeeded" + data: + initdb.sql: | + \c {{ .Values.pgstacBootstrap.settings.database }} + +diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml +index fa9b60f..473ef94 100644 +--- a/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml ++++ b/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml +@@ -154,5 +154,5 @@ spec: + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +- backoffLimit: 1 ++ backoffLimit: 3 + {{- end }} +diff --git a/helm-chart/eoapi/templates/services/ingress-browser.yaml b/helm-chart/eoapi/templates/services/ingress-browser.yaml +new file mode 100644 +index 0000000..ea79901 +--- /dev/null ++++ b/helm-chart/eoapi/templates/services/ingress-browser.yaml +@@ -0,0 +1,53 @@ ++# We need a separate ingress because browser has the prefix /browser hardcoded in the code ++{{- if and .Values.browser.enabled .Values.ingress.enabled }} ++{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} ++apiVersion: networking.k8s.io/v1 ++{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }} ++apiVersion: networking.k8s.io/v1beta1 ++{{- else }} ++apiVersion: extensions/v1beta1 ++{{- end }} ++kind: Ingress ++metadata: ++ name: eoapi-ingress-browser-{{ .Release.Name }} ++ labels: ++ app: eoapi-{{ .Release.Name }} ++ annotations: ++ {{- if .Values.ingress.annotations }} ++{{ toYaml .Values.ingress.annotations | indent 4 }} ++ {{- end }} ++ {{- if eq .Values.ingress.className "nginx" }} ++ nginx.ingress.kubernetes.io/rewrite-target: /browser/$2 ++ nginx.ingress.kubernetes.io/use-regex: "true" ++ {{- end }} ++ # Temporary annotations for Traefik until uvicorn support real prefix in ASGI: https://github.com/encode/uvicorn/discussions/2490 ++ {{- if eq .Values.ingress.className "traefik" }} ++ traefik.ingress.kubernetes.io/router.entrypoints: web ++ traefik.ingress.kubernetes.io/router.middlewares: {{ $.Release.Namespace }}-strip-prefix-middleware-{{ $.Release.Name }}@kubernetescrd ++ {{- end }} ++spec: ++ {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} ++ ingressClassName: {{ .Values.ingress.className }} ++ {{- end }} ++ rules: ++ - {{- if .Values.ingress.host }} ++ host: {{ .Values.ingress.host }} ++ {{- end }} ++ http: ++ paths: ++ {{- if and .Values.browser.enabled (or (not (hasKey .Values.browser "ingress")) .Values.browser.ingress.enabled) }} ++ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} ++ path: "/browser{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }}" ++ backend: ++ service: ++ name: browser-{{ $.Release.Name }} ++ port: ++ number: 8080 ++ {{- end }} ++ {{- if and .Values.ingress.host .Values.ingress.tls.enabled }} ++ tls: ++ - hosts: ++ - {{ .Values.ingress.host }} ++ secretName: {{ .Values.ingress.tls.secretName }} ++ {{- end }} ++{{- end }} +diff --git a/helm-chart/eoapi/templates/services/ingress.yaml b/helm-chart/eoapi/templates/services/ingress.yaml +index 3ddfa59..1609317 100644 +--- a/helm-chart/eoapi/templates/services/ingress.yaml ++++ b/helm-chart/eoapi/templates/services/ingress.yaml +@@ -12,6 +12,10 @@ metadata: + labels: + app: eoapi-{{ .Release.Name }} + annotations: ++ {{- if eq .Values.ingress.className "nginx" }} ++ nginx.ingress.kubernetes.io/rewrite-target: /$2 ++ nginx.ingress.kubernetes.io/use-regex: "true" ++ {{- end }} + {{- if .Values.ingress.annotations }} + {{ toYaml .Values.ingress.annotations | indent 4 }} + {{- end }} +@@ -31,8 +35,8 @@ spec: + http: + paths: + {{- if and .Values.raster.enabled (or (not (hasKey .Values.raster "ingress")) .Values.raster.ingress.enabled) }} +- - pathType: {{ .Values.ingress.pathType }} +- path: /raster{{ .Values.ingress.pathSuffix }} ++ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} ++ path: /raster{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} + backend: + service: + name: raster-{{ $.Release.Name }} +@@ -41,8 +45,8 @@ spec: + {{- end }} + + {{- if and .Values.stac.enabled (or (not (hasKey .Values.stac "ingress")) .Values.stac.ingress.enabled) }} +- - pathType: {{ .Values.ingress.pathType }} +- path: /stac{{ .Values.ingress.pathSuffix }} ++ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} ++ path: /stac{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} + backend: + service: + name: stac-{{ $.Release.Name }} +@@ -51,8 +55,8 @@ spec: + {{- end }} + + {{- if and .Values.vector.enabled (or (not (hasKey .Values.vector "ingress")) .Values.vector.ingress.enabled) }} +- - pathType: {{ .Values.ingress.pathType }} +- path: /vector{{ .Values.ingress.pathSuffix }} ++ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} ++ path: /vector{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} + backend: + service: + name: vector-{{ $.Release.Name }} +@@ -61,8 +65,8 @@ spec: + {{- end }} + + {{- if and .Values.multidim.enabled (or (not (hasKey .Values.multidim "ingress")) .Values.multidim.ingress.enabled) }} +- - pathType: {{ .Values.ingress.pathType }} +- path: /multidim{{ .Values.ingress.pathSuffix }} ++ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} ++ path: /multidim{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} + backend: + service: + name: multidim-{{ $.Release.Name }} +@@ -70,19 +74,8 @@ spec: + number: {{ .Values.service.port }} + {{- end }} + +- {{- if and .Values.browser.enabled (or (not (hasKey .Values.browser "ingress")) .Values.browser.ingress.enabled) }} +- # We need a separate path because browser does not play well with nginx rewrite_path directive +- - pathType: {{ .Values.ingress.pathType }} +- path: "/browser" +- backend: +- service: +- name: browser-{{ $.Release.Name }} +- port: +- number: 8080 +- {{- end }} +- + {{- if .Values.docServer.enabled }} +- - pathType: {{ $.Values.ingress.pathType | default "Prefix" }} ++ - pathType: Prefix + path: "/{{ $.Values.ingress.rootPath | default "" }}" + backend: + service: +diff --git a/helm-chart/eoapi/templates/services/traefik-middleware.yaml b/helm-chart/eoapi/templates/services/traefik-middleware.yaml +index 0c9718c..2e252cc 100644 +--- a/helm-chart/eoapi/templates/services/traefik-middleware.yaml ++++ b/helm-chart/eoapi/templates/services/traefik-middleware.yaml +@@ -19,7 +19,4 @@ spec: + {{- if .Values.multidim.enabled }} + - /multidim + {{- end }} +- # {{- if .Values.browser.enabled }} +- # - /browser +- # {{- end }} + {{- end }} + +diff --git a/helm-chart/eoapi/values.schema.json b/helm-chart/eoapi/values.schema.json +index 7d7f7a7..03af347 100644 +--- a/helm-chart/eoapi/values.schema.json ++++ b/helm-chart/eoapi/values.schema.json +@@ -6,6 +6,10 @@ + "gitSha" + ], + "properties": { ++ "previousVersion": { ++ "type": "string", ++ "description": "Previous version when upgrading. Used for migrations (e.g., when upgrading from pre-0.7.0 versions)" ++ }, + "gitSha": { + "type": "string", + "description": "Git SHA of the deployment" +@@ -65,15 +69,6 @@ + "enum": ["nginx", "traefik"], + "description": "Ingress controller class name" + }, +- "pathType": { +- "type": "string", +- "enum": ["Prefix", "ImplementationSpecific"], +- "description": "Ingress path type" +- }, +- "pathSuffix": { +- "type": "string", +- "description": "Suffix to add to service paths" +- }, + "rootPath": { + "type": "string", + "description": "Root path for doc server" +diff --git a/helm-chart/eoapi/values.yaml b/helm-chart/eoapi/values.yaml +index 96ef7c8..0472c0c 100644 +--- a/helm-chart/eoapi/values.yaml ++++ b/helm-chart/eoapi/values.yaml +@@ -41,11 +41,6 @@ ingress: + enabled: true + # ingressClassName: "nginx" or "traefik" + className: "nginx" +- # Path configuration +- pathType: "Prefix" # Can be "Prefix" or "ImplementationSpecific" based on controller +- # NOTE: When using nginx ingress controller with regex in pathSuffix, +- # you must set pathType to "ImplementationSpecific". See issue #189 for more context. +- pathSuffix: "" # Add a suffix to service paths (e.g. "(/|$)(.*)" for nginx regex) + rootPath: "" # Root path for doc server + # Host configuration + host: "" +@@ -103,6 +98,8 @@ postgresql: + # this is declared as a dependency of eoapi in helm-chart/eoapi/Chart.yaml + postgrescluster: + enabled: true ++ # The name of the postgres cluster ++ # name: pgstac + postgresVersion: 16 + postGISVersion: "3.4" + pgBouncerReplicas: 1 +@@ -470,3 +467,10 @@ browser: + + docServer: + enabled: true ++ ++# Version being upgraded from, used for migration purposes ++# Dont set the value in the values.yaml file ++# prefer to set it in the command line ++# helm upgrade --set previousVersion=$PREVIOUS_VERSION ++# or in the CI/CD pipeline ++previousVersion: "" +\ No newline at end of file +diff --git a/helm-chart/postgrescluster/values.yaml b/helm-chart/postgrescluster/values.yaml +index 4843b3d..93c1b88 100644 +--- a/helm-chart/postgrescluster/values.yaml ++++ b/helm-chart/postgrescluster/values.yaml +@@ -10,6 +10,9 @@ + # name is the name of the cluster. This defaults to the name of the Helm + # release. + # name: hippo ++# namespace is the namespace that the cluster will be deployed in. This defaults ++# to the namespace of the Helm release. ++# namespace: hippo + + # postgresVersion sets the version to deploy. This version number needs to be + # available as one of the "RELATED_IMAGE_POSTGRES_..." images as part of the PGO From a8a4ba6ed7aebcc6ae8269039897bf9345bc3d56 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 14:21:14 +0200 Subject: [PATCH 6/8] Update configuration documentation to enhance clarity and detail for required values, database options, and service settings --- docs/configuration.md | 178 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 145 insertions(+), 33 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index c82abeaf..c1bd4f8d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2,60 +2,172 @@ ## Required Values -The required values to pass to `helm install` or `helm template` commands can be found by showing what is validated: +The required values to pass to `helm install` or `helm template` commands can be found in our schema validation: ```bash -$ head -n 9 /values.schema.json { - "$schema": "http://json-schema.org/schema#", - "type": "object", "required": [ "service", "gitSha" - ], + ] +} ``` -Most of the required fields have common-sense defaults. -The table below and the `values.yaml` comments should explain what the options and defaults are: +Most fields have sensible defaults. Here are the core configuration options: -| **Values Key** | **Description** | **Default** | **Choices** | -|:-------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|:------------|:------------------------| -| `service.port` | the port that all vector/raster/stac services run on
used in `kind: Service` and `kind: Ingress` | 8080 | your favorite port | -| `gitSha` | sha attached to a `kind: Deployment` key `metadata.labels` | gitshaABC123 | your favorite sha | +| **Values Key** | **Description** | **Default** | **Choices** | +|:--------------|:----------------|:------------|:------------| +| `service.port` | Port for all services (vector/raster/stac) | 8080 | any valid port | +| `gitSha` | SHA for deployment tracking | gitshaABC123 | any valid SHA | +| `previousVersion` | Previous version during upgrades | "" | semantic version | +## Database Configuration ---- +### PostgreSQL Cluster (Default) -## Default Configuration +Using Crunchydata's PostgreSQL Operator (`postgresql.type: "postgrescluster"`): -Running `helm install` from https://devseed.com/eoapi-k8s/ should spin up similar infrastructure in EKS or GKE: +| **Values Key** | **Description** | **Default** | **Choices** | +|:--------------|:----------------|:------------|:------------| +| `postgrescluster.enabled` | Enable PostgreSQL cluster | true | true/false | +| `postgrescluster.name` | Cluster name | Release name | any valid k8s name | +| `postgrescluster.postgresVersion` | PostgreSQL version | 16 | supported versions | +| `postgrescluster.postGISVersion` | PostGIS version | "3.4" | supported versions | -In EKS or GKE you'll by default get: +### External Database -* a HA PostgreSQL database deployment and service via [Crunchdata's Postgresl Operator](https://access.crunchydata.com/documentation/postgres-operator) -* the same vector and raster data fixtures used for testing loaded into the DB -* a load balancer and nginx-compatible ingress with the following path rewrites: - * a `/stac` service for `stac_fastapi.pgstac` - * a `/raster` service for `titler.pgstac` - * a `/vector` service for `tipg.pgstac` +For external databases, set `postgresql.type` to either: -Here's a simplified high-level diagram to grok: -![](./images/default_architecture.png) +1. Using plaintext credentials (`external-plaintext`): +```yaml +postgresql: + type: "external-plaintext" + external: + host: "your-host" + port: "5432" + database: "eoapi" + credentials: + username: "eoapi" + password: "your-password" +``` ---- +2. Using Kubernetes secrets (`external-secret`): +```yaml +postgresql: + type: "external-secret" + external: + existingSecret: + name: "your-secret" + keys: + username: "username" + password: "password" + host: "your-host" # can also be in secret + port: "5432" # can also be in secret + database: "eoapi" # can also be in secret +``` -## Additional Options +## Ingress Configuration + +Unified ingress configuration supporting both NGINX and Traefik: + +| **Values Key** | **Description** | **Default** | **Choices** | +|:--------------|:----------------|:------------|:------------| +| `ingress.enabled` | Enable ingress | true | true/false | +| `ingress.className` | Ingress controller | "nginx" | "nginx", "traefik" | +| `ingress.host` | Ingress hostname | "" | valid hostname | +| `ingress.rootPath` | Doc server root path | "" | valid path | + +See [Unified Ingress Configuration](./unified-ingress.md) for detailed setup. + +## Service Configuration + +Each service (stac, raster, vector, multidim) supports: + +| **Values Key** | **Description** | **Default** | **Choices** | +|:--------------|:----------------|:------------|:------------| +| `{service}.enabled` | Enable the service | varies | true/false | +| `{service}.image.name` | Container image | varies | valid image | +| `{service}.image.tag` | Image tag | varies | valid tag | +| `{service}.autoscaling.enabled` | Enable HPA | false | true/false | +| `{service}.autoscaling.type` | Scaling metric | "requestRate" | "cpu", "requestRate", "both" | + +Example service configuration: +```yaml +raster: + enabled: true + autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 10 + type: "requestRate" + targets: + cpu: 75 + requestRate: "100000m" +``` ---- +## STAC Browser -### Key `autoscaling` +| **Values Key** | **Description** | **Default** | **Choices** | +|:--------------|:----------------|:------------|:------------| +| `browser.enabled` | Enable STAC browser | true | true/false | +| `browser.replicaCount` | Number of replicas | 1 | integer > 0 | +| `browser.ingress.enabled` | Enable browser ingress | true | true/false | -#### `autoscaling.type` +## Deployment Architecture -| **Values Key** | **Description** | **Default** | **Choices** | -|:-----------------|:-----------------------------------------------------------------------------------------------------------------------------------------------|:-----------|:--------------| -| `autoscaling.type` | a simple example of a default metric (`cpu`) and custom metric (`requestRate`) to scale by. If selecting `both` the metric that results in the "highest amount of change" wins. See [k8s documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#scaling-on-multiple-metrics) for more info | requestRate | requestRate
cpu
both
| +When using default settings, the deployment looks like this: +![](./images/default_architecture.png) + +The deployment includes: +- HA PostgreSQL database (via PostgreSQL Operator) +- Sample data fixtures +- Load balancer with path-based routing: + - `/stac` → STAC API + - `/raster` → Titiler + - `/vector` → TiPG + - `/browser` → STAC Browser + - `/` → Documentation + +## Advanced Configuration + +### Autoscaling Behavior + +Fine-tune scaling behavior: + +```yaml +autoscaling: + behaviour: + scaleDown: + stabilizationWindowSeconds: 60 + scaleUp: + stabilizationWindowSeconds: 0 +``` -#### `autoscaling.behaviour.[scaleDown||scaleUp]` +See [Kubernetes HPA documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior) for details. -These are normal k8s autoscaling pass throughs. They are stablization windows in seconds to for scaling up or down to prevent flapping from happening. Read more about [the options on the k8s documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior) \ No newline at end of file +### Resource Requirements + +Each service can have custom resource limits: + +```yaml +settings: + resources: + limits: + cpu: "768m" + memory: "1024Mi" + requests: + cpu: "256m" + memory: "512Mi" +``` + +### Additional Service Settings + +Each service also supports: +```yaml +settings: + labels: {} # Additional pod labels + extraEnvFrom: [] # Additional environment variables from references + extraVolumeMounts: [] # Additional volume mounts + extraVolumes: [] # Additional volumes + envVars: {} # Environment variables +``` From 8dbf8159ed0ee8c286bc43effee6faebc075910c Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 14:37:20 +0200 Subject: [PATCH 7/8] Update changelog and chart version for v0.7.1 release, including breaking changes and new features --- CHANGELOG.md | 16 +- helm-chart/eoapi/Chart.yaml | 7 +- helm-chart/eoapi/diff | 437 ------------------------------------ 3 files changed, 13 insertions(+), 447 deletions(-) delete mode 100644 helm-chart/eoapi/diff diff --git a/CHANGELOG.md b/CHANGELOG.md index acaef3b5..1e2f22d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,21 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [v0.7.1] - Unreleased +## [v0.7.1] - 2025-05-16 ### Breaking Changes - Remove hard-coded cert-manager configuration from ingress template [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) -- Remove `pathType` and `pathSuffix` configurations in favor of controller-specific defaults +- Remove `pathType` and `pathSuffix` configurations in favor of controller-specific defaults [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) ### Added -- Add upgrade job to handle database permissions for migrations from pre-0.7.0 versions -- Add separate ingress configuration for STAC browser -- Support custom cluster naming via `postgrescluster.name` +- Add upgrade job to handle database permissions for migrations from pre-0.7.0 versions [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) +- Add separate ingress configuration for STAC browser [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) +- Support custom cluster naming via `postgrescluster.name` [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) ### Changed -- Improve Nginx and Traefik support with controller-specific rewrites -- Increase bootstrap job retry limit to 3 attempts -- Enhance secret handling with custom PostgreSQL cluster names +- Improve Nginx and Traefik support with controller-specific rewrites [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) +- Increase bootstrap job retry limit to 3 attempts [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) +- Enhance secret handling with custom PostgreSQL cluster names [#228](https://github.com/developmentseed/eoapi-k8s/pull/228) - Simplify TLS configuration to allow user-controlled certificate management [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) - Update documentation with comprehensive cert-manager setup guide [#227](https://github.com/developmentseed/eoapi-k8s/pull/227) diff --git a/helm-chart/eoapi/Chart.yaml b/helm-chart/eoapi/Chart.yaml index 530c35de..d69f21fc 100644 --- a/helm-chart/eoapi/Chart.yaml +++ b/helm-chart/eoapi/Chart.yaml @@ -16,7 +16,10 @@ kubeVersion: ">=1.23.0-0" icon: https://eoapi.dev/img/eoAPI.png annotations: artifacthub.io/changes: | - - Adds integration with Artifacthub.io + - Remove pathType and pathSuffix configurations + - Add upgrade job for pre-0.7.0 migrations + - Add separate browser ingress configuration + - Support custom PostgreSQL cluster naming artifacthub.io/links: | - name: GitHub Repository url: https://github.com/developmentseed/eoapi-k8s @@ -36,7 +39,7 @@ annotations: # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: "0.7.0" +version: "0.7.1" # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm-chart/eoapi/diff b/helm-chart/eoapi/diff deleted file mode 100644 index b5e0b478..00000000 --- a/helm-chart/eoapi/diff +++ /dev/null @@ -1,437 +0,0 @@ - - -diff --git a/docs/stac-auth-proxy.md b/docs/stac-auth-proxy.md -index f0fd960..2c06d92 100644 ---- a/docs/stac-auth-proxy.md -+++ b/docs/stac-auth-proxy.md -@@ -23,27 +23,6 @@ raster: - enabled: true - ``` - --### 2. Template Changes -- --The ingress template now checks service-specific settings: -- --```yaml --{{- if and .Values.stac.enabled (or (not (hasKey .Values.stac "ingress")) .Values.stac.ingress.enabled) }} --- pathType: {{ .Values.ingress.pathType }} -- path: /stac{{ .Values.ingress.pathSuffix }} -- backend: -- service: -- name: stac -- port: -- number: {{ .Values.service.port }} --{{- end }} --``` -- --This ensures: --- Service paths are only included if the service and its ingress are enabled --- Backward compatibility is maintained (ingress enabled by default) --- Clean separation of service configurations -- - ## Deployment Guide - - ### 1. Configure EOAPI-K8S -diff --git a/docs/unified-ingress.md b/docs/unified-ingress.md -index 77157dd..24d6391 100644 ---- a/docs/unified-ingress.md -+++ b/docs/unified-ingress.md -@@ -23,8 +23,6 @@ ingress: - # ingressClassName: "nginx" or "traefik" - className: "nginx" - # Path configuration -- pathType: "Prefix" # Can be "Prefix" or "ImplementationSpecific" based on controller -- pathSuffix: "" # Add a suffix to service paths (e.g. "(/|$)(.*)" for nginx regex) - rootPath: "" # Root path for doc server - # Host configuration - host: "" - -diff --git a/helm-chart/eoapi/samples/values-with-nginx.yaml b/helm-chart/eoapi/samples/values-with-nginx.yaml -new file mode 100644 -index 0000000..737639e ---- /dev/null -+++ b/helm-chart/eoapi/samples/values-with-nginx.yaml -@@ -0,0 +1,21 @@ -+ingress: -+ annotations: -+ nginx.ingress.kubernetes.io/rewrite-target: /$2 -+ className: nginx -+ enabled: true -+ host: eoapi.local -+ tls: -+ certManager: false -+ enabled: true -+ secretName: eoapi-tls -+namespace: eoapi -+postgrescluster: -+ enabled: true -+ name: pgstac -+resources: -+ limits: -+ cpu: 1000m -+ memory: 1Gi -+ requests: -+ cpu: 200m -+ memory: 256Mi -\ No newline at end of file -diff --git a/helm-chart/eoapi/templates/_helpers.tpl b/helm-chart/eoapi/templates/_helpers.tpl -index ebb38e6..df3c20a 100644 ---- a/helm-chart/eoapi/templates/_helpers.tpl -+++ b/helm-chart/eoapi/templates/_helpers.tpl -@@ -85,80 +85,80 @@ PostgreSQL cluster secrets - - name: PGUSER - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: user - - name: PGPORT - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: port - - name: PGHOST - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: host - - name: PGPASSWORD - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: password - - name: PGDATABASE - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: dbname - - name: PGBOUNCER_URI - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: pgbouncer-uri - # Legacy variables for backward compatibility - - name: POSTGRES_USER - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: user - - name: POSTGRES_PORT - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: port - - name: POSTGRES_HOST - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: host - - name: POSTGRES_HOST_READER - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: host - - name: POSTGRES_HOST_WRITER - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: host - - name: POSTGRES_PASS - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: password - - name: POSTGRES_DBNAME - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: dbname - - name: DATABASE_URL - valueFrom: - secretKeyRef: -- name: {{ $.Release.Name }}-pguser-{{ index $v "name" }} -+ name: {{ $.Values.postgrescluster.name | default $.Release.Name }}-pguser-{{ index $v "name" }} - key: uri - {{- end }} - {{- end }} - - name: PGADMIN_URI - valueFrom: - secretKeyRef: -- name: {{ .Release.Name }}-pguser-postgres -+ name: {{ .Values.postgrescluster.name | default .Release.Name }}-pguser-postgres - key: uri - {{- end }} - -diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml -index 2459bf2..98feb83 100644 ---- a/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml -+++ b/helm-chart/eoapi/templates/pgstacbootstrap/configmap.yaml -@@ -50,10 +50,6 @@ apiVersion: v1 - kind: ConfigMap - metadata: - name: initdb -- annotations: -- helm.sh/hook: "post-install,post-upgrade" -- helm.sh/hook-weight: "-6" -- helm.sh/hook-delete-policy: "before-hook-creation,hook-succeeded" - data: - initdb.sql: | - \c {{ .Values.pgstacBootstrap.settings.database }} - -diff --git a/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml b/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml -index fa9b60f..473ef94 100644 ---- a/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml -+++ b/helm-chart/eoapi/templates/pgstacbootstrap/job.yaml -@@ -154,5 +154,5 @@ spec: - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} -- backoffLimit: 1 -+ backoffLimit: 3 - {{- end }} -diff --git a/helm-chart/eoapi/templates/services/ingress-browser.yaml b/helm-chart/eoapi/templates/services/ingress-browser.yaml -new file mode 100644 -index 0000000..ea79901 ---- /dev/null -+++ b/helm-chart/eoapi/templates/services/ingress-browser.yaml -@@ -0,0 +1,53 @@ -+# We need a separate ingress because browser has the prefix /browser hardcoded in the code -+{{- if and .Values.browser.enabled .Values.ingress.enabled }} -+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} -+apiVersion: networking.k8s.io/v1 -+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }} -+apiVersion: networking.k8s.io/v1beta1 -+{{- else }} -+apiVersion: extensions/v1beta1 -+{{- end }} -+kind: Ingress -+metadata: -+ name: eoapi-ingress-browser-{{ .Release.Name }} -+ labels: -+ app: eoapi-{{ .Release.Name }} -+ annotations: -+ {{- if .Values.ingress.annotations }} -+{{ toYaml .Values.ingress.annotations | indent 4 }} -+ {{- end }} -+ {{- if eq .Values.ingress.className "nginx" }} -+ nginx.ingress.kubernetes.io/rewrite-target: /browser/$2 -+ nginx.ingress.kubernetes.io/use-regex: "true" -+ {{- end }} -+ # Temporary annotations for Traefik until uvicorn support real prefix in ASGI: https://github.com/encode/uvicorn/discussions/2490 -+ {{- if eq .Values.ingress.className "traefik" }} -+ traefik.ingress.kubernetes.io/router.entrypoints: web -+ traefik.ingress.kubernetes.io/router.middlewares: {{ $.Release.Namespace }}-strip-prefix-middleware-{{ $.Release.Name }}@kubernetescrd -+ {{- end }} -+spec: -+ {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} -+ ingressClassName: {{ .Values.ingress.className }} -+ {{- end }} -+ rules: -+ - {{- if .Values.ingress.host }} -+ host: {{ .Values.ingress.host }} -+ {{- end }} -+ http: -+ paths: -+ {{- if and .Values.browser.enabled (or (not (hasKey .Values.browser "ingress")) .Values.browser.ingress.enabled) }} -+ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} -+ path: "/browser{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }}" -+ backend: -+ service: -+ name: browser-{{ $.Release.Name }} -+ port: -+ number: 8080 -+ {{- end }} -+ {{- if and .Values.ingress.host .Values.ingress.tls.enabled }} -+ tls: -+ - hosts: -+ - {{ .Values.ingress.host }} -+ secretName: {{ .Values.ingress.tls.secretName }} -+ {{- end }} -+{{- end }} -diff --git a/helm-chart/eoapi/templates/services/ingress.yaml b/helm-chart/eoapi/templates/services/ingress.yaml -index 3ddfa59..1609317 100644 ---- a/helm-chart/eoapi/templates/services/ingress.yaml -+++ b/helm-chart/eoapi/templates/services/ingress.yaml -@@ -12,6 +12,10 @@ metadata: - labels: - app: eoapi-{{ .Release.Name }} - annotations: -+ {{- if eq .Values.ingress.className "nginx" }} -+ nginx.ingress.kubernetes.io/rewrite-target: /$2 -+ nginx.ingress.kubernetes.io/use-regex: "true" -+ {{- end }} - {{- if .Values.ingress.annotations }} - {{ toYaml .Values.ingress.annotations | indent 4 }} - {{- end }} -@@ -31,8 +35,8 @@ spec: - http: - paths: - {{- if and .Values.raster.enabled (or (not (hasKey .Values.raster "ingress")) .Values.raster.ingress.enabled) }} -- - pathType: {{ .Values.ingress.pathType }} -- path: /raster{{ .Values.ingress.pathSuffix }} -+ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} -+ path: /raster{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} - backend: - service: - name: raster-{{ $.Release.Name }} -@@ -41,8 +45,8 @@ spec: - {{- end }} - - {{- if and .Values.stac.enabled (or (not (hasKey .Values.stac "ingress")) .Values.stac.ingress.enabled) }} -- - pathType: {{ .Values.ingress.pathType }} -- path: /stac{{ .Values.ingress.pathSuffix }} -+ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} -+ path: /stac{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} - backend: - service: - name: stac-{{ $.Release.Name }} -@@ -51,8 +55,8 @@ spec: - {{- end }} - - {{- if and .Values.vector.enabled (or (not (hasKey .Values.vector "ingress")) .Values.vector.ingress.enabled) }} -- - pathType: {{ .Values.ingress.pathType }} -- path: /vector{{ .Values.ingress.pathSuffix }} -+ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} -+ path: /vector{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} - backend: - service: - name: vector-{{ $.Release.Name }} -@@ -61,8 +65,8 @@ spec: - {{- end }} - - {{- if and .Values.multidim.enabled (or (not (hasKey .Values.multidim "ingress")) .Values.multidim.ingress.enabled) }} -- - pathType: {{ .Values.ingress.pathType }} -- path: /multidim{{ .Values.ingress.pathSuffix }} -+ - pathType: {{ if eq .Values.ingress.className "nginx" }}ImplementationSpecific{{ else }}Prefix{{ end }} -+ path: /multidim{{ if eq .Values.ingress.className "nginx" }}(/|$)(.*){{ end }} - backend: - service: - name: multidim-{{ $.Release.Name }} -@@ -70,19 +74,8 @@ spec: - number: {{ .Values.service.port }} - {{- end }} - -- {{- if and .Values.browser.enabled (or (not (hasKey .Values.browser "ingress")) .Values.browser.ingress.enabled) }} -- # We need a separate path because browser does not play well with nginx rewrite_path directive -- - pathType: {{ .Values.ingress.pathType }} -- path: "/browser" -- backend: -- service: -- name: browser-{{ $.Release.Name }} -- port: -- number: 8080 -- {{- end }} -- - {{- if .Values.docServer.enabled }} -- - pathType: {{ $.Values.ingress.pathType | default "Prefix" }} -+ - pathType: Prefix - path: "/{{ $.Values.ingress.rootPath | default "" }}" - backend: - service: -diff --git a/helm-chart/eoapi/templates/services/traefik-middleware.yaml b/helm-chart/eoapi/templates/services/traefik-middleware.yaml -index 0c9718c..2e252cc 100644 ---- a/helm-chart/eoapi/templates/services/traefik-middleware.yaml -+++ b/helm-chart/eoapi/templates/services/traefik-middleware.yaml -@@ -19,7 +19,4 @@ spec: - {{- if .Values.multidim.enabled }} - - /multidim - {{- end }} -- # {{- if .Values.browser.enabled }} -- # - /browser -- # {{- end }} - {{- end }} - -diff --git a/helm-chart/eoapi/values.schema.json b/helm-chart/eoapi/values.schema.json -index 7d7f7a7..03af347 100644 ---- a/helm-chart/eoapi/values.schema.json -+++ b/helm-chart/eoapi/values.schema.json -@@ -6,6 +6,10 @@ - "gitSha" - ], - "properties": { -+ "previousVersion": { -+ "type": "string", -+ "description": "Previous version when upgrading. Used for migrations (e.g., when upgrading from pre-0.7.0 versions)" -+ }, - "gitSha": { - "type": "string", - "description": "Git SHA of the deployment" -@@ -65,15 +69,6 @@ - "enum": ["nginx", "traefik"], - "description": "Ingress controller class name" - }, -- "pathType": { -- "type": "string", -- "enum": ["Prefix", "ImplementationSpecific"], -- "description": "Ingress path type" -- }, -- "pathSuffix": { -- "type": "string", -- "description": "Suffix to add to service paths" -- }, - "rootPath": { - "type": "string", - "description": "Root path for doc server" -diff --git a/helm-chart/eoapi/values.yaml b/helm-chart/eoapi/values.yaml -index 96ef7c8..0472c0c 100644 ---- a/helm-chart/eoapi/values.yaml -+++ b/helm-chart/eoapi/values.yaml -@@ -41,11 +41,6 @@ ingress: - enabled: true - # ingressClassName: "nginx" or "traefik" - className: "nginx" -- # Path configuration -- pathType: "Prefix" # Can be "Prefix" or "ImplementationSpecific" based on controller -- # NOTE: When using nginx ingress controller with regex in pathSuffix, -- # you must set pathType to "ImplementationSpecific". See issue #189 for more context. -- pathSuffix: "" # Add a suffix to service paths (e.g. "(/|$)(.*)" for nginx regex) - rootPath: "" # Root path for doc server - # Host configuration - host: "" -@@ -103,6 +98,8 @@ postgresql: - # this is declared as a dependency of eoapi in helm-chart/eoapi/Chart.yaml - postgrescluster: - enabled: true -+ # The name of the postgres cluster -+ # name: pgstac - postgresVersion: 16 - postGISVersion: "3.4" - pgBouncerReplicas: 1 -@@ -470,3 +467,10 @@ browser: - - docServer: - enabled: true -+ -+# Version being upgraded from, used for migration purposes -+# Dont set the value in the values.yaml file -+# prefer to set it in the command line -+# helm upgrade --set previousVersion=$PREVIOUS_VERSION -+# or in the CI/CD pipeline -+previousVersion: "" -\ No newline at end of file -diff --git a/helm-chart/postgrescluster/values.yaml b/helm-chart/postgrescluster/values.yaml -index 4843b3d..93c1b88 100644 ---- a/helm-chart/postgrescluster/values.yaml -+++ b/helm-chart/postgrescluster/values.yaml -@@ -10,6 +10,9 @@ - # name is the name of the cluster. This defaults to the name of the Helm - # release. - # name: hippo -+# namespace is the namespace that the cluster will be deployed in. This defaults -+# to the namespace of the Helm release. -+# namespace: hippo - - # postgresVersion sets the version to deploy. This version number needs to be - # available as one of the "RELATED_IMAGE_POSTGRES_..." images as part of the PGO From 71631c6584e7a435ca117b9c94bfcfe675019860 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 16 May 2025 15:00:30 +0200 Subject: [PATCH 8/8] Update docs/unified-ingress.md Co-authored-by: Jonas --- docs/unified-ingress.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/unified-ingress.md b/docs/unified-ingress.md index 2b58d5ce..ef7a636a 100644 --- a/docs/unified-ingress.md +++ b/docs/unified-ingress.md @@ -4,7 +4,7 @@ This document describes the unified ingress approach implemented in the eoAPI He ## Overview -As of version 0.7.0, eoAPI uses an even more streamlined ingress configuration with smart defaults for different controllers. This approach: +eoAPI includes a streamlined ingress configuration with smart defaults for different controllers. This approach: - Eliminates manual pathType and suffix configurations - Uses controller-specific optimizations for NGINX and Traefik