Skip to content

OpenShift installation

OpenShift enforces strict Security Context Constraints (SCC) policies that prevent certain resources from being managed inside a standard Helm release. Deploying DataQI on OpenShift (or Azure Red Hat OpenShift - ARO) therefore requires a two-phase installation process.

  1. Phase 1 — Install the CloudNativePG (CNPG) operator and its SecurityContextConstraints as raw manifests, outside of Helm.
  2. Phase 2 — Install the DataQI Helm chart with the embedded CNPG sub-chart disabled.

The CNPG operator requires a custom SecurityContextConstraints (SCC) to run with its required UID (10001). The SCC is a cluster-scoped, OpenShift-specific resource. It cannot be cleanly managed inside a namespaced Helm release alongside the application resources. Installing it separately keeps the Helm release idempotent and avoids conflicts if the CNPG operator is already present on the cluster.


Phase 1: Cluster bootstrap (run once per cluster)

Section titled “Phase 1: Cluster bootstrap (run once per cluster)”
Terminal window
kubectl create namespace <namespace>

Apply the CNPG operator as a raw manifest. Use the version pinned in the chart’s Chart.yaml:

Terminal window
# Apply the operator manifest using server-side apply
kubectl apply --server-side --force-conflicts -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.25/releases/cnpg-1.25.1.yaml

Wait for the operator to become ready:

Terminal window
kubectl rollout status deployment/cnpg-controller-manager -n cnpg-system

1c. Apply the CNPG SecurityContextConstraints

Section titled “1c. Apply the CNPG SecurityContextConstraints”

The SCC grants the CNPG operator the permissions it needs to run under OpenShift’s restricted-v2 policy.

Download the cnpg-scc.yaml manifest and apply it to your cluster:

Terminal window
kubectl apply -f cnpg-scc.yaml

1d. Ensure there is a RWX storage class available

Section titled “1d. Ensure there is a RWX storage class available”

The DataQI cache and persistent filesystem claims both require a ReadWriteMany (RWX) storage class. On Azure and many other cloud providers, this must be created manually as the default storage classes are RWO only, for example:

azure-file-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azure-file
provisioner: file.csi.azure.com
parameters:
skuName: Standard_LRS
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate
Terminal window
kubectl apply -f azure-file-storage-class.yaml

1e. Create a NetworkPolicy for Operator Communication

Section titled “1e. Create a NetworkPolicy for Operator Communication”

If your OpenShift cluster enforces a default-deny network policy, the CNPG operator (running in cnpg-system) will be unable to communicate with the Postgres pods (running in your DataQI namespace). The operator requires access to port 8000 on the Postgres pods to check their health and status.

Apply a NetworkPolicy in your DataQI namespace to allow this ingress traffic:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-cnpg-operator
# Change this to your DataQI installation namespace
namespace: dataqi
spec:
podSelector: {} # Selects all pods in the DataQI namespace
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: cnpg-system
ports:
- protocol: TCP
port: 8000

With the cluster bootstrapped, install the main chart. The CNPG sub-chart must be disabled because the operator is already running from Phase 1.

Terminal window
helm upgrade --install dataqi ./dataqi-<chart-version>.tgz \
--namespace <namespace> \
-f <values-file>.yaml

Your customer values file must include the following OpenShift-specific configurations:

# Disable CNPG sub-chart — operator was installed in Phase 1
cloudnative-pg:
enabled: false
platform:
openshift:
enabled: true # Enables SCC and Ingress resources
azureAlb:
healthCheckPolicy:
enabled: false # Azure ALB must be disabled on non-Azure clusters
storageClass:
shared: "<rwx-storage-class>" # RWX default for cache and persistent claims
# Optional: use separate RWX classes when persistent storage has a different backup policy.
# sharedFilesystem:
# storageClass: "<cache-rwx-storage-class>"
# persistentFilesystem:
# storageClass: "<backed-up-rwx-storage-class>"
routing:
type: "ingress"
provider: "openshift" # Configures routing for OpenShift routes/ingress

Some pre-configured OpenShift clusters (such as ARO) typically provide a wildcard DNS entry (e.g., *.apps.<cluster>.aroapp.io). All three DataQI hostnames must be single-level subdomains of that wildcard.

Set global.domain to a subdomain of apps.*, not to apps.* itself:

global:
# Correct — all three generated hostnames match *.apps.<cluster>
domain: "dataqi.apps.<cluster>.aroapp.io"
# Wrong — generated hostnames (e.g., api-apps) do not match the wildcard
global:
domain: "apps.<cluster>.aroapp.io"