Upgrade to GoodData.CN 4.0
This guide describes the one-time migration steps and breaking changes you need to handle when upgrading to GoodData.CN 4.0. For the general upgrade procedure and version-specific upgrade notes, see Upgrade GoodData.CN.
Etcd Configuration Updates
GoodData.CN exposes additional Helm values to control how etcd is deployed and used by platform services. This is useful when migrating an existing deployment between etcd configurations.
Deprecation Notice
useInternalQuiverEtcd has been removed. Use useInternalGDEtcd with customEtcd instead.
New Values
useInternalGDEtcd
useInternalGDEtcd: false
# If set to true, Quiver will use the internal custom etcd if customEtcd.enabled is also true.
# If customEtcd.enabled is false, Quiver tries to use external etcd instead.customEtcd
customEtcd deploys a GoodData-managed etcd StatefulSet. The annotated example
below shows the available keys; for the authoritative current defaults, see the
Helm Chart Values Reference.
customEtcd:
# Enable the custom etcd StatefulSet deployment
enabled: false
# Number of etcd replicas (should be an odd number for quorum)
replicaCount: 3
image:
# etcd image name (uses repositoryPrefix from global/cascade settings)
name: etcd
# etcd image tag
tag: <ETCD_IMAGE_TAG>
service:
# Client port for etcd connections
clientPort: 2379
# Peer port for etcd cluster communication
peerPort: 2380
# Metrics port for Prometheus scraping
metricsPort: 8080
# Pod annotations
podAnnotations: {}
# Pod labels
podLabels: {}
# Resources for etcd container
resources:
requests:
cpu: 200m
memory: 768Mi
limits:
cpu: 400m
memory: 1Gi
podSecurityContext:
fsGroupChangePolicy: Always
fsGroup: 1001
containerSecurityContext:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
readOnlyRootFilesystem: true
# Persistence configuration for etcd data
persistence:
# Storage size for etcd data PVC
size: 8Gi
# Storage class (empty uses cluster default)
storageClassName: ""
# Pod anti-affinity ensures etcd pods are spread across different nodes
antiAffinity:
enabled: true
type: requiredDuringSchedulingIgnoredDuringExecution
topologyKey: kubernetes.io/hostname
# Liveness probe configuration
livenessProbe:
path: /livez
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
# Readiness probe configuration
readinessProbe:
path: /readyz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
# Auto compaction configuration
autoCompaction:
mode: periodic
retention: 5m
# Snapshot count for compaction trigger
snapshotCount: 5000
# Defragmentation CronJob configuration
defrag:
enabled: true
schedule: "15 3 * * *"
pauseDuration: "1m"
commandTimeout: "20s"
resources:
limits:
cpu: 50m
memory: 50Mi
# PodMonitor configuration for Prometheus Operator
podMonitor:
enabled: true
interval: 20s
scrapeTimeout: 10s
path: /metrics
port: etcd-metricsHow to Decide What to Use
- If you run external etcd, set
useInternalGDEtcd: falseandcustomEtcd.enabled: false, and configureservice.etcd.*. - If you want to run internal etcd managed by GoodData, set:
customEtcd.enabled: trueuseInternalGDEtcd: true
PostgreSQL Configuration Updates
GoodData.CN provides Helm values for controlling PostgreSQL deployment and connectivity used by platform services. The Bitnami postgresql-ha subchart has been removed from the chart, so these values are important if you still need to migrate an existing deployment to an externally managed PostgreSQL instance.
External PostgreSQL Configuration
In GoodData.CN 4.0, configure your external PostgreSQL connection with the following Helm values:
service:
postgres:
host: "<POSTGRES_HOST>"
port: 5432
username: postgres
password: "<POSTGRES_PASSWORD>"
# Alternative: reference an existing Kubernetes secret
# existingSecret: "my-postgres-secret"If you use an existing Kubernetes secret, it must contain the postgresql-password key.
deployPostgresHA removed in 4.0
The deployPostgresHA value was removed together with the Bitnami postgresql-ha subchart. Delete it from your Helm values file before you upgrade. Only service.postgres.* configures the database connection in 4.0.
Databases Used by GoodData.CN
Depending on your deployment, GoodData.CN uses the following databases:
| Database | Service | Required When |
|---|---|---|
md | metadata-api | Always |
automation | automation | Always |
genai | automation | If deployGenAIService: true |
dex | dex | If deployDexIdP: true |
gw | gateway-forge | Always (as of 4.0, gateway-forge is a core service) |
How to Decide What to Use
- If you already use external PostgreSQL, your
service.postgres.*settings carry over unchanged. Remove the now-unrecognizeddeployPostgresHAkey from your Helm values file. - If you are still running the Bitnami
postgresql-hasubchart on a pre-4.0 GoodData.CN version, migrate to an external PostgreSQL instance before you upgrade to 4.0, where the subchart is no longer available.
PostgreSQL Migration Guide
This procedure describes how to migrate from the Bitnami postgresql-ha subchart to an external PostgreSQL instance by using pg_dump and pg_restore. The migration requires planned downtime. Complete this migration before upgrading to a GoodData.CN version where the postgresql-ha subchart is no longer available.
Prerequisites
- Access to the Kubernetes cluster where GoodData.CN is deployed
- A provisioned external PostgreSQL instance
- Network connectivity between your Kubernetes namespace and the new PostgreSQL instance
kubectlconfigured with access to the target namespace- Sufficient storage for database dumps
Step 1: Prepare the External PostgreSQL Instance
Create the required databases in your external PostgreSQL instance:
CREATE DATABASE md;
CREATE DATABASE automation;
CREATE DATABASE genai; -- skip if deployGenAIService is false
CREATE DATABASE dex; -- skip if deployDexIdP is false
CREATE DATABASE gw;Create only the optional databases that you need for your deployment.
Step 2: Verify Connectivity
Create a temporary pod with PostgreSQL client tools:
kubectl run pg-debug --rm -it \
--image=postgres:16 \
--restart=Never \
--namespace <NAMESPACE> \
-- bashInside the pod, verify access to the current and new PostgreSQL instances:
export PGPASSWORD='<POSTGRES_PASSWORD>'
psql -h <RELEASE>-db-pgpool -p 5432 -U postgres -c "SELECT version();"
psql -h <NEW_POSTGRES_HOST> -p 5432 -U postgres -c "SELECT version();"Step 3: Scale Down Services
Scale down all services that write to PostgreSQL:
NAMESPACE=<NAMESPACE>
RELEASE=<RELEASE>
kubectl scale deployment ${RELEASE}-metadata-api --replicas=0 -n $NAMESPACE
kubectl scale deployment ${RELEASE}-automation --replicas=0 -n $NAMESPACE
kubectl scale deployment ${RELEASE}-genai --replicas=0 -n $NAMESPACE # skip if deployGenAIService is false
kubectl scale deployment ${RELEASE}-dex --replicas=0 -n $NAMESPACE 2>/dev/null || true # skip if deployDexIdP is false
kubectl scale deployment ${RELEASE}-gateway-md-sink --replicas=0 -n $NAMESPACE 2>/dev/null || trueStep 4: Dump the Databases
export PGPASSWORD='<POSTGRES_PASSWORD>'
SOURCE_HOST=${RELEASE}-db-pgpool
pg_dump -h $SOURCE_HOST -p 5432 -U postgres -d md -Fc -v > /tmp/md.dump
pg_dump -h $SOURCE_HOST -p 5432 -U postgres -d automation -Fc -v > /tmp/automation.dump
pg_dump -h $SOURCE_HOST -p 5432 -U postgres -d genai -Fc -v > /tmp/genai.dump # skip if deployGenAIService is false
pg_dump -h $SOURCE_HOST -p 5432 -U postgres -d dex -Fc -v > /tmp/dex.dump # skip if deployDexIdP is false
pg_dump -h $SOURCE_HOST -p 5432 -U postgres -d gw -Fc -v > /tmp/gw.dumpSkip the optional databases that are not used in your deployment.
Step 5: Restore the Databases
export PGPASSWORD='<POSTGRES_PASSWORD>'
TARGET_HOST=<NEW_POSTGRES_HOST>
pg_restore -h $TARGET_HOST -p 5432 -U postgres -d md -v /tmp/md.dump
pg_restore -h $TARGET_HOST -p 5432 -U postgres -d automation -v /tmp/automation.dump
pg_restore -h $TARGET_HOST -p 5432 -U postgres -d genai -v /tmp/genai.dump # skip if deployGenAIService is false
pg_restore -h $TARGET_HOST -p 5432 -U postgres -d dex -v /tmp/dex.dump # skip if deployDexIdP is false
pg_restore -h $TARGET_HOST -p 5432 -U postgres -d gw -v /tmp/gw.dumpStep 6: Update Helm Values and Upgrade the Release
You still run this step on your current pre-4.0 chart version, so the values file combines two things: deployPostgresHA: false turns off the Bitnami subchart you are migrating away from, and service.postgres.* points the services at the new instance.
# Pre-4.0 chart only. This key no longer exists in 4.0, so delete
# it from your values file before you upgrade to 4.0.
deployPostgresHA: false
service:
postgres:
host: "<NEW_POSTGRES_HOST>"
port: 5432
username: postgres
password: "<POSTGRES_PASSWORD>"
# Alternative: use an existing Kubernetes secret
# existingSecret: "my-postgres-secret"helm upgrade <RELEASE> gooddata/gooddata-cn \
--namespace <NAMESPACE> \
--version <CURRENT_PRE_4_0_CHART_VERSION> \
-f values.yaml \
--reuse-valuesStep 7: Verify the Deployment
After the upgrade, verify that the affected services start successfully and connect to the new database.
API Gateway Authentication Updates
Starting with version 4.5, the API Gateway handles OIDC sign-in, JWT bearer authentication, and API-token validation by default.
Users who are already signed in stay signed in after the upgrade. You do not need to reconfigure your identity provider, change client_id, or ask users to sign in again.
Session Cookies
The API Gateway now uses a server-side session model.
| Cookie | Description |
|---|---|
GD_SESSION_ID | Primary opaque session cookie that points to a server-side session. |
GD_OAUTH_FLOW | Short-lived cookie used during the OIDC redirect step. It is removed after sign-in completes. |
The following legacy cookies are still accepted during the migration window:
SPRING_SEC_SECURITY_CONTEXTSPRING_SEC_OAUTH2_AUTHZ_CLIENT
On the first request after the upgrade, legacy cookies are exchanged for GD_SESSION_ID and cleared automatically.
Cookies are HttpOnly, Secure over HTTPS, use Path=/, and use SameSite=Lax by default. Use the chart-level cookiePolicy value if you need to change the default cookie policy.
Action Required
If a WAF, CDN, reverse proxy, or any other component between the browser and API Gateway filters cookies by name, allow the following cookies:
GD_SESSION_IDGD_OAUTH_FLOW
After you confirm that no users rely on stale legacy sessions, you can remove allow-list rules for the legacy SPRING_SEC_* cookies.
Helm Values
Gateway-side authentication is enabled by default through the following Helm values:
enableGatewayOauth: true
enableGatewayJwt: true
enableGatewayApiTokens: true
apiGw:
oauth:
enabled: true
jwt:
enabled: trueThrough version 4.8.x, you could temporarily opt out by setting these values to false in your Helm values file. The opt-out was removed in 4.9.0, where the API Gateway always handles this authentication. If you set any of these values to false while on 4.0 through 4.8.x, remove the overrides before you upgrade to 4.9.0 or later. See Version 4.9.0 in the upgrade notes.
Other Breaking Changes in GoodData CN 4.0
Network Policy Helm Values Renamed
The following Helm values were renamed:
nginxIngressNamespaceLabelSelectortoingressControllerNamespaceLabelSelectornginxIngressPodLabelSelectortoingressControllerPodLabelSelector
If you use either of the old values in your Helm values file, replace them with the new names before you upgrade.
Deprecated Organization Fields Removed
The ingressClass and gatewayType fields were removed from the Organization custom resource because they were no longer used. They must be removed from the organization’s specification.
Geo Chart Base Map Configuration
In GoodData.CN 4.0, do not use extraEnvVars to configure the base map provider for geo charts and geo area charts. Configure the base map provider through the new apiGw.locationService settings in your custom Helm values instead:
apiGw:
locationService:
plugin: "MapboxLocation"
mapbox:
token: "..."For full details, see Configure Geo Charts and the 4.0 release note.