Installation On Kubernetes

XDM can be installed and operated on a Kubernetes or OpenShift cluster. XDM provides a Helm chart that simplifies configuration and deployment. This section explains how configuration is managed, how to install the Helm chart, and how to maintain the installation.

Configuration Concept

When installing XDM on Kubernetes or OpenShift, configuration is managed in two main places:

  • The values.yaml file used by Helm

  • Kubernetes objects that are created or referenced by the chart

Helm Values (values.yaml)

The Helm chart is configured through a values.yaml file. This file contains all XDM‑specific settings, such as:

  • XDM release version and environment metadata

  • License and security settings

  • Database configuration (internal or external PostgreSQL)

  • User management (local, LDAP, OAuth2)

  • Task execution limits and platforms

  • Loki and Tempo for Logging

  • Persistence, Ingress, and optional services (Grafana, Elasticsearch, sample database)

You pass your customized values.yaml file to the helm install and helm upgrade commands. For an overview of all available parameters, refer to Configuration Parameters.

Kubernetes Objects

The Helm chart creates and uses several standard Kubernetes objects:

  • ConfigMaps – Store non‑sensitive configuration that is injected into the XDM services. Most of this configuration is derived from the values in values.yaml.

  • Secrets – Store sensitive data such as:

  • XDM license (or a reference to a license secret)

  • Database credentials

  • LDAP / OAuth2 client secrets

  • Password seed and JWT secrets These secrets can either be created by the chart (from values) or referenced as existing Kubernetes secrets.

  • PersistentVolumeClaims (PVCs) – Provide persistent storage for:

  • XDM task working directories and logs

  • The internal PostgreSQL database

  • Optional services like Grafana, Elasticsearch, or the sample database

You define how these objects are created and used via the persistence, database, security, and related sections in values.yaml. For details, see "Persistence" and the related configuration chapters.

Prerequisites

To install XDM on Kubernetes or OpenShift, you need:

  • A running Kubernetes or OpenShift cluster.

  • A local installation of Helm version 3.

  • Helm configured to access the target cluster (for example, via kubectl config).

  • Sufficient access rights in the target namespace to create:

  • Deployments, StatefulSets, Services, Ingresses

  • ConfigMaps, Secrets

  • PersistentVolumeClaims

  • Network and resource prerequisites that match your planned XDM usage

  • A valid XDM license key with the CloudSupport option enabled.

  • For resource and hardware requirements, refer to System Requirements.

Installing The Helm Chart

Installing XDM with Helm consists of three basic steps:

  1. Add the XDM Helm repository.

  2. Update the local repository index.

  3. Install the chart with your customized values.yaml.

Adding The Helm Repository

First, add the XDM Helm repository to your local Helm installation:

helm repo add ubs https://www.ubs-hainer.com/downloads/XDM3/helm

This command registers the repository under the name ubs. You only need to do this once per Helm setup.

Updating The Repository Index

Before installing or upgrading XDM, update the local repository index:

helm repo update

This command downloads the latest index of the ubs chart repository so that Helm can resolve the available XDM versions.

Installing The Chart

Prepare a values.yaml file that contains at least all mandatory parameters (see Configuring values.yaml).

Then install XDM with:

helm install <NAME> ubs/xdm \
  -f <VALUES_FILE> \
  --version <XDM_RELEASE> \
  --namespace <NAMESPACE> \
  --create-namespace
<NAME>

Logical name of the Helm release (for example xdm-prod or xdm-test). You will use this name for future helm upgrade commands.

<VALUES_FILE>

Specify the name to the helm chart file. For more information on the values.yaml file, see Configuring values.yaml.

<XDM_RELEASE>

The XDM version to install. If you omit --version, Helm installs the latest stable XDM version.

<NAMESPACE>

Kubernetes namespace for the XDM installation. All deployments, pods, services, and other resources will be created in this namespace. If you omit --create-namespace, the namespace must already exist.

To list all available XDM versions in the repository, run:

helm search repo ubs/xdm -l

After the installation, verify that all pods in the namespace reach the Running state, for example:

kubectl get pods --namespace <NAMESPACE>

Optional Rootless configuration

For security reasons, the default to run the XDM containers is using non-root users. For more Information about the non-root user Configuration for XDM, see Non-Root User Container Configuration.

Updating The Release

For further information on updating XDM, refer to the article Update.

Once XDM is installed, you will regularly apply configuration changes and version upgrades using helm upgrade. To change configuration values or upgrade to a newer XDM version, update your values.yaml and run:

helm upgrade <NAME> ubs/xdm \
  -f <VALUES_FILE> \
  --version <NEW_XDM_RELEASE> \
  --namespace <NAMESPACE>
  • Reuse the same <NAME> and <NAMESPACE> you used for helm install.

  • Define the Chart configuration file (values.yaml).

  • Adjust xdm.version in values.yaml to match <NEW_XDM_RELEASE>.

  • Review the release notes for any migration steps or deprecated settings before upgrading.

After the upgrade, monitor the pods and logs to ensure that XDM starts correctly:

kubectl get pods --namespace <NAMESPACE>
kubectl logs deploy/xdm-core --namespace <NAMESPACE>

Configuring values.yaml

The values.yaml file controls almost all aspects of an XDM installation. This section explains which parameters you must set, which you should review for most installations, and where to find detailed descriptions.

Overview Of Parameters

The Helm chart exposes many configuration options, grouped into logical sections such as:

  • General XDM settings (release, environment metadata)

  • Security and user management

  • Database and persistence

  • Ingress and network access

  • Optional services (Grafana, Elasticsearch, sample database)

  • Configuration as Code (CaSC)

A complete reference of all common parameters is available in Configuration Parameters.

In this section, we focus on the most important settings for a basic installation.

When installing on an OpenShift system, refer also to Open Shift Customization

Configuring Mandatory Parameters

For a functional and licensed XDM installation all mandatory Docker images must be available and all services are running.

Furthermore, you must at least configure:

Furthermore, it is possible to set the XDM release version, but in most cases it is predefined in the helm chart.

Example skeleton:

xdm:
  license: |
    LICENSE = ...
    LIC0001 = COMPANY:...
    ...
  # Or reference an existing secret instead of inline license:
  # licenseSecret: xdm-license-secret

security:
  passwordSeed: "<secure-random-string>"
  # Or reference an existing secret:
  # secret: xdm-password-seed-secret

database:
  extern: false
  # For external database set extern: true and configure url, user, and secret.
xdm.license / xdm.licenseSecret

Provide either the license content directly or reference a Kubernetes secret.

security.passwordSeed / security.secret

Required for secure password handling.

database

Controls whether you use the internal PostgreSQL container or an external PostgreSQL instance. See Admin Database configuration for details.

Never use trivial or guessable password seeds in production. For secrets, prefer Kubernetes secrets rather than plain text values.

Configuring Recommended Parameters

For most real‑world installations you should also configure:

Example:

repository: docker.ubs-hainer.com
imagePullSecrets:
  - xdm-pull-secret

xdm:
  timezone: Europe/Berlin
  environment:
    id: "prod"
    name: "Production"
    color: "blue"
  certificates:
    - xdm-ca-certificates

  jdbcDriversCommand: |-
    wget -P /xdm/config/jdbc-drivers/ -v --no-check-certificate \
      https://jdbc.postgresql.org/download/postgresql-42.3.3.jar

security:
  jwt:
    expireTime: 3600
    validTime: 3600
    secret: "<jwt-secret-value>"

userManagement:
  # Example: ldap configuration
  ldap: ...

For environments that must integrate with corporate identity providers, configure:

  • userManagement.ldap for LDAP / Active Directory

  • userManagement.oauth2 for OAuth2 / OpenID Connect providers

See the dedicated configuration chapters for details on each option:

Persistence (PVCs)

Persistence is configured in the persistence section:

persistence:
  data:
    storageClass: <storage-class>
    accessMode: ReadWriteMany
    size: 100Gi
  postgres:
    storageClass: <storage-class>
    accessMode: ReadWriteOnce
    size: 50Gi
  # Optional volumes, depending on enabled services:
  # sample:
  # grafana:
  # elasticsearch:
data

Stores XDM task working directories, logs, and reports. This volume is shared by multiple pods (core and dataflow).

postgres

Stores data of the integrated PostgreSQL database. Not required if you use an external database.

sample, grafana, elasticsearch, graph_store, neo4j, file_sink, loki, tempo

Only needed if the respective services are enabled.

We highly recommend using a cloud storage solution that supports the ReadWriteMany access mode. Without ReadWriteMany, the core and dataflow pods must run on the same node, which removes many of the advantages of Kubernetes (such as flexible scheduling and better resilience). If you still want to use this approach as a temporary workaround to ensure both pods are scheduled on the same node, see Configuring Pod Affinity.

For a detailed description of all persistence options, see Persistence.

Configuring Ingress

To expose the XDM web UI via HTTP/HTTPS, configure the ingress section:

ingress:
  enabled: true
  domain: xdm.example.com
  annotations:
    # Example for NGINX basic auth:
    # nginx.ingress.kubernetes.io/auth-type: basic
    # nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
  tls:
    - hosts:
        - xdm.example.com
      secretName: xdm-tls
  ingressClassName: nginx
domain

Public domain name for the XDM UI.

annotations

Ingress‑specific options, for example authentication, rate limiting, or older ingress class settings.

tls

Hosts and TLS secret to enable HTTPS access.

ingressClassName

Ingress controller class (Kubernetes 1.18+). For older clusters, use kubernetes.io/ingress.class via annotations.

Configuring Optional Services

Depending on your use case, you can enable additional services such as:

These are typically controlled via dedicated sections in values.yaml, for example:

casc:
  enabled: true
  url: https://git.example.com/xdm-config.git
  branch: main
  path: config
  cron: "0 * * * *"
  secret: xdm-casc-git-credentials

Security context

A securityContext in Kubernetes defines security and access control settings for a pod or container. These settings can be used to control how the container runs, such as whether it runs as a root user, what user and group memberships it has, and what file system permissions it has.

The following represents a list of the most significant fields that may be used in a securityContext:

runAsUser

Specify the user ID under which the container is running.

runAsGroup

Specify the group ID under which the container is executed.

runAsNonRoot

Forces the container not to be executed as the root user.

fsGroup

Specify the group ID used for all files in the container’s file system.

<service>:
    securityContext:
        runAsUser: 1002
        runAsGroup: 1000
        runAsNonRoot: true
        fsGroup: 2000
service

The name of the service. Possible service are:

  • core

  • dataflow

  • file_sink

  • elasticsearch

  • generator_source

  • grafana

  • graph_store

  • loki

  • postgres

  • prometheus

  • sample

  • tempo

  • ui

  • webservice_apply_sink

  • webservice_extract_source

  • ai_assistance

Service account

In a Kubernetes environment, the service account section refers to the configuration of service accounts for a range of services within a Kubernetes cluster. A service account in Kubernetes is a specific type of account that pods use to facilitate communication with the Kubernetes API server.

In addition to the global defaultServiceAccount setting which applies to all containers / pods, the serviceAccount can be overridden for individual containers.

To specify a serviceAccount per container, use the following syntax:

<service>:
    serviceAccount: "xdm-<service>-account"
service

The name of the service for which the service account is configured. Possible services are:

  • core

  • dataflow

  • file_sink

  • elasticsearch

  • generator_source

  • grafana

  • graph_store

  • loki

  • postgres

  • prometheus

  • sample

  • tempo

  • ui

  • webservice_apply_sink

  • webservice_extract_source

  • ai_assistance

Task execution platforms

XDM allows the definition of different execution platforms. An own Kubernetes Pod is started for each task execution. The system settings of the Pod are based on the platform settings. XDM defines a default platform. The settings of the default platform can be customized as seen below. To add a new platform add a new sub-entry to the deployer.platform setting.

The platform name must not start with a number or contain special characters.
deployer:
  platform:
    default:
      limits:
        cpu: 500m
        memory: 1024Mi
      requests:
        cpu: 500m
        memory: 1024Mi

The following example adds the new platform example. Each task execution that runs on that platform can use up to 4GB main storage.

deployer:
  platform:
    example:
      limits:
        memory: 4096Mi
      requests:
        memory: 4096Mi

OpenShift specific customization

In open shift it is not allowed to run the docker container as root user. Therefore, you have to customize your images to grant access to the internal directories and use ports > 1024 which can be bound by a none root user. In this case, the property runAsNonRoot: must set to true in all security contexts.