For the complete documentation index, see llms.txt.
Skip to main content

Red Hat OpenShift

Red Hat OpenShift, a Kubernetes distribution maintained by Red Hat, provides options for both managed and on-premises hosting.

Deploying Camunda 8 on Red Hat OpenShift is supported using Helm, given the appropriate configurations.

However, it's important to note that the Security Context Constraints (SCCs) and Routes configurations might require slight deviations from the guidelines provided in the general Helm deployment guide.

Additional informational and high-level overview based on Kubernetes as upstream project is available on our Kubernetes deployment reference.

Requirements​

  • Helm
  • kubectl to interact with the cluster.
  • jq to interact with some variables.
  • yq to edit your values.yml file.
  • GNU envsubst to generate manifests.
  • oc (version supported by your OpenShift) to interact with OpenShift.
  • AWS Quotas
    • Ensure at least 3 Elastic IPs (one per availability zone).
    • Verify quotas for VPCs, EC2 instances, and storage.
    • Request increases if needed via the AWS console (guide), costs are only for resources used.
  • A namespace to host Camunda.

For the tool versions used, check the .tool-versions file in the repository. It contains an up-to-date list of versions that Camunda also uses for testing.

Deploy Camunda 8 via Helm charts​

Configure your deployment​

Start by creating a values.yml file to store the configuration for your environment. This file will contain key-value pairs that will be substituted using envsubst. Over this guide, you will add and merge values in this file to configure your deployment to fit your needs.

You can find a reference example of this file here:

8.7/generic/openshift/single-region/helm-values/base.yml
loading...
Merging YAML files

This guide references multiple configuration files that need to be merged into a single YAML file. Be cautious to avoid duplicate keys when merging the files. Additionally, pay close attention when copying and pasting YAML content. Ensure that the separator notation --- does not inadvertently split the configuration into multiple documents.

We strongly recommend double-checking your YAML file before applying it. You can use tools like yamllint.com or the YAML Lint CLI if you prefer not to share your information online.

Configuring the Ingress​

Before exposing services outside the cluster, we need an Ingress component. Here's how you can configure it:

Routes expose services externally by linking a URL to a service within the cluster. OpenShift supports both the standard Kubernetes Ingress and routes, giving cluster users the flexibility to choose.

The presence of routes is rooted in their specification predating Ingress. The functionality of routes differs from Ingress; for example, unlike Ingress, routes don't allow multiple services to be linked to a single route or the use of paths.

To use these routes for the Zeebe Gateway, configure this through Ingress as well.

Setting Up the application domain for Camunda 8​

The route created by OpenShift will use a domain to provide access to the platform. By default, you can use the OpenShift applications domain, but any other domain supported by the router can also be used.

To retrieve the OpenShift applications domain (used as an example here), run the following command and define the route domain that will be used for the Camunda 8 deployment:

8.7/generic/openshift/single-region/procedure/setup-application-domain.sh
loading...

If you choose to use a custom domain instead, ensure it is supported by your router configuration and replace the example domain with your desired domain. For more details on configuring custom domains in OpenShift, refer to the official custom domain OpenShift documentation.

Checking if HTTP/2 is enabled​

As the Zeebe Gateway also uses gRPC (which relies on HTTP/2), HTTP/2 Ingress Connectivity must be enabled.

To check if HTTP/2 is already enabled on your OpenShift cluster, run the following command:

oc get ingresses.config/cluster -o json | jq '.metadata.annotations."ingress.operator.openshift.io/default-enable-http2"'

Alternatively, if you use a dedicated IngressController for the deployment:

8.7/generic/openshift/single-region/procedure/get-ingress-http2-status.sh
loading...
  • If the output is "true", it means HTTP/2 is enabled.
  • If the output is null or empty, HTTP/2 is not enabled.
Enable HTTP/2

If HTTP/2 is not enabled, you can enable it by running the following command:

IngressController configuration:

8.7/generic/openshift/single-region/procedure/enable-ingress-http2.sh
loading...

Global cluster configuration:

oc annotate ingresses.config/cluster ingress.operator.openshift.io/default-enable-http2=true

This will add the necessary annotation to enable HTTP/2 for Ingress in your OpenShift cluster globally on the cluster.

Enable ALPN h2 on ROSA HCP​

These steps are required only on Red Hat OpenShift Service on AWS – Hosted Control Planes (ROSA HCP) managed clusters. Self-managed OpenShift clusters where the cluster-wide ingress.operator.openshift.io/default-enable-http2=true annotation is honored do not need this workaround.

On ROSA HCP, the ingress-config-validation.managed.openshift.io admission webhook denies the cluster-wide annotation, and the per-IngressController annotation alone does not make HAProxy advertise ALPN h2 on the default certificate path. As a result, gRPC clients fail to connect to the Zeebe Gateway, with zbctl reporting credentials: cannot check peer: missing selected ALPN property.

The OpenShift router advertises ALPN h2 on a per-SNI basis through a crt-list entry that HAProxy generates only for Routes that carry an explicit spec.tls.certificate. In other words, the gRPC Route must reference a TLS Secret in the Camunda namespace; the empty default secretName (Ingress-Operator-managed) is not enough on ROSA HCP.

To fix this, copy the router default wildcard TLS Secret from openshift-ingress into the Camunda namespace, then point the gRPC Ingress to it:

  1. Copy the router wildcard certificate Secret into the Camunda namespace. If you install Camunda into a namespace other than camunda, export CAMUNDA_NAMESPACE with that namespace before you run this step, and use the same value when you set up the chart environment later in this guide. This guide does not clone the reference architectures repository, so download the script first:

    8.7/generic/openshift/single-region/procedure/copy-router-tls-secret.sh
    loading...
    curl -fsSL -o copy-router-tls-secret.sh \
    https://raw.githubusercontent.com/camunda/camunda-deployment-references/stable/8.7/generic/openshift/single-region/procedure/copy-router-tls-secret.sh
    chmod +x copy-router-tls-secret.sh

    export CAMUNDA_NAMESPACE="${CAMUNDA_NAMESPACE:-camunda}"
    export CAMUNDA_PLATFORM_ROUTER_TLS_SECRET="camunda-platform-router-tls"
    ./copy-router-tls-secret.sh
  2. After you have added the Zeebe Gateway Route configuration to your values.yml, as described in Configure Route TLS below, override zeebeGateway.ingress.grpc.tls.secretName in that same file. The empty default lets the Ingress Operator manage the certificate automatically; on ROSA HCP, replace it with the Secret you just created:

    yq -i ".zeebeGateway.ingress.grpc.tls.secretName = \"$CAMUNDA_PLATFORM_ROUTER_TLS_SECRET\"" \
    values.yml

    Run this after the Route configuration is in values.yml, never before. Pasting that snippet afterwards would reset secretName to its default and the Route would lose its certificate.

After applying both steps, the auto-generated Route for the Zeebe gRPC Ingress will carry an inlined spec.tls.certificate, HAProxy will emit a per-SNI [alpn h2,http/1.1] crt-list entry, and gRPC clients will negotiate h2 successfully.

warning

copy-router-tls-secret.sh copies the certificate as it exists at that moment. It does not track later changes. When the router wildcard certificate is rotated or replaced, the copy in the Camunda namespace goes stale. The Route keeps serving the old certificate, and gRPC clients fail once that certificate expires or is revoked.

Re-run the script after any router certificate change, then confirm the Route picked the new certificate up:

oc -n "$CAMUNDA_NAMESPACE" get route -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.tls.certificate}{"\n"}{end}'

Restarting the Camunda pods does not refresh this certificate and only causes downtime: the pods use the separate internal service certificate described below, not the Route one. To avoid the manual step entirely, manage the copy with a controller that keeps the two Secrets in sync.

Configure Route TLS​

Additionally, the Zeebe Gateway should be configured to use an encrypted connection with TLS. In OpenShift, the connection from HAProxy to the Zeebe Gateway service can use HTTP/2 only for re-encryption or pass-through routes, and not for edge-terminated or insecure routes.

  1. Zeebe Gateway: two TLS secrets for the Zeebe Gateway are required, one for the service and the other one for the route:

    • The first TLS secret is issued to the Zeebe Gateway Service Name. This must use the PKCS #8 syntax or PKCS #1 syntax as Zeebe only supports these, referenced as camunda-platform-internal-service-certificate.

      In the example below, a TLS certificate is generated for the Zeebe Gateway service with an annotation. The generated certificate will be in the form of a secret.

      Another option is Cert Manager. For more details, review the OpenShift documentation.

    PKCS #8, PKCS #1 syntax

    PKCS #1 private key encoding. PKCS #1 produces a PEM block that contains the private key algorithm in the header and the private key in the body. A key that uses this can be recognised by its BEGIN RSA PRIVATE KEY or BEGIN EC PRIVATE KEY header. NOTE: This encoding is not supported for Ed25519 keys. Attempting to use this encoding with an Ed25519 key will be ignored and default to PKCS #8.

    PKCS #8 private key encoding. PKCS #8 produces a PEM block with a static header and both the private key algorithm and the private key in the body. A key that uses this encoding can be recognised by its BEGIN PRIVATE KEY header.

    PKCS #1, PKCS #8 syntax definitionfrom cert-manager

    • The second TLS secret is used on the exposed route, referenced as camunda-platform-external-certificate. For example, this would be the same TLS secret used for Ingress. We also configure the Zeebe Gateway Ingress to create a Re-encrypt Route.

    To configure a Zeebe cluster securely, it's essential to set up a secure communication configuration between pods:

    • We enable gRPC ingress for the ZeebeGateway pod, which sets up a secure proxy that we'll use to communicate with the Zeebe cluster. To avoid conflicts with other services, we use a specific domain (zeebe-$DOMAIN_NAME) for the gRPC proxy, different from the one used by other services ($DOMAIN_NAME). We also note that the port used for gRPC is 443.

    • We mount the Service Certificate Secret (camunda-platform-internal-service-certificate) to the Core pod and configure a secure TLS connection. Finally, we mount the Service Certificate Secret (camunda-platform-internal-service-certificate) to the Zeebe Gateway Pod and the Zeebe Pod to configure both broker security and gateway security.

    Update your values.yml file with the following:

    8.7/generic/openshift/single-region/helm-values/zeebe-gateway-route.yml
    loading...

    The domain used by the Zeebe Gateway for gRPC is zeebe-$DOMAIN_NAME which different from the one used for the rest, namely $DOMAIN_NAME, to avoid any conflicts. It is also important to note that the port used for gRPC is 443.

  2. Operate: mount the Service Certificate Secret to the Operate pod and configure the secure TLS connection. Here, only the tls.crt file is required.

Update your values.yml file with the following:

8.7/generic/openshift/single-region/helm-values/operate-route.yml
loading...

The actual configuration properties can be reviewed in the Operate configuration documentation.

  1. Tasklist: mount the Service Certificate Secret to the Tasklist pod and configure the secure TLS connection. Here, only the tls.crt file is required.

    Update your values.yml file with the following:

8.7/generic/openshift/single-region/helm-values/tasklist-route.yml
loading...

The actual configuration properties can be reviewed in the Tasklist configuration documentation.

  1. Connectors: update your values.yml file with the following:
8.7/generic/openshift/single-region/helm-values/connectors-route.yml
loading...

The actual configuration properties can be reviewed in the connectors configuration documentation.

  1. Configure all other applications running inside the cluster and connecting to the Zeebe Gateway to also use TLS.

  2. Set up the global configuration to enable the single Ingress definition with the host. Update your configuration file as shown below:

8.7/generic/openshift/single-region/helm-values/domain.yml
loading...

Configuring the Security Context Constraints​

Depending on your OpenShift cluster's Security Context Constraints (SCCs) configuration, the deployment process may vary. By default, OpenShift employs more restrictive SCCs. The Helm chart must assign null to the user running all components and dependencies.

The global.compatibility.openshift.adaptSecurityContext variable in your values.yaml can be used to set the following possible values:

  • force: The runAsUser and fsGroup values will be null in all components.
  • disabled: The runAsUser and fsGroup values will not be modified (default).
8.7/generic/openshift/single-region/helm-values/scc.yml
loading...

Enable Enterprise components​

Some components are not enabled by default in this deployment. For more information on how to configure and enable these components, refer to configuring Enterprise components and connectors.

Fill your deployment with actual values​

Once you've prepared the values.yml file, run the following envsubst command to substitute the environment variables with their actual values:

8.7/generic/openshift/single-region/procedure/assemble-envsubst-values.sh
loading...

Next, store various passwords in a Kubernetes secret, which will be used by the Helm chart. Below is an example of how to set up the required secret. You can use openssl to generate random secrets and store them in environment variables:

8.7/generic/openshift/single-region/procedure/generate-passwords.sh
loading...

Use these environment variables in the kubectl command to create the secret.

Install Camunda 8 using Helm​

Now that the generated-values.yml is ready, you can install Camunda 8 using Helm.

The following are the required environment variables with some example values:

8.7/generic/openshift/single-region/procedure/chart-env.sh
loading...
  • CAMUNDA_NAMESPACE is the Kubernetes namespace where Camunda will be installed. The script sets it to camunda. If you use another namespace, for example the one you exported in Enable ALPN h2 on ROSA HCP, set that value here, or export it again after you run the script.
  • CAMUNDA_RELEASE_NAME is the name of the Helm release associated with this Camunda installation

Then run the following command:

8.7/generic/openshift/single-region/procedure/install-chart.sh
loading...

This command:

  • Installs (or upgrades) Camunda using the Helm chart.
  • Substitutes the appropriate version using the $CAMUNDA_HELM_CHART_VERSION environment variable.
  • Applies the configuration from generated-values.yml.
note

This guide uses helm upgrade --install as it runs install on initial deployment and upgrades future usage. This may make it easier for future Camunda 8 Helm upgrades or any other component upgrades.

You can track the progress of the installation using the following command:

8.7/generic/kubernetes/single-region/procedure/check-deployment-ready.sh
loading...

Verify connectivity to Camunda 8​

Please follow our guide to verify connectivity to Camunda 8

Domain name for gRPC Zeebe

In this setup, the domain used for gRPC communication with Zeebe is slightly different from the one in the guide. Instead of using zeebe.$DOMAIN_NAME, you need to use zeebe-$DOMAIN_NAME.

Pitfalls to avoid​

For general deployment pitfalls, visit the deployment troubleshooting guide.

Security Context Constraints (SCCs)​

Security Context Constraints (SCCs) are a set of conditions that a pod must adhere to in order to be accepted into the system. They define the security conditions under which a pod operates.

Similar to how roles control user permissions, SCCs regulate the permissions of deployed applications, both at the pod and container level. It's generally recommended to deploy applications with the most restrictive SCCs possible. If you're unfamiliar with security context constraints, you can refer to the OpenShift documentation.

Restrictive SCCs​

The following represents the most restrictive SCCs that can be used to deploy Camunda 8. Note that in OpenShift 4.10, these are equivalent to the built-in restricted SCCs (which are the default SCCs).

Allow Privileged: false
Default Add Capabilities: <none>
Required Drop Capabilities: KILL, MKNOD, SYS_CHROOT, SETUID, SETGID
Allowed Capabilities: <none>
Allowed Seccomp Profiles: <none>
Allowed Volume Types: configMap, downwardAPI, emptyDir, persistentVolumeClaim, projected, secret
Allow Host Network: false
Allow Host Ports: false
Allow Host PID: false
Allow Host IPC: false
Read Only Root Filesystem: false
Run As User Strategy: MustRunAsRange
SELinux Context Strategy: MustRunAs
FSGroup Strategy: MustRunAs
Supplemental Groups Strategy: RunAsAny

When using these SCCs, be sure not to specify any runAsUser or fsGroup values in either the pod or container security context. Instead, allow OpenShift to assign arbitrary IDs.

note

If you are providing the ID ranges yourself, you can also configure the runAsUser and fsGroup values accordingly.

The Camunda Helm chart can be deployed to OpenShift with a few modifications, primarily revolving around your desired security context constraints.

Writing pod permissions for logs​

OpenShift security policies often restrict writing to files within containers. This can cause Camunda pods to fail to write to the filesystem, which is typically required for writing log in files.

Instead, we configure the environment to output logs to stdout and stderr only, which are supported by OpenShift logging infrastructure.

For Camunda components (except Identity), this can be done by setting the environment variable in the chart values:

zeebe/tasklist/operate/etc:
env:
- name: CAMUNDA_LOG_FILE_APPENDER_ENABLED
value: "false"

This will disable the file appender and ensure logs are visible via the container's log output.