Self-host (K8s/Openshift)
Enterprise only!
Self-deployment of the Vulavula inference stack is intended for enterprise customers running the platform inside their own infrastructure. It is not the right path for most users — the managed Vulavula API is faster to integrate, fully maintained, and requires no cluster or GPU operations on your side.
Please reach out first!
Before you attempt a self-deploy, contact us at [email protected] so we can assist with sizing, licensing, access to the private GHCR registry, and ongoing support. Deploying without that conversation is unsupported and will run into private-image auth, chart-version pinning, and feature-gate prerequisites you'll otherwise discover the hard way.
What this is
The your-cloud Helm chart deploys the full Lelapa inference stack — the
same one powering the managed Vulavula API — into
your own Kubernetes cluster. You bring the cluster and GPU capacity; the
chart ships everything else needed to run speech-to-text and translation
workloads.
It front-loads a small FastAPI service that accepts your requests and routes them to two GPU-backed predictor pools behind an internal load-balancer. The two pools cover the two distinct workloads the API supports: low-latency streaming and higher-throughput batch processing. Models travel as OCI images pulled with the same credentials as the app images — no separate S3 or model-registry plumbing on your side.
This chart does not expose anything outside the cluster or attach
authentication — bring your own Ingress / Gateway / LoadBalancer and auth
layer in front. See the chart's own README.md, RUNBOOK.md, and
DESIGN.md (shipped inside the chart tarball at charts/your-cloud/)
for the full, maintained reference. The steps below are a quickstart;
reach out to us first (see the callout above) to get access.
Prerequisites
Before you start, confirm with us which your-cloud chart version and
which their-cloud-mvp image release tag you should pin — both are
private (GHCR internal visibility) and version advice is per-customer.
- Kubernetes
ImageVolumefeature gate (alpha since 1.31, off by default) — the predictor pods mount model weights straight out of an OCI image; there's no fallback path. Confirm the gate is actually on with whoever manages the cluster. - At least one GPU in the cluster for inference. Set
inferenceServer.{live,sync}.nodePool.{selector,tolerations}in your values file to match your actual GPU node's labels/taints. - A
lelapa-ghcrimage pull secret in the target namespace — the app, runtime, and model weights images are all private (GHCRinternal). Create it with a GitHub PAT that hasread:packagesscope (Step 6 below); the chart never provisions it itself. - Your own Ingress / Gateway + auth in front of the chart's internal
:9000service — the chart does not expose anything outside the cluster, terminate TLS, or attach authentication. Its only built-in auth is a Basic Auth pair on the service itself, not a substitute for real edge auth.
cert-manager and KServe
cert-manager and KServe are also required, but they're installed as
part of the steps below — skip those steps if your cluster already has
them.
Install
-
Get a chart version and image tag from us
Email [email protected] for the
your-cloudchart version (X.Y.Z) and thetheir-cloud-mvpimage release tag (YY.MM.<counter>, e.g.26.7.2) you should pin. Both artifacts live under private GHCR packages. -
Install cert-manager (skip if your cluster already has it)
Code -
Install KServe (CRDs + controller) (skip if already installed)
Two separate
helm installcalls — the CRD chart must land and become discoverable before the controller chart runs:Code -
Log in to the Lelapa Helm OCI registry
Code -
Configure your
my-values.yamlMinimum every install needs to touch:
CodeTo see the full set of available keys (or check what any of the above defaults to), render the default values straight from the published chart:
Code -
Create the
lelapa-ghcrimage pull secretCode -
Install
your-cloudDry-run against the real cluster first — this catches CRD/webhook mismatches that
helm templatealone won't, since it actually talks to the API server:CodeOnce that looks right, drop
--dry-run=server:CodeMatch
--namespaceto whatevernamespace:you set inmy-values.yaml— Helm tracks the release itself in whatever--namespaceyou pass here, independently of.Values.namespacegoverning where the chart's resources land. A mismatch doesn't break the install, but it does meanhelm list/helm uninstallwon't find the release where you expect it.The chart's preflight check (on by default; set
--set preflight.enabled=falseto bypass) fails the install immediately with a clear message if the KServe CRD isn't registered or — on upgrade — if the predictor Services aren't actually headless. -
Verify
CodeCheck both predictor pools are ready (KServe sets
.status.conditions):Code
External exposure and auth are your responsibility
This chart does not create an Ingress / Gateway / LoadBalancer or
attach authentication in front of adapters (:9000, ClusterIP).
Front it with your own, and terminate TLS there — the chart-rendered
adapters-secrets Basic Auth pair travels in the clear otherwise.
Update
Code
Same command for first install and every subsequent upgrade — helm upgrade --install is idempotent. Bump only the chart --version to move
chart templates / schema / defaults; bump only image.tag in your values
file to move what code / model weights run. Tell us when you intend to do
either so we can confirm version compatibility.
Rollback
Code
Rollback reverts the chart's rendered manifests to a previous release, not
any data — the metering-db PVC (if enabled) isn't touched either way.
Uninstall
Code
The metering-db-pvc PVC is not deleted automatically by Helm — remove
it manually if you actually want the data gone:
Code
Troubleshooting
- Predictor pod stuck
Pending, no obvious reason — almost always theImageVolumefeature gate, or a GPU node selector/toleration mismatch. Re-check your actual node labels againstinferenceServer.{live,sync}.nodePool.{selector,tolerations}. - Predictor pod stuck
Init:0/1— themodels-image-trackerinitContainer is a trivialcommand: ["true"]that exists only so ArgoCD's image scanner sees the models image; if it's stuck, the actual model image pull is stuck. Checkimage.models.tagexists andimage.pullSecretcan read it. - Predictor pod
Runningbut not serving — check thepod-liveness-guardsidecar logs first. It force-deletes the pod after 3 consecutive/v2/health/livefailures; if it's cycling, the underlying Triton process is what to debug, not Kubernetes scheduling. adapters-secretsmissing / pods stuckCreateContainerConfigError— withsecrets.mode: existingSecret, the chart never creates this Secret; confirm whatever provisions it (ExternalSecret, SealedSecret, etc.) has actually run. Withmode: directValuesandCLIENT_USERNAME/CLIENT_PASSWORDleft unset, the chart generates random ones on first install — retrieve them with:CodeLEAST_REQUESTLB doesn't seem to be doing anything (all traffic hits one pod) — almost always means the predictor Service isn't headless. Confirmkubectl get svc <name>-predictor -n <namespace> -o jsonpath='{.spec.clusterIP}'returnsNone; otherwisekserve.service.serviceClusterIPNonewasn't set on the KServe installation (see Step 3).- HPA not scaling
sync— expected.inferenceServer.sync. autoscaling.maxReplicasis pinned to1by design.
Need help?
Self-deploying is something we want to support you through, not something to figure out alone. Reach out at [email protected] or join our Discord community and we'll pair you with someone who knows the chart.

