Upgrade Camunda 8.7 to 8.8 using Helm
Upgrade a Helm-managed Camunda 8 Self-Managed deployment from version 8.7 to 8.8.
Prerequisites
Before upgrading:
- Confirm your deployment is running the latest
8.7.xpatch. If you are upgrading from a version earlier than 8.7, see Upgrading from an earlier version. - Review Prepare for upgrade to confirm upgrade eligibility and complete any required pre-upgrade actions for 8.8.
- Review the Camunda Helm chart version matrix and confirm:
- the Helm chart version that deploys Camunda 8.8 is supported for your Kubernetes version, and
- your Helm client version is supported for that chart.
- Create and verify backups for your Camunda data. See Backup and restore.
- Review your existing
values.yamlfor custom configuration you must migrate toorchestration.*in 8.8 (for example, Ingress rules, external Elasticsearch/OpenSearch connections, index prefixes, exporters, and component overrides). - If your environment uses more than one Elasticsearch or OpenSearch instance for exported Zeebe, Operate, and Tasklist data, consolidate to a single instance before upgrading. See Single Elasticsearch/OpenSearch instance.
- If you use custom index prefixes, review and apply the required prefix changes before upgrading. See Update any custom prefixes.
- Test the upgrade in a non-production environment using a copy of your production configuration.
- If your
values.yamlcontains plaintext secrets, migrate them to Kubernetes secrets before upgrading. See Extract plaintext values and reference them as Kubernetes secrets.
Create your 8.8 values file
Use your existing 8.7 configuration as the starting point for the upgrade.
-
Copy your current
values.yamland name the filevalues-8.8.yaml. -
Download the default values for the Camunda 8.8 Helm chart:
helm repo update
helm show values camunda/camunda-platform --version <CHART_VERSION> > values-8.8-default.yamlTo identify the latest available chart version, run:
helm search repo camunda/camunda-platform --versions -
Compare
values-8.8.yamlwithvalues-8.8-default.yamlto identify:- new configuration options,
- changed defaults, and
- deprecated or removed settings.
-
Update
values-8.8.yamlusing the configuration tables below before runninghelm upgrade.
The examples in this guide show common upgrade scenarios. Your configuration may differ depending on how your deployment is set up (for example, authentication method, Ingress usage, or storage backend).
Update your values file to 8.8
Camunda 8.8 consolidates Zeebe Gateway, Operate, and Tasklist under the Orchestration Cluster (orchestration.*). Use the following tables to update values-8.8.yaml.
Top-level chart keys
| 12.x/8.7 values | 13.x/8.8 values |
|---|---|
postgresql | Move to webModelerPostgresql. |
zeebe | Move to orchestration and use it as the base for the Orchestration Cluster configuration.The type of clusterSize, partitionCount, and replicationFactor changed from integer to string.Consider increasing orchestration.resources because the Orchestration Cluster serves Zeebe, Operate, Tasklist, and the embedded gateway by default. |
View example values files
This example shows how to migrate Zeebe sizing settings and the chart-managed PostgreSQL block to their 8.8 locations.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
zeebe:
clusterSize: 3
partitionCount: 6
replicationFactor: 3
resources:
requests:
cpu: "2"
memory: "8Gi"
limits:
cpu: "4"
memory: "16Gi"
postgresql:
enabled: true
auth:
username: <DB_USERNAME>
password: <DB_PASSWORD>
existingSecret: <DB_SECRET>
database: <DB_NAME>
primary:
persistence:
enabled: true
size: 50Gi
orchestration:
clusterSize: "3"
partitionCount: "6"
replicationFactor: "3"
resources:
requests:
cpu: "2"
memory: "8Gi"
limits:
cpu: "4"
memory: "16Gi"
webModelerPostgresql:
enabled: true
auth:
username: <DB_USERNAME>
password: <DB_PASSWORD>
existingSecret: <DB_SECRET>
database: <DB_NAME>
primary:
persistence:
enabled: true
size: 50Gi
Global Identity keys
| 12.x/8.7 values | 13.x/8.8 values |
|---|---|
global.identity.auth.connectors.* | Move to connectors.security.authentication.oidc.*. |
global.identity.auth.zeebe.* | Move to orchestration.security.authentication.oidc.*. |
global.identity.auth.operate.audience | Add the audience value to orchestration.security.authentication.oidc.backwardsCompatibleAudiences if you need existing clients for that audience to continue working and access the Orchestration Cluster API. |
global.identity.auth.tasklist.audience | Add the audience value to orchestration.security.authentication.oidc.backwardsCompatibleAudiences if you need existing clients for that audience to continue working and access the Orchestration Cluster API. |
global.identity.auth.operate | Remove. Operate runs under the Orchestration Cluster in 8.8. |
global.identity.auth.tasklist | Remove. Tasklist runs under the Orchestration Cluster in 8.8. |
View example values files
This example shows how to move 8.7 global.identity.auth.* settings to 8.8 orchestration.security.authentication.oidc.* and connectors.security.authentication.oidc.*.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
global:
identity:
auth:
issuerBackendUrl: https://<IDP_INTERNAL_URL>/realms/<REALM>
publicIssuerUrl: https://<IDP_PUBLIC_URL>/realms/<REALM>
zeebe:
clientId: <ZEEBE_CLIENT_ID>
existingSecret:
name: <ZEEBE_CLIENT_SECRET>
operate:
clientId: <OPERATE_CLIENT_ID>
audience: <OPERATE_AUDIENCE>
existingSecret:
name: <OPERATE_CLIENT_SECRET>
tasklist:
clientId: <TASKLIST_CLIENT_ID>
audience: <TASKLIST_AUDIENCE>
existingSecret:
name: <TASKLIST_CLIENT_SECRET>
global:
identity:
auth:
issuerBackendUrl: https://<IDP_INTERNAL_URL>/realms/<REALM>
publicIssuerUrl: https://<IDP_PUBLIC_URL>/realms/<REALM>
orchestration:
security:
authentication:
method: oidc
oidc:
clientId: <PRIMARY_CLIENT_ID>
secret:
existingSecret: <PRIMARY_CLIENT_SECRET>
existingSecretKey: <SECRET_KEY>
backwardsCompatibleAudiences:
- <OPERATE_AUDIENCE>
- <TASKLIST_AUDIENCE>
Connectors keys
| 12.x/8.7 values | 13.x/8.8 values |
|---|---|
connectors.env[i].name=OPERATE_CLIENT_SCOPEconnectors.env[i].value=<scope> | Replace with connectors.security.authentication.oidc.tokenScope: <scope>. |
View example values files
This example shows how to replace the legacy OPERATE_CLIENT_SCOPE environment variable with the 8.8 connectors.security.authentication.oidc.tokenScope setting.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
connectors:
env:
- name: OPERATE_CLIENT_SCOPE
value: <OPERATE_SCOPE>
connectors:
security:
authentication:
method: oidc
oidc:
tokenScope: <OPERATE_SCOPE>
Cluster component keys
| 12.x/8.7 values | 13.x/8.8 values |
|---|---|
| Keys to move | |
zeebeGateway.ingress.grpc | Move to orchestration.ingress.grpc. |
zeebeGateway.service.grpcPort | Move to orchestration.service.grpcPort. |
zeebeGateway.service.commandPort | Move to orchestration.service.commandPort. |
zeebeGateway.service.restPort | Move to orchestration.service.httpPort. |
zeebeGateway.service.internalPort | Move to orchestration.service.internalPort. |
operate.enabled | Operate is enabled by default. Disable it with orchestration.profiles.operate: false. |
tasklist.enabled | Tasklist is enabled by default. Disable it with orchestration.profiles.tasklist: false. |
| Keys to merge into Orchestration Cluster | |
operate.configurationtasklist.configurationzeebeGateway.configuration | Merge into orchestration.configuration.Some legacy properties are replaced by unified Orchestration Cluster settings. See Camunda 8.8 property changes. |
operate.envtasklist.envzeebeGateway.env | Merge into orchestration.env.Some legacy environment variables are replaced by unified Orchestration Cluster settings. See Camunda 8.8 property changes. |
operate.envFromtasklist.envFromzeebeGateway.envFrom | Merge into orchestration.envFrom. |
operate.extraConfigurationtasklist.extraConfigurationzeebeGateway.extraConfiguration | Merge into orchestration.extraConfiguration. |
operate.initContainerstasklist.initContainerszeebeGateway.initContainers | Merge into orchestration.initContainers where applicable. |
operate.retentiontasklist.retention | Merge into orchestration.history.retention.In 8.8, historical data retention is unified across Operate, Tasklist, and Camunda indices. See Configure data retention. |
operate.sidecarstasklist.sidecarszeebeGateway.sidecars | Merge into orchestration.sidecars where applicable. |
operate.extraVolumeMountstasklist.extraVolumeMountszeebeGateway.extraVolumeMounts | Merge into orchestration.extraVolumeMounts where applicable. |
operate.extraVolumestasklist.extraVolumeszeebeGateway.extraVolumes | Merge into orchestration.extraVolumes where applicable. |
View example values files
This example shows how to consolidate component-level overrides (such as env, volumes, probes, resources, and retention) into the unified orchestration.* configuration in 8.8.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
zeebeGateway:
# (Optional) Set only if you changed it in 8.7
# enabled: true
env:
- name: <ENV_KEY_1>
value: <ENV_VALUE_1>
- name: <ENV_KEY_2>
value: <ENV_VALUE_2>
extraVolumes:
- name: <VOLUME_NAME_1>
secret:
secretName: <SECRET_NAME_1>
items:
- key: <SECRET_KEY_1>
path: <SECRET_FILE_NAME_1>
- name: <VOLUME_NAME_2>
secret:
secretName: <SECRET_NAME_2>
items:
- key: <SECRET_KEY_2>
path: <SECRET_FILE_NAME_2>
extraVolumeMounts:
- name: <VOLUME_NAME_1>
mountPath: <MOUNT_PATH_1>
subPath: <SECRET_FILE_NAME_1>
readOnly: true
- name: <VOLUME_NAME_2>
mountPath: <MOUNT_PATH_2>
subPath: <SECRET_FILE_NAME_2>
readOnly: true
resources:
requests:
cpu: <CPU_REQUEST>
memory: <MEMORY_REQUEST>
limits:
cpu: <CPU_LIMIT>
memory: <MEMORY_LIMIT>
livenessProbe:
scheme: HTTPS
readinessProbe:
scheme: HTTPS
startupProbe:
scheme: HTTPS
tolerations:
- key: <TOLERATION_KEY_1>
operator: <TOLERATION_OPERATOR_1>
value: <TOLERATION_VALUE_1>
effect: <TOLERATION_EFFECT_1>
- key: <TOLERATION_KEY_2>
operator: <TOLERATION_OPERATOR_2>
value: <TOLERATION_VALUE_2>
effect: <TOLERATION_EFFECT_2>
podSecurityContext:
runAsNonRoot: <BOOLEAN>
fsGroup: <FS_GROUP>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
containerSecurityContext:
allowPrivilegeEscalation: <BOOLEAN>
privileged: <BOOLEAN>
readOnlyRootFilesystem: <BOOLEAN>
runAsNonRoot: <BOOLEAN>
runAsUser: <RUN_AS_USER>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
capabilities:
add:
- <CAPABILITY_NAME>
operate:
enabled: true
env:
- name: <ENV_KEY_1>
value: <ENV_VALUE_1>
extraVolumes:
- name: <VOLUME_NAME_1>
secret:
secretName: <SECRET_NAME_1>
items:
- key: <SECRET_KEY_1>
path: <SECRET_FILE_NAME_1>
extraVolumeMounts:
- name: <VOLUME_NAME_1>
mountPath: <MOUNT_PATH_1>
subPath: <SECRET_FILE_NAME_1>
readOnly: true
resources:
requests:
cpu: <CPU_REQUEST>
memory: <MEMORY_REQUEST>
livenessProbe:
scheme: HTTPS
readinessProbe:
scheme: HTTPS
startupProbe:
scheme: HTTPS
tolerations:
- key: <TOLERATION_KEY_1>
operator: <TOLERATION_OPERATOR_1>
value: <TOLERATION_VALUE_1>
effect: <TOLERATION_EFFECT_1>
podSecurityContext:
runAsNonRoot: <BOOLEAN>
fsGroup: <FS_GROUP>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
containerSecurityContext:
allowPrivilegeEscalation: <BOOLEAN>
privileged: <BOOLEAN>
readOnlyRootFilesystem: <BOOLEAN>
runAsNonRoot: <BOOLEAN>
runAsUser: <RUN_AS_USER>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
capabilities:
add:
- <CAPABILITY_NAME>
retention:
enabled: true
minimumAge: <RETENTION_PERIOD>
tasklist:
enabled: true
env:
- name: <ENV_KEY_1>
value: <ENV_VALUE_1>
extraVolumes:
- name: <VOLUME_NAME_1>
secret:
secretName: <SECRET_NAME_1>
items:
- key: <SECRET_KEY_1>
path: <SECRET_FILE_NAME_1>
extraVolumeMounts:
- name: <VOLUME_NAME_1>
mountPath: <MOUNT_PATH_1>
subPath: <SECRET_FILE_NAME_1>
readOnly: true
resources:
requests:
cpu: <CPU_REQUEST>
memory: <MEMORY_REQUEST>
livenessProbe:
scheme: HTTPS
readinessProbe:
scheme: HTTPS
startupProbe:
scheme: HTTPS
tolerations:
- key: <TOLERATION_KEY_1>
operator: <TOLERATION_OPERATOR_1>
value: <TOLERATION_VALUE_1>
effect: <TOLERATION_EFFECT_1>
podSecurityContext:
runAsNonRoot: <BOOLEAN>
fsGroup: <FS_GROUP>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
containerSecurityContext:
allowPrivilegeEscalation: <BOOLEAN>
privileged: <BOOLEAN>
readOnlyRootFilesystem: <BOOLEAN>
runAsNonRoot: <BOOLEAN>
runAsUser: <RUN_AS_USER>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
capabilities:
add:
- <CAPABILITY_NAME>
retention:
enabled: true
minimumAge: <RETENTION_PERIOD>
orchestration:
profiles:
# Operate and Tasklist are enabled by default in 8.8.
# Set these only if you disabled them in 8.7.
# operate: false
# tasklist: false
env:
# Merge env entries from zeebeGateway.env + operate.env + tasklist.env.
# Copy all remaining env entries using the same pattern.
- name: <ENV_KEY_1>
value: <ENV_VALUE_1>
- name: <ENV_KEY_2>
value: <ENV_VALUE_2>
extraVolumes:
# Merge volumes from zeebeGateway.extraVolumes + operate.extraVolumes + tasklist.extraVolumes.
- name: <VOLUME_NAME_1>
secret:
secretName: <SECRET_NAME_1>
items:
- key: <SECRET_KEY_1>
path: <SECRET_FILE_NAME_1>
- name: <VOLUME_NAME_2>
secret:
secretName: <SECRET_NAME_2>
items:
- key: <SECRET_KEY_2>
path: <SECRET_FILE_NAME_2>
extraVolumeMounts:
# Merge mounts from zeebeGateway.extraVolumeMounts + operate.extraVolumeMounts + tasklist.extraVolumeMounts.
- name: <VOLUME_NAME_1>
mountPath: <MOUNT_PATH_1>
subPath: <SECRET_FILE_NAME_1>
readOnly: true
- name: <VOLUME_NAME_2>
mountPath: <MOUNT_PATH_2>
subPath: <SECRET_FILE_NAME_2>
readOnly: true
history:
retention:
enabled: true
minimumAge: <RETENTION_PERIOD>
resources:
requests:
cpu: <CPU_REQUEST>
memory: <MEMORY_REQUEST>
# limits:
# cpu: <CPU_LIMIT>
# memory: <MEMORY_LIMIT>
livenessProbe:
scheme: HTTPS
readinessProbe:
scheme: HTTPS
startupProbe:
scheme: HTTPS
tolerations:
- key: <TOLERATION_KEY_1>
operator: <TOLERATION_OPERATOR_1>
value: <TOLERATION_VALUE_1>
effect: <TOLERATION_EFFECT_1>
- key: <TOLERATION_KEY_2>
operator: <TOLERATION_OPERATOR_2>
value: <TOLERATION_VALUE_2>
effect: <TOLERATION_EFFECT_2>
podSecurityContext:
runAsNonRoot: <BOOLEAN>
fsGroup: <FS_GROUP>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
containerSecurityContext:
allowPrivilegeEscalation: <BOOLEAN>
privileged: <BOOLEAN>
readOnlyRootFilesystem: <BOOLEAN>
runAsNonRoot: <BOOLEAN>
runAsUser: <RUN_AS_USER>
seccompProfile:
type: <SECCOMP_PROFILE_TYPE>
capabilities:
add:
- <CAPABILITY_NAME>
Deprecated keys with no 8.8 equivalent
| 12.x/8.7 values | 13.x/8.8 values |
|---|---|
operate.contextPath | Remove. Operate is available under {orchestration.contextPath}/operate. |
tasklist.contextPath | Remove. Tasklist is available under {orchestration.contextPath}/tasklist. |
zeebeGateway.contextPath | Remove. orchestration.contextPath defines the base path. The Orchestration Cluster API is available under {orchestration.contextPath}/v2. |
tasklist.identity.userAccessRestrictions.enabled | Remove. To switch Tasklist V1/V2 behavior, configure Tasklist mode through orchestration.{env,envFrom,configuration}. See Switching between Tasklist V1 and V2 modes. |
View example values files
This example shows how to remove deprecated context path and user access restriction keys that are no longer configurable per component in 8.8.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
zeebeGateway:
contextPath: /zeebe
operate:
contextPath: /operate
tasklist:
contextPath: /tasklist
identity:
userAccessRestrictions:
enabled: <BOOLEAN>
# Remove the deprecated keys. In 8.8, these paths are derived from orchestration.contextPath.
orchestration:
contextPath: <BASE_CONTEXT_PATH>
# Operate is served under: {orchestration.contextPath}/operate
# Tasklist is served under: {orchestration.contextPath}/tasklist
# Orchestration Cluster API is served under: {orchestration.contextPath}/v2
Remove deprecated component blocks after migration
After you move or merge the relevant settings into orchestration.*, remove these blocks from values-8.8.yaml:
| 12.x/8.7 values | 13.x/8.8 values |
|---|---|
operate | After merging any relevant settings into orchestration.*, remove the remaining operate.* section. |
tasklist | After merging any relevant settings into orchestration.*, remove the remaining tasklist.* section. |
zeebeGateway | After moving or merging relevant settings into orchestration.*, remove the remaining zeebeGateway.* section. |
View example values files
This example shows the expected end state after migration, where legacy operate, tasklist, and zeebeGateway blocks are removed and configuration is managed under orchestration.*.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
operate:
enabled: true
env:
- name: <OPERATE_ENV_KEY>
value: <VALUE>
tasklist:
enabled: true
env:
- name: <TASKLIST_ENV_KEY>
value: <VALUE>
zeebeGateway:
service:
grpcPort: <PORT>
env:
- name: <ZEEBE_GATEWAY_ENV_KEY>
value: <VALUE>
# Legacy component blocks removed after migration.
# All required configuration now lives under orchestration.*.
orchestration:
enabled: true
env:
- name: <SHARED_ENV_KEY>
value: <VALUE>
Changes to the default deployment setup
Starting with Camunda 8.8, the set of components deployed by default changed compared to 8.7. If you used any of the components listed below, enable them explicitly to ensure they are present after the upgrade.
| Component disabled by default in 13.x/8.8.x | 13.x/8.8.x key to enable it |
|---|---|
| Console | console.enabled: true |
| Management Identity | identity.enabled: true |
| Management Identity PostgreSQL | identityPostgresql.enabled: true |
| Management Identity Keycloak (Bitnami subchart) | identityKeycloak.enabled: true |
| Optimize | optimize.enabled: true |
| Web Modeler | webModeler.enabled: true |
| Web Modeler PostgreSQL | webModelerPostgresql.enabled: true |
For more information, see Enable additional components.
Authentication
Configure authentication for your deployment.
- OIDC
- OAuth with Keycloak
- Basic auth
- LDAP
For OIDC, make sure your configuration includes the required keys. The following example shows a typical setup for Microsoft Entra ID:
global:
security:
authentication:
method: oidc
orchestration:
security:
authentication:
oidc:
# :start: relocated from former `global.identity.auth.zeebe`
clientId: <YOUR_CLIENTID>
secret:
existingSecret: <YOUR_CLIENTSECRET>
existingSecretKey: <YOUR_CLIENTSECRET_KEY>
audience: <YOUR_AUDIENCE>
# :end: relocated from former `global.identity.auth.zeebe`
redirectUrl: https://<YOUR_PUBLIC_HOST>{{ .Values.orchestration.contextPath }}
# Configure the claim in the access token to identify a client, default: client_id
clientIdClaim: azp
# Configure the claim in the access token to identify a user by, default: preferred_username
usernameClaim: preferred_username
# Configure the claim in the access token to retrieve groups from, default: groups
groupsClaim: groups
# For Microsoft Entra ID the following scopes are required
scope:
- openid
- profile
- offline_access
- <YOUR_AUDIENCE>/.default
# In case of Microsoft Entra ID, a user acces token contains `azp` and `preferred_username` thus the username claim needs to be preferred
preferUsernameClaim: true
Internal Keycloak
global:
security:
authentication:
method: oidc
orchestration:
security:
authentication:
method: oidc
oidc:
secret:
existingSecret: <YOUR_CLIENTSECRET>
existingSecretKey: <YOUR_CLIENTSECRET_KEY>
redirectUrl: https://<YOUR_PUBLIC_HOST>{{ .Values.orchestration.contextPath }}
For more information, see the Internal Keycloak guide. For an external Keycloak deployment, see External Keycloak guide.
In the Camunda 8.7 Helm chart, Keycloak was upgraded to version 26.3.3, which introduces changes to environment variable prefixes.
Some variables previously using the KEYCLOAK_ prefix now use KC_.
For more information, see the Keycloak release notes.
Update the prefix for any affected environment variables in your configuration. No action is required if you don’t use custom variables passed to the Keycloak deployment (for example, via the values file or post-rendering).
orchestration:
security:
authentication:
method: basic
connectors:
security:
authentication:
method: basic
In 8.7, Basic authentication is applied to Operate and Tasklist only. In 8.8, authentication applies to the entire Orchestration Cluster.
If you use Basic authentication, plan to migrate or recreate users so they can access the Orchestration Cluster endpoints.
For more information, see Set up the Helm chart with basic authentication.
LDAP authentication is not supported in the Camunda 8.8 Orchestration Cluster architecture. Contact Camunda Consulting for assistance with LDAP authentication requirements.
Multi-tenancy
If you configured multi-tenancy in 8.7, review the Helm chart configuration for 8.8.
For more information, see Configure multi-tenancy in the Helm chart.
Ingress
Starting with Camunda 8.8, the separated Ingress configuration is no longer supported. Use the combined Ingress setup.
For more information, see Configure Ingress.
Custom users and clients for Management Identity
To configure custom users and OAuth2 clients for Management Identity, see Add users and clients.
Example: upgrade values.yaml from 8.7 to 8.8
This section shows a complete before-and-after example of a Helm values.yaml migrated from Camunda 8.7 to 8.8.
View example values files
This example shows one possible migration from 8.7 to 8.8 using OIDC, Ingress, and a single Elasticsearch/OpenSearch instance. Adjust the configuration to match your deployment.
- 8.7 values.yaml (before)
- 8.8 values-8.8.yaml (after)
# =========================
# Camunda 8.7 values.yaml
# =========================
global:
security:
authentication:
method: oidc
identity:
auth:
zeebe:
clientId: <ZEEBE_CLIENT_ID>
clientSecret:
existingSecret: zeebe-oidc-secret
existingSecretKey: client-secret
audience: <ZEEBE_AUDIENCE>
operate:
audience: <OPERATE_AUDIENCE>
tasklist:
audience: <TASKLIST_AUDIENCE>
zeebe:
clusterSize: 3
partitionCount: 3
replicationFactor: 3
resources:
requests:
cpu: "<CPU_REQUEST>"
memory: <MEMORY_REQUEST>
limits:
cpu: "<CPU_LIMIT>"
memory: <MEMORY_LIMIT>
tolerations:
- key: "<TOLERATION_KEY>"
operator: "Equal"
value: "<TOLERATION_VALUE>"
effect: "NoSchedule"
nodeSelector:
<NODE_LABEL_KEY>: <NODE_LABEL_VALUE>
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: zeebe
topologyKey: kubernetes.io/hostname
env:
- name: ZEEBE_BROKER_EXPORTERS_ELASTICSEARCH_CLASSNAME
value: io.camunda.zeebe.exporter.ElasticsearchExporter
- name: ZEEBE_LOG_LEVEL
value: <LOG_LEVEL>
extraVolumeMounts:
- name: zeebe-config
mountPath: /usr/local/zeebe/config/application.yaml
subPath: application.yaml
extraVolumes:
- name: zeebe-config
configMap:
name: zeebe-config
items:
- key: application.yaml
path: application.yaml
zeebeGateway:
service:
grpcPort: 26500
commandPort: 26501
restPort: 9600
internalPort: 26502
ingress:
grpc:
enabled: true
host: <GRPC_HOST>
operate:
enabled: true
resources:
requests:
cpu: "<CPU_REQUEST>"
memory: <MEMORY_REQUEST>
limits:
cpu: "<CPU_LIMIT>"
memory: <MEMORY_LIMIT>
env:
- name: OPERATE_LOG_LEVEL
value: <LOG_LEVEL>
extraVolumeMounts:
- name: operate-config
mountPath: /usr/local/operate/config/application.yaml
subPath: application.yaml
extraVolumes:
- name: operate-config
configMap:
name: operate-config
items:
- key: application.yaml
path: application.yaml
tasklist:
enabled: true
resources:
requests:
cpu: "<CPU_REQUEST>"
memory: <MEMORY_REQUEST>
limits:
cpu: "<CPU_LIMIT>"
memory: <MEMORY_LIMIT>
env:
- name: TASKLIST_LOG_LEVEL
value: <LOG_LEVEL>
connectors:
env:
- name: OPERATE_CLIENT_SCOPE
value: <OPERATE_SCOPE>
postgresql:
enabled: false
# =========================
# Camunda 8.8 values-8.8.yaml
# =========================
global:
security:
authentication:
method: oidc
orchestration:
# Migrated from zeebe cluster sizing (type changed from int -> string in 8.8)
clusterSize: "3"
partitionCount: "3"
replicationFactor: "3"
resources:
requests:
cpu: "<CPU_REQUEST>"
memory: <MEMORY_REQUEST>
limits:
cpu: "<CPU_LIMIT>"
memory: <MEMORY_LIMIT>
tolerations:
- key: "<TOLERATION_KEY>"
operator: "Equal"
value: "<TOLERATION_VALUE>"
effect: "NoSchedule"
nodeSelector:
<NODE_LABEL_KEY>: <NODE_LABEL_VALUE>
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: zeebe
topologyKey: kubernetes.io/hostname
# Merged from zeebeGateway.env + operate.env + tasklist.env
env:
- name: ZEEBE_BROKER_EXPORTERS_ELASTICSEARCH_CLASSNAME
value: io.camunda.zeebe.exporter.ElasticsearchExporter
- name: ZEEBE_LOG_LEVEL
value: <LOG_LEVEL>
- name: OPERATE_LOG_LEVEL
value: <LOG_LEVEL>
- name: TASKLIST_LOG_LEVEL
value: <LOG_LEVEL>
# Merged volumes/mounts from zeebe/operate/tasklist patterns
extraVolumeMounts:
- name: orchestration-config
mountPath: /usr/local/orchestration/config/application.yaml
subPath: application.yaml
extraVolumes:
- name: orchestration-config
configMap:
name: orchestration-config
items:
- key: application.yaml
path: application.yaml
profiles:
operate: true
tasklist: true
security:
authentication:
oidc:
# Relocated from former global.identity.auth.zeebe + audiences
clientId: <ORCHESTRATION_CLIENT_ID>
secret:
existingSecret: orchestration-oidc-secret
existingSecretKey: client-secret
audience: <ORCHESTRATION_AUDIENCE>
backwardsCompatibleAudiences:
- <OPERATE_AUDIENCE>
- <TASKLIST_AUDIENCE>
redirectUrl: https://<PUBLIC_HOST>{{ .Values.orchestration.contextPath }}
clientIdClaim: azp
usernameClaim: preferred_username
groupsClaim: groups
scope:
- openid
- profile
- offline_access
- <ORCHESTRATION_SCOPE>
service:
# Migrated from zeebeGateway.service.*
grpcPort: 26500
commandPort: 26501
httpPort: 9600
internalPort: 26502
ingress:
# Migrated from zeebeGateway.ingress.grpc
grpc:
enabled: true
host: <GRPC_HOST>
migration:
data:
enabled: true
identity:
enabled: true
claimName: azp
claimValue: <IDENTITY_CLIENT_ID>
clientId: <IDENTITY_CLIENT_ID>
secret:
existingSecret: identity-migration-secret
existingSecretKey: password
connectors:
security:
authentication:
oidc:
# Migrated from connectors.env OPERATE_CLIENT_SCOPE
tokenScope: <OPERATE_SCOPE>
webModelerPostgresql:
# Migrated from top-level postgresql
enabled: false
Prepare and run the upgrade
Add required upgrade-specific configuration.
Data migration
Enable data migration:
orchestration:
migration:
data:
enabled: true
For additional configuration details, see Data migration in the components upgrade guide.
Identity migration (recommended)
Camunda 8.8 uses Orchestration Cluster Identity for authentication and authorization. Identity migration migrates permissions from Management Identity to Orchestration Cluster Identity, preserving your 8.7 authorization setup.
For more information about what is migrated and what you may still need to recreate after the upgrade, see Identity authorization and permission changes.
If you use Resource-Based Authorization (RBA) and have users assigned to roles with zeebe-api:write permissions (including the default Zeebe role), users may receive wildcard permissions after migration.
While a user remains a member of such a role, access in Tasklist and Operate will not be restricted to specific resources.
- OIDC
- OAuth with Keycloak
The Identity Migration App requires read access to Management Identity. Create or reuse client credentials with read permission for the Management Identity API and provide the corresponding clientId and secret.
-
Create a file named
identity-migration-secret.yamlwith the following content:apiVersion: v1
kind: Secret
metadata:
name: identity-migration-secret
type: Opaque
data:
password: "WU9VUl9QQVNTV09SRA==" # base64 encoded YOUR_PASSWORD -
Apply the secret to your cluster:
kubectl apply -f identity-migration-secret.yaml -n <NAMESPACE> -
Reference this secret in your
values-8.8.yamlfile and enable the Identity Migration App.orchestration:
migration:
identity:
enabled: true
# In case of Microsoft Entra ID, you can use the `azp` claim that contains the client_id value
claimName: azp
claimValue: <YOUR_IDENTITY_CLIENT_ID>
clientId: <YOUR_IDENTITY_CLIENT_ID>
secret:
existingSecret: identity-migration-secret
existingSecretKey: password
To authorize the Identity Migration App with your Keycloak instance, you need to create a new Kubernetes Secret.
-
Create a file named
identity-migration-secret.yamlwith the following content:apiVersion: v1
kind: Secret
metadata:
name: identity-migration-secret
type: Opaque
data:
password: "WU9VUl9QQVNTV09SRA==" # base64 encoded YOUR_PASSWORD -
Apply the secret to your cluster:
kubectl apply -f identity-migration-secret.yaml -
Reference this secret in your
values-8.8.yamlfile and enable the Identity Migration App:migration:
identity:
enabled: true
secret:
existingSecret: identity-migration-secret
existingSecretKey: password
# Only required if resource authorizations are used
resourceAuthorizationsEnabled: true
The Helm chart creates a dedicated Keycloak client with read-only access to your Identity Resource Server. If you override your Identity clients, follow the Helm chart section in Common configuration for the Identity Migration application to set up the required migration client.
For more information, see Camunda Orchestration Cluster Identity data migration.
Groups migration
In 8.7 groups are persisted in Keycloak and are not migrated into Orchestration Cluster to avoid splitting group management. Identity migration migrates permissions previously assigned to groups.
Configure bring your own groups in 8.8 so group memberships and authorizations take effect.
See Configure bring your own groups.
Run the Helm upgrade
If you use custom prefixes for Camunda indices, complete the Update any custom prefixes steps before upgrading.
If your environment uses more than one Elasticsearch/OpenSearch instance for exported Zeebe, Operate, and Tasklist data, consolidate to a single instance before upgrading.
For more information, see Single Elasticsearch/OpenSearch instance.
After preparing secrets and enabling migration configuration, run the Helm upgrade:
helm repo update
helm upgrade camunda camunda/camunda-platform \
--namespace <NAMESPACE> \
-f values-8.8.yaml
Monitor the upgrade
After triggering the Helm upgrade, monitor the rollout to ensure all pods return to a healthy state and migration jobs complete.
Watch pod rollout progress
Watch the pods being migrated via:
kubectl -n <NAMESPACE> get pods -w
You should see:
- pods terminating and restarting with updated images,
- the Orchestration Cluster (
zeebeStatefulSet) continuing to run as a StatefulSet, and - one or more migration jobs running if enabled.
If both migrations are enabled, two Kubernetes Jobs can run in parallel:
<RELEASE_NAME>-zeebe-migration-data(data migration)<RELEASE_NAME>-zeebe-migration-identity(identity migration)
Inspect migration and importer logs
# Importer deployment (migrates remaining Zeebe data)
kubectl -n <NAMESPACE> logs deploy/<importer-name> -f
# Data migration job
kubectl -n <NAMESPACE> logs job/<release>-zeebe-migration-data -f
# Identity migration job (if enabled)
kubectl -n <NAMESPACE> logs job/<release>-zeebe-migration-identity -f
Expected behaviour:
- Importer logs show batches of records being imported and end with
Importer finished successfully. - Migration jobs terminate with status
Complete.
If a job is stuck in Running or CrashLoopBackOff, inspect its logs.
Wait until all pods are Ready before validating.
Validate the upgrade
-
Confirm all pods are healthy:
kubectl -n <namespace> get pods -
Confirm all pods are running
8.8.ximages:kubectl -n <namespace> get pods -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}" -
Verify access to Camunda components
For example:
https://<your-domain>/<contextPath>/operate
https://<your-domain>/<contextPath>/tasklist
https://<your-domain>/<contextPath>/identity -
Verify authentication and authorization behavior:
- Confirm users can access Operate and Tasklist.
- Verify role- and tenant-based permissions behave as expected, especially if you use RBA or migrated groups.
-
Verify workers
Confirm your workers can still poll and complete jobs (for example, by running a known process end-to-end and checking worker logs/metrics).
-
Optional: scale down the importer.
After you confirm the importer is idle, scale it down:
kubectl -n <namespace> scale deploy/<importer-name> --replicas=0
Troubleshooting
Migration job did not complete
If a migration job (data or identity) fails to complete, it may reach its backoffLimit (maximum retry attempts). This can happen if a required dependency (for example, the importer) did not complete.
How to fix this:
-
Check the job status
kubectl -n <namespace> get jobs -
Delete the failed migration jobs
kubectl -n <namespace> delete job camunda-zeebe-migration-data
kubectl -n <namespace> delete job camunda-zeebe-migration-identity -
Rerun your Helm upgrade command to recreate and restart the migration jobs.
Upgrade failed due to missing secrets
If your upgrade fails due to missing credentials (often when migrating from chart-managed secret generation to Kubernetes secrets), see Extract plaintext values and reference them as Kubernetes Secrets.
The Bitnami library chart used by Camunda can block upgrades when credentials were previously generated and persisted (for example, in PVCs). This is expected behavior to prevent secret regeneration.
For additional context, see Helm chart Bitnami legacy values file.
The following is an example of the error you might see:
Error: UPGRADE FAILED: execution error at (camunda-platform/charts/identity/templates/tasklist-secret.yaml:10:22):
PASSWORDS ERROR: You must provide your current passwords when upgrading the release.
Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims.
Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases
'global.identity.auth.tasklist.existingSecret' must not be empty, please add '--set global.identity.auth.tasklist.existingSecret=$TASKLIST_SECRET' to the command. To get the current value:
export TASKLIST_SECRET=$(kubectl get secret --namespace "camunda" "camunda-platform-test-tasklist-identity-secret" -o jsonpath="{.data.tasklist-secret}" | base64 --decode)
To complete the upgrade, migrate plaintext values to Kubernetes secrets and reference them from your values file as described in the secret management guide.