Production deployment
A production deployment requires database provisioning, secrets, access control, network policy, storage, and backups.
It is recommended that okapictl be installed from PyPI
before starting the deployment:
python -m pip install okapi-ctlFor command options and controller versioning guidance, see the
okapictl reference.
Helm charts are published with every Okapi release as OCI artifacts under
oci://ghcr.io/okapi-core/charts. The Kubernetes installation deploys only
Okapi: ops, ingester, oscar, and web. PostgreSQL and ClickHouse are
production dependencies and must be deployed and operated separately.
Prerequisites
You’ll need:
- a Kubernetes cluster and a configured
kubectlcontext; - Helm 3 with OCI registry support;
- PostgreSQL and ClickHouse reachable through Kubernetes Services;
- the matching PostgreSQL and ClickHouse credentials;
- an OpenAI API key for Oscar, if AI-assisted investigation is required; and
okapictlinstalled at the same release as the Okapi charts.
Before installing Okapi, configure PostgreSQL and ClickHouse as described in the PostgreSQL configuration guide and the ClickHouse configuration guide. This deployment guide assumes those databases, users, permissions, and ClickHouse cluster settings are already in place.
Select the target context and create the namespace:
kubectl config use-context <context-name>
kubectl create namespace okapi --dry-run=client -o yaml | kubectl apply -f -Create the reserved Secrets
Create these Secrets in the Okapi namespace. The Secret names and keys form the interface between the deployment configuration and the Helm charts:
kubectl -n okapi create secret generic okapi-clickhouse \
--from-literal=username=<clickhouse-user> \
--from-literal=password='<clickhouse-password>'
kubectl -n okapi create secret generic okapi-postgres \
--from-literal=migration-username=<migration-user> \
--from-literal=migration-password='<migration-password>' \
--from-literal=web-username=<web-user> \
--from-literal=web-password='<web-password>' \
--from-literal=oscar-username=<oscar-user> \
--from-literal=oscar-password='<oscar-password>'
kubectl -n okapi create secret generic okapi-openai \
--from-literal=api-key='<openai-api-key>'The ClickHouse Secret contains the client account used by ops and
ingester; it is not used for ClickHouse inter-node authentication. The
PostgreSQL Secret contains three accounts: migration, Web runtime, and Oscar
runtime. The OpenAI Secret is only needed when Oscar’s AI-assisted features
are enabled.
Verify that the Secrets exist without printing their values:
kubectl -n okapi get secret okapi-clickhouse okapi-postgres okapi-openai
for item in \
okapi-clickhouse:username \
okapi-clickhouse:password \
okapi-postgres:migration-username \
okapi-postgres:migration-password \
okapi-postgres:web-username \
okapi-postgres:web-password \
okapi-postgres:oscar-username \
okapi-postgres:oscar-password \
okapi-openai:api-key; do
secret="${item%%:*}"
key="${item#*:}"
kubectl -n okapi get secret "$secret" \
-o go-template="{{if not (index .data \"$key\")}}missing $secret/$key{{end}}"
donePrepare values
Create a directory containing these four files:
ops-values.yaml
ingester-values.yaml
oscar-values.yaml
web-values.yamlUse the version-matched templates bundled with okapictl, then replace the
placeholders with the PostgreSQL and ClickHouse Service names, database names,
and Secret references. The important settings are:
ops-values.yaml:
clickhouse:
host: okapi-clickhouse
port: 8123
existingSecret: okapi-clickhouse
usernameKey: username
passwordKey: password
postgres:
url: jdbc:postgresql://<postgres-service>:5432/okapi_oscar?currentSchema=okapi_web
existingSecret: okapi-postgres
usernameKey: migration-username
passwordKey: migration-passwordingester-values.yaml:
clickhouse:
host: okapi-clickhouse
port: 8123
existingSecret: okapi-clickhouse
usernameKey: username
passwordKey: passwordweb-values.yaml:
postgres:
host: <postgres-service>
port: 5432
database: okapi_oscar
schema: okapi_web
existingSecret: okapi-postgres
usernameKey: web-username
passwordKey: web-passwordoscar-values.yaml:
postgres:
host: <postgres-service>
port: 5432
database: okapi_oscar
schema: okapi_oscar
existingSecret: okapi-postgres
usernameKey: oscar-username
passwordKey: oscar-password
openai:
existingSecret: okapi-openai
apiKeyKey: api-keyKeep the image repository and tag pinned to the same Okapi release across all four files. If you change a Secret key, database name, schema name, or Service name, update the corresponding value in every affected file.
Install Okapi
Point okapictl to the values directory:
okapictl install --k8s \
--namespace okapi \
--values-dir ./okapi-values \
--timeout 900The controller installs the charts in dependency order:
ops → ingester → oscar → webIt uses the current kubectl context and does not change cluster selection or
install PostgreSQL or ClickHouse. To check the resulting workloads:
kubectl -n okapi get pods,deployments,jobs
helm -n okapi list
kubectl -n okapi get events --sort-by=.lastTimestampAdmins note
Why databases are external
Okapi does not prescribe a production PostgreSQL or ClickHouse topology. Capacity, availability, storage, backup, and recovery requirements vary with telemetry volume and organizational policy. Operate and scale both databases independently, and use Okapi’s PostgreSQL and ClickHouse dashboards to monitor throughput, latency, and resource usage.