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>

Enterprise Deployment With CI/CD

In enterprise environments, XDM is usually not installed or upgraded manually from a local workstation. Instead, the Helm-based deployment is typically integrated into an existing CI/CD or GitOps process.

The Helm commands shown in the previous section can still be used as a technical reference. In an enterprise setup, these commands are usually executed by predefined pipeline jobs or by a deployment controller. The exact process depends on the customer’s internal platform, repository structure, security requirements, and approval workflow.

Basic Deployment Model

A typical enterprise deployment separates the following concerns:

  • the XDM Helm chart

  • the XDM default values provided with the chart

  • environment-specific configuration

  • secrets, certificates, and credentials

  • container images

  • deployment automation

  • monitoring and verification

The following diagram shows a generalized deployment flow:

flowchart TD A[XDM Helm chart] --> B[Internal Git or Helm repository] B --> C[CI/CD pipeline or GitOps controller] C --> D[Kubernetes namespace] D --> E[Monitoring and operational checks] A:::source B:::repo C:::pipeline D:::runtime E:::monitoring classDef source fill:#e8f1ff,stroke:#4a75b5,stroke-width:1px classDef repo fill:#eef7e8,stroke:#5b8f3a,stroke-width:1px classDef pipeline fill:#fff4df,stroke:#c2872f,stroke-width:1px classDef runtime fill:#f2e8ff,stroke:#7a57b8,stroke-width:1px classDef monitoring fill:#f8f8f8,stroke:#666,stroke-width:1px

This model can be implemented in different ways. Some organizations store the Helm chart and the environment-specific configuration in the same repository. Other organizations keep the Helm chart in one repository and maintain the customer-specific values in a separate repository. Some environments use a central deployment platform that combines chart defaults, environment values, secrets, certificates, and additional configuration at deployment time.

Before defining the XDM deployment process, verify which mechanism is used in the target organization.

Repository And Configuration Layout

The repository layout is organization-specific. Common layouts include:

  • a single Git repository that contains the Helm chart and the environment-specific values files

  • one repository for the Helm chart and another repository for the environment-specific configuration

  • an internal Helm repository for chart packages and a Git repository for values files

  • a GitOps repository that contains the desired deployment state for each environment

The following diagram shows two common repository models:

flowchart LR subgraph ModelA["Model A: Chart and values in one repository"] A1[Deployment repository] A2[Helm chart] A3[dev-values.yaml] A4[test-values.yaml] A5[prod-values.yaml] A1 --> A2 A1 --> A3 A1 --> A4 A1 --> A5 end subgraph ModelB["Model B: Chart and values in separate repositories"] B1[Chart repository] B2[Helm chart] B3[Configuration repository] B4[dev-values.yaml] B5[test-values.yaml] B6[prod-values.yaml] B1 --> B2 B3 --> B4 B3 --> B5 B3 --> B6 end

Common tools and platforms used for these purposes include:

  • Git repositories, such as GitLab, GitHub, Bitbucket, Azure Repos, or Gerrit

  • CI/CD systems, such as Jenkins, GitLab CI/CD, GitHub Actions, Azure DevOps, TeamCity, or Tekton

  • GitOps tools, such as Argo CD or Flux CD

  • internal artifact or container registries, such as JFrog Artifactory, Sonatype Nexus Repository, Harbor, Azure Container Registry, Amazon ECR, Google Artifact Registry, or OpenShift Image Registry

These tools are examples only. Use the tools and approval processes that are defined by the operating organization.

Managing values.yaml In Git

The environment-specific values.yaml file is typically stored in Git. This makes the deployment configuration version-controlled, reviewable, and reproducible.

Use separate values files, directories, branches, or repositories for different environments. For example:

  • Development

  • Test

  • Staging

  • Production

Typical file names are:

dev-values.yaml
test-values.yaml
staging-values.yaml
prod-values.yaml

Some organizations use the file extension .yml instead of .yaml. Both formats are technically common. Use the naming convention that is defined for the respective repository.

Configuration changes should be committed and reviewed before they are deployed to a Kubernetes cluster. For production environments, use the approval workflow required by the organization, for example a merge request, pull request, change request, or release approval.

Avoid making direct, undocumented changes to Helm templates. If direct template changes are required, document them explicitly and review them during every XDM version update. Where possible, implement environment-specific behavior through values files instead of changing chart templates.

Obtaining The XDM Helm Chart

The XDM Helm chart can be obtained from the UBS Hainer Helm repository.

helm repo add ubs https://www.ubs-hainer.com/downloads/XDM3/helm
helm repo update
helm search repo xdm -l

Use helm search repo xdm -l to list the available chart versions. Select the chart version that matches the XDM version planned for the deployment.

If the chart package must be downloaded for review, archiving, or mirroring, use helm pull. For example:

helm pull ubs/xdm --version <XDM_RELEASE>

For an enterprise deployment, the CI/CD process can use the UBS Hainer Helm repository directly if external access is permitted. If the Kubernetes or CI/CD environment is not allowed to access external repositories, mirror the required chart version to an internal Helm repository first. In that case, the deployment job should reference the internal Helm repository instead of the UBS Hainer repository.

Mirroring Container Images

Many enterprise Kubernetes environments do not allow workloads to pull container images directly from external registries. In such environments, the required XDM images must be copied to an internal container registry first.

After mirroring the images, update the image references in the relevant values file so that Kubernetes pulls the images from the internal registry.

A simplified values fragment can look like this:

image:
  repository: <INTERNAL_REGISTRY>

The exact configuration depends on the registry structure and on the image settings used by the Helm chart and the values file.

This list shows the available XDM images that must be mirrored to the internal registry.

Mandatory images
docker.ubs-hainer.com/xdm3-core:<version>
docker.ubs-hainer.com/xdm3-dataflow:<version>
docker.ubs-hainer.com/xdm3-ui:<version>
docker.ubs-hainer.com/xdm3-prime-ui:<version>
docker.ubs-hainer.com/postgres:15
docker.ubs-hainer.com/xdm3-grafana:<version>
docker.ubs-hainer.com/xdm3-prometheus:<version>
docker.ubs-hainer.com/xdm3-loki:<version>
docker.ubs-hainer.com/xdm3-tempo:<version>
Optional for Data Generation
docker.ubs-hainer.com/xdm3-ai-assistance:<version>
docker.ubs-hainer.com/xdm3-file-sink:<version>>
docker.ubs-hainer.com/xdm3-graph-store:<version>
docker.ubs-hainer.com/xdm3-mcp:<version>
Optional for Global Search
docker.ubs-hainer.com/elasticsearch:8.19.19
Optional for Test Data Finder
docker.ubs-hainer.com/neo4j:4.4
Optional for Sample Environment
docker.ubs-hainer.com/linuxserver/openssh-server:version-9.0_p1-r2
docker.ubs-hainer.com/sample-environment:<version>

Recommended checks after image mirroring:

  • Verify that all required XDM images are available in the internal registry.

  • Verify that the image tags match the XDM version and the Helm chart version that will be deployed.

  • Verify that the Kubernetes cluster can pull the images from the internal registry.

  • Verify that required image pull secrets are available in the target namespace, if the registry requires authentication.

It is recommended to create a dedicated CI/CD job for image mirroring. This job should copy the required XDM images from the external source registry to the internal registry and make the result visible in the pipeline log. Depending on the organization’s process, this job can run manually for each XDM update or automatically when a new approved XDM version is prepared.

CI/CD Jobs For Deployment

The actual installation or upgrade is usually executed by predefined CI/CD jobs. These jobs run the required Helm commands with the correct chart version, namespace, release name, and values file.

A deployment job typically defines or receives the following parameters:

  • target environment

  • Kubernetes namespace

  • Helm release name

  • Helm chart name or chart package

  • Helm chart version

  • values file or values source

  • container registry configuration

  • credentials or references to existing secrets

For example, a CI/CD job may execute a command similar to the example in Installing The Helm Chart:

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

Depending on the internal process, the command can also reference an internal chart repository or a locally checked-out chart instead of the external Helm repository.

If the chart was mirrored to an internal Helm repository, replace ubs/xdm with the chart reference used by the internal repository.

In GitOps-based environments, the pipeline may not run helm upgrade directly. Instead, it updates the desired state in Git. A GitOps controller then applies the change to the Kubernetes cluster.

The following diagram shows the difference between a CI/CD-based deployment and a GitOps-based deployment:

flowchart TD subgraph CICD["CI/CD-based deployment"] C1[Change values file in Git] C2[Review and approve change] C3[Run deployment pipeline] C4[Pipeline executes Helm command] C5[Kubernetes applies XDM resources] C1 --> C2 --> C3 --> C4 --> C5 end subgraph GitOps["GitOps-based deployment"] G1[Change desired state in Git] G2[Review and approve change] G3[Merge change] G4[GitOps controller detects change] G5[Controller applies XDM resources] G1 --> G2 --> G3 --> G4 --> G5 end

A typical deployment process in an enterprise environment is:

  1. Update the environment-specific values file or deployment configuration in Git.

  2. Commit the changes.

  3. Create a merge request or pull request.

  4. Review and approve the changes.

  5. Mirror the required XDM container images to the internal registry, if required.

  6. Run the predefined CI/CD deployment job or let the GitOps controller apply the approved change.

  7. Verify the deployment in the target Kubernetes namespace.

  8. Continue with the next environment only after the previous environment has been verified.

For staged rollouts, use the environment sequence defined by the operating organization. A common sequence is:

flowchart LR DEV[Development] --> TEST[Test] TEST --> STAGE[Staging] STAGE --> PROD[Production]

Update Procedure

When updating XDM to a new version, review both the Helm chart and the environment-specific configuration.

A typical update procedure is:

  1. Obtain the new XDM Helm chart version.

  2. Compare the new chart with the currently deployed chart.

  3. Review changes in the chart templates and in the default values.yaml.

  4. Identify new, changed, removed, or renamed configuration parameters.

  5. Check whether existing environment-specific values are still valid.

  6. Check whether direct template modifications exist and whether they must be reapplied or can be replaced by values.

  7. Update the environment-specific values files.

  8. Update the chart version in the deployment configuration or CI/CD job.

  9. Mirror the required XDM container images to the internal registry.

  10. Deploy the update to the first non-production environment.

  11. Verify the deployment.

  12. Continue through the remaining environments according to the organization’s rollout process.

The following diagram summarizes the update procedure:

flowchart TD A[Obtain new XDM Helm chart] --> B[Compare chart with current version] B --> C[Review values.yaml and templates] C --> D[Update environment-specific values] D --> E[Update CI/CD or GitOps configuration] E --> F[Mirror required container images] F --> G[Deploy to first non-production environment] G --> H[Verify deployment] H --> I{More environments?} I -- Yes --> J[Deploy to next environment] J --> H I -- No --> K[Update completed]

During the chart comparison, pay special attention to the following areas:

  • image repositories and image tags

  • environment variables

  • resource requests and limits

  • persistence settings

  • services and ingress settings

  • secrets and certificate mounts

  • volume definitions

  • configuration keys that were added, removed, or renamed

If direct changes were made to Helm templates in an earlier version, review each change explicitly. Direct template changes can make updates more complex because they must be compared and possibly re-applied for every new chart version.

Verification After Deployment

After the CI/CD job or GitOps synchronization has completed, verify the deployment in the target Kubernetes namespace.

Check the pod status:

kubectl get pods --namespace <NAMESPACE>

Typically, there is also a monitoring platform that provides a central overview of the cluster and the deployed services.

All required pods should reach the expected running state. If a pod does not start, inspect the pod events and logs.

Check logs if required:

kubectl logs deploy/<XDM-SERVICE> --namespace <NAMESPACE>

Depending on the organization’s monitoring setup, also check the central monitoring platform for:

  • failed deployments

  • pods in an error state

  • repeated restarts

  • unavailable services

  • resource pressure

  • image pull errors

  • configuration or startup errors

Only continue with the next environment after the deployment has been verified successfully.

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:
  - name: 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

  • 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

  • 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

Deactivation of role, role binding and service account creation

If it is not allowed to create roles, role bindings and service accounts from the helm chart, you can deactivate the creation of these resources by setting the following values in your values.yaml file:

xdm:
  createRole: false

When setting createRole to false, the helm chart will not create any roles, role bindings or service accounts for the XDM services.

The creation of roles, role bindings and service accounts must be done manually by the cluster administrator, without this it is not possible to run the XDM executions in the cluster.

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.