Prerequisites
Before you begin the installation of DataQI, ensure that your environment meets the following requirements.
Kubernetes cluster
Section titled “Kubernetes cluster”- A supported Kubernetes distribution (e.g., AKS, OpenShift, RKE2, or vanilla Kubernetes). If you are deploying to OpenShift, refer to the OpenShift installation guide for platform-specific requirements.
- Kubernetes version 1.28 or higher.
- At least 4 vCPUs and 16GB of RAM available for the core DataQI components.
- A default StorageClass configured for dynamic volume provisioning. If your cluster lacks a default storage class, you must explicitly set
platform.storageClass.default: "your-class-name"in yourvalues.yamlfile so the PostgreSQL database instances can start up. Additionally, you must override the upstream NATS JetStream storage class by settingnats.config.jetstream.fileStore.pvc.storageClassName: "your-class-name". - A StorageClass that supports ReadWriteMany (RWX) access modes (e.g., Azure Files or CephFS) for both application file store claims. Set
platform.storageClass.sharedto use one class for both claims, or setplatform.sharedFilesystem.storageClassandplatform.persistentFilesystem.storageClassindependently. The persistent class should support the backup or snapshot policy required by your organisation.
Command line tools
Section titled “Command line tools”You will need the following tools installed on your local machine or host:
kubectlconfigured with administrative access to your target cluster.helm
Container registry access
Section titled “Container registry access”DataQI images and Helm charts are hosted in a secure, private container registry.
You must obtain the registry credentials from your DataQI account representative. These credentials will be used to create the image pull secret in your cluster and to authenticate your local Helm client. Please download and securely store these credentials once you receive them.
Networking and DNS
Section titled “Networking and DNS”To successfully route traffic to your DataQI installation, your cluster must have the following networking infrastructure established:
- Gateway API implementation: A Gateway API controller (such as NGINX Gateway Fabric, Cilium, or Azure Application Gateway for Containers) to handle incoming HTTP/HTTPS traffic. Standard Kubernetes Ingress is also supported via
routing.type: ingress. - DNS configuration: You must own a base domain (e.g.,
dataqi.yourdomain.com) to configure the chart. You must be able to create DNS records (A or CNAME) pointing this domain to the public IP address or FQDN of your cluster’s load balancer. - TLS: DataQI supports four TLS modes — cert-manager automation, pre-provisioned secrets, external termination (Cloudflare, WAF), and plain HTTP for development. See the TLS certificate configuration guide for details.
Cluster operators
Section titled “Cluster operators”DataQI relies on two Kubernetes Operators that must be installed on the cluster before deploying the Helm chart. These operators extend Kubernetes with Custom Resource Definitions (CRDs) that the DataQI chart uses to declare its database and identity infrastructure.
CloudNative-PG (CNPG)
Section titled “CloudNative-PG (CNPG)”CNPG manages the PostgreSQL database clusters used by DataQI.
For all other installations, apply the operator manifest once per cluster before deploying the Helm chart:
# Install the CNPG operator (check for the latest stable version at https://cloudnative-pg.io)kubectl apply --server-side -f \ https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.25/releases/cnpg-1.25.1.yamlVerify the operator is running:
kubectl get deployment -n cnpg-system cnpg-controller-managerKeycloak Operator
Section titled “Keycloak Operator”The Keycloak Operator manages the identity server used by DataQI. It handles pod lifecycle, rolling upgrades, and high-availability clustering.
The DataQI Helm chart deploys the operator per-namespace — each environment gets its own operator instance with namespace-scoped RBAC only. No cluster-wide bindings are required.
However, Custom Resource Definitions (CRDs) and ClusterRoles are inherently cluster-scoped and must be installed once by a cluster administrator:
# Install the CRDs (cluster-scoped — required once per cluster)kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/refs/tags/26.6.1/kubernetes/keycloaks.k8s.keycloak.org-v1.ymlkubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/refs/tags/26.6.1/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml
# Install the ClusterRoles (permission definitions only — they grant nothing# without a binding). The Helm chart creates namespace-scoped RoleBindings# referencing these ClusterRoles.kubectl apply -f - <<'EOF'apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: keycloakcontroller-cluster-role labels: app.kubernetes.io/name: keycloak-operatorrules: - apiGroups: ["k8s.keycloak.org"] resources: ["keycloaks", "keycloaks/status", "keycloaks/finalizers"] verbs: ["get", "list", "watch", "patch", "update", "create", "delete"] - apiGroups: [""] resources: ["services"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] - apiGroups: ["apps"] resources: ["statefulsets"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses", "networkpolicies"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] - apiGroups: [""] resources: ["secrets"] verbs: ["create", "delete", "get", "list", "watch"] - apiGroups: ["monitoring.coreos.com"] resources: ["servicemonitors"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: keycloakrealmimportcontroller-cluster-role labels: app.kubernetes.io/name: keycloak-operatorrules: - apiGroups: ["k8s.keycloak.org"] resources: ["keycloakrealmimports", "keycloakrealmimports/status", "keycloakrealmimports/finalizers"] verbs: ["get", "list", "watch", "patch", "update", "create", "delete"] - apiGroups: ["batch"] resources: ["jobs"] verbs: ["create", "delete", "get", "list", "patch", "watch"] - apiGroups: [""] resources: ["secrets"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]EOFVerify the CRDs are installed:
kubectl get crd keycloaks.k8s.keycloak.org keycloakrealmimports.k8s.keycloak.org