JDBC driver management for RDBMS
This page covers JDBC driver management for RDBMS deployments in Kubernetes. For configuration and troubleshooting, see configure RDBMS in Helm charts.
Bundled vs. custom JDBC drivers
Which drivers are included?
Camunda bundles JDBC drivers for databases where licensing permits:
| Database | Bundled | When to supply custom drivers |
|---|---|---|
| PostgreSQL | Yes | Patches, extensions, or compatibility with older server versions. |
| MariaDB | Yes | Custom JDBC features or compliance requirements. |
| SQL Server | Yes | Custom features or version-specific requirements. |
| H2 | Yes | Development and testing only; not recommended for production due to scalability limitations. |
| Oracle | No | Always; licensing prevents bundling. |
| MySQL | No | Always; licensing prevents bundling. |
When to supply a custom driver
Consider supplying a custom JDBC driver in these scenarios:
- Oracle or MySQL databases: No bundled drivers available; custom drivers required.
- Version compatibility: Your database version is not compatible with the bundled driver.
- Security patches: A critical patch is available for the bundled driver before the next Camunda release.
- Custom extensions: You use database-specific features not covered by bundled drivers.
- Compliance or licensing: Your organization policy requires specific driver versions or sources.
Driver provisioning strategies
Choose one of the three approaches below. Init container is recommended for production.
| Strategy | Pros | Cons | Best for |
|---|---|---|---|
| Init container | Automatic at pod startup; reproducible. | Requires external download source. | Production (standard) |
| Custom image | Simple for teams with image registries. | Not yet validated in production. | Dev/test only |
| ConfigMap/Volume | GitOps-friendly; no external downloads. | Requires manual driver management. | Teams with restrictions |
Loading JDBC drivers into pods
Some databases—such as Oracle and MySQL—require JDBC drivers that cannot be included in the Camunda image due to licensing restrictions. You must provide these drivers at runtime using one of the following approaches.
Option 1: Using an init container
This example uses /driver-lib, which the Orchestration Cluster automatically adds to the classpath. If you use a different directory, additional override configuration may be required.
orchestration:
exporters:
camunda:
enabled: false
rdbms:
enabled: true
data:
secondaryStorage:
type: rdbms
rdbms:
url: jdbc:oracle:thin:@//hostname:1521/FREEPDB1
username: myuser
secret:
inlineSecret: mypassword
extraVolumeMounts:
- name: jdbcdrivers
mountPath: /driver-lib
extraVolumes:
- name: jdbcdrivers
emptyDir: {}
initContainers:
- name: fetch-jdbc-drivers
image: alpine:3.19
imagePullPolicy: Always
command:
- sh
- -c
- >
wget https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc11/23.9.0.25.07/ojdbc11-23.9.0.25.07.jar
-O /driver-lib/ojdbc.jar
volumeMounts:
- name: jdbcdrivers
mountPath: /driver-lib
securityContext:
runAsUser: 1001
After loading JDBC drivers into pods, run the validation checklist in validate RDBMS connectivity to confirm the application can load the driver, reach the database, and initialize schema.
Option 2: Using a custom Docker image
This is a custom image approach. For production, prefer the init-container method to stay aligned with supported Helm patterns.
FROM camunda/camunda-platform:8.9.0
ADD ojdbc8.jar /driver-lib/ojdbc8.jar
Build and push:
docker build -t internal-registry/orchestration:8.9.0 .
docker push internal-registry/orchestration:8.9.0
Configure in Helm:
orchestration:
exporters:
camunda:
enabled: false
rdbms:
enabled: true
image:
repository: internal-registry/orchestration
tag: 8.9.0
data:
secondaryStorage:
type: rdbms
rdbms:
url: jdbc:oracle:thin:@//hostname:1521/FREEPDB1
username: myuser
secret:
inlineSecret: mypassword
Option 3: Mounting a JDBC driver from a volume
Mounting an emptyDir volume does not persist across pod restarts. Use a ConfigMap, PersistentVolume, or custom image for production.
orchestration:
exporters:
camunda:
enabled: false
rdbms:
enabled: true
data:
secondaryStorage:
type: rdbms
rdbms:
url: jdbc:oracle:thin:@//hostname:1521/FREEPDB1
username: myuser
secret:
inlineSecret: mypassword
extraVolumeMounts:
- name: jdbcdrivers
mountPath: /driver-lib
extraVolumes:
- name: jdbcdrivers
emptyDir: {}
Copy the driver manually to the pod:
kubectl cp /path/to/ojdbc8.jar <pod-name>:/driver-lib/ojdbc8.jar
Verifying driver loading
After deployment, verify the JDBC driver was loaded:
# Check that the driver JAR exists
kubectl exec <pod-name> -- ls -la /driver-lib/
# Check logs for successful driver initialization
kubectl logs <pod-name> | grep -i "driver\|jdbc"
Common success indicators in logs:
INFO org.springframework.boot.StartupInfoLogger - Started Application in X seconds
INFO io.camunda.exporter.rdbms.RdbmsExporter - RdbmsExporter created with Configuration
Common failure indicators:
java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver
java.sql.SQLException: No suitable driver found
If you see failures, verify:
- The driver JAR file is present in
/driver-lib/. - The init container or custom image executed successfully.
- The JDBC URL in your configuration matches the driver (for example, Oracle URL with Oracle driver).
JDBC driver updates
Updating bundled drivers
Bundled drivers are updated with new Camunda releases. To update:
- Identify the new Camunda version with the updated driver.
- Upgrade Camunda:
helm upgrade camunda camunda/camunda-platform --version X.Y.Z -f values.yaml -n camunda.
Updating custom drivers
If you're supplying a custom driver, update it by:
- Init container approach: Update the driver download URL or image in your Helm values.
- Custom image approach: Rebuild and push a new image with the updated driver.
- ConfigMap/Volume approach: Update the driver JAR in your ConfigMap or PersistentVolume.
Then redeploy:
helm upgrade camunda camunda/camunda-platform -f values.yaml -n camunda
Kubernetes will recreate the pods with the new driver.