For the complete documentation index, see llms.txt. This page is also available as Markdown.

Helm

Deploy the Kitaru server on Kubernetes using the Kitaru Helm chart

The Kitaru Helm chart wraps the ZenML Helm chart as a dependency, overriding defaults to use the Kitaru server image and Kitaru-specific environment variables. All ZenML server features — database migrations, secrets encryption, ingress, autoscaling — are available through the subchart. Server configuration goes under the kitaru.server key in your values file.

Prerequisites

  • A Kubernetes cluster (1.19+)

  • kubectl configured for your cluster

  • Helm 3.x installed

  • Optional but recommended for production: a MySQL 8.0+ database reachable from the cluster

Quick start

helm install kitaru-server oci://public.ecr.aws/zenml/kitaru \
  --version 0.2.0 \
  --namespace kitaru \
  --create-namespace

This starts a single Kitaru server pod with a local SQLite database persisted via a PersistentVolumeClaim. The chart uses the official Kitaru server image, so it inherits the Kitaru UI bundled into that image at release time.

Once the pod is ready, port-forward and connect:

kubectl -n kitaru port-forward svc/kitaru-server-kitaru 8080:80
kitaru login http://localhost:8080

Check the pod is healthy:

Configuration

All configuration is done through a Helm values file. Create a custom-values.yaml with the settings you need (omit everything else to use defaults), then install or upgrade:

Server settings go under kitaru.server. For the full list of available options, see the ZenML Helm chart values — all options are available under the kitaru.server key.

The sections below show what to put in your values file for common scenarios.

Deployment invocation support (workload manager)

Snapshot-backed deployment execution (kitaru invoke, KitaruClient().deployments.invoke(...), and kitaru flow deployments curl) requires server workload-manager support.

The default Kitaru chart/image path already includes this support and the release-bundled Kitaru UI. If you override the image (for example using plain zenmldocker/zenml-server) or replace environment settings, preserve a compatible workload-manager configuration explicitly under kitaru.server.environment.

Persist your data

Default: SQLite with a PVC

Out of the box, the chart creates a PersistentVolumeClaim that stores the SQLite database. Data survives pod restarts and redeployments.

For production, point the server at an external MySQL database. This removes the SQLite limitation and enables horizontal scaling.

The server runs database migrations automatically via a dedicated migration job on first startup and on every upgrade.

Keep the password out of values

Instead of embedding the password in the URL, create a Kubernetes Secret and reference it:

MySQL with SSL

Connect to the server

After deployment, the Helm chart prints connection instructions. The method depends on your Service type.

Port-forward (default: ClusterIP)

LoadBalancer

API key login (headless / CI)

For automation, create an OSS service-account API key first from an already-authenticated admin/operator machine:

These bootstrap commands require your current Kitaru CLI session to have permission to manage service accounts. The headless job only needs the one-time key value from the create response.

Store the one-time key value from the create response, then use it to connect:

See Authentication for the full service-account/API-key flow and how it relates to kitaru auth token.

Disconnect

Expose with Ingress

To make the Kitaru server accessible outside the cluster via a hostname, enable Ingress. This section assumes you have an Ingress controller (e.g. nginx-ingress) and optionally cert-manager already running in your cluster.

Basic Ingress with TLS

First, install cert-manager and nginx-ingress if you have not already:

Create a ClusterIssuer for Let's Encrypt:

Then deploy Kitaru with Ingress enabled:

serverURL tells the server its own external address, used for browser-based login redirects.

If you manage TLS certificates manually, create a Secret and reference it in tls.secretName:

Security

JWT secret key

The chart auto-generates a random JWT signing key on first install and preserves it across upgrades. You do not need to set this for a single-replica deployment.

For multi-replica deployments, all pods must share the same key:

Secrets encryption

Secrets stored by the Kitaru server live in the SQL database. By default they are not encrypted. To encrypt them at rest:

Production example

A complete production values file combining MySQL, Ingress with TLS, secrets encryption, resource limits, and autoscaling:

Install:

Upgrading

The JWT secret key is preserved automatically across upgrades. The server runs a database migration job before the new version starts.

Use a version-pinned image tag (e.g. kitaru.server.image.tag: "0.2.0") that matches your client SDK version to avoid API incompatibilities.

Uninstalling

The PVC created for SQLite persistence is not deleted automatically. To remove it:

Troubleshooting

Pod won't start or CrashLoopBackOff

Common causes:

  • Database connection refused (wrong host/port/credentials in kitaru.server.database.url)

  • Database name contains hyphens (use underscores or plain alphanumeric names)

  • PVC pending — no storage class available or insufficient capacity (kubectl -n kitaru get pvc)

  • Image pull error — wrong repository/tag or missing imagePullSecrets

DB migration job fails

The chart runs a database migration job before starting the server. If it fails:

Common causes:

  • Database is unreachable or credentials are wrong

  • Insufficient database user privileges (needs CREATE TABLE, ALTER TABLE)

Login stalls or shows errors

  • Wait for the readiness probe to pass before attempting login. Check pod status with kubectl -n kitaru get pods.

  • If the CLI keeps printing authorization_pending, the server may not be fully initialized. Wait and retry.

  • Check kubectl -n kitaru logs deploy/kitaru-server-kitaru for error details.

Ingress returns 502/503

  • Confirm the server pod is healthy: kubectl -n kitaru get pods

  • Check the Ingress controller logs for upstream errors.

  • Verify kitaru.server.ingress.host matches your DNS record.

  • If using TLS, check that the TLS Secret exists and contains valid certificate data: kubectl -n kitaru describe secret kitaru-tls

Last updated

Was this helpful?