Helm chart
One chart, in deploy/helm/obzly,
deploys every role. It renders the same pods as the
plain Kubernetes manifests, with values instead of edited YAML.
mode |
What runs |
|---|---|
ha (default) |
broker StatefulSet (NATS JetStream ingest buffer), api (UI, REST, OTLP, query coordination), worker (Parquet writes, compaction, retention, alert evaluation), querier (query executors) |
single |
One SERVICE_MODE=all pod on a PersistentVolumeClaim |
control-plane |
The multi-site control plane |
Postgres and object storage are always yours: RDS/Aurora or any Postgres, and S3 or any
S3-compatible store. Valkey runs in the release unless you set valkey.enabled: false and point
the chart at your own. For cluster versions, node sizes, sizing by ingest volume and which tiers
can run on Spot nodes, see System requirements.
Install
Section titled “Install”kubectl create namespace obzlyhelm install obzly deploy/helm/obzly -n obzly \ --set config.objectStorageUrl='s3://harborline-obzly?region=eu-west-1' \ --set secrets.databaseDsn='host=... user=obzly password=... dbname=obzly port=5432 sslmode=require' \ --set serviceAccount.annotations.eks\.amazonaws\.com/role-arn=arn:aws:iam::111122223333:role/obzly-s3 \ --set broker.nodeSelector.karpenter\.sh/capacity-type=on-demandThe chart’s notes print how to reach the UI and the OTLP endpoints:
- UI and API:
kubectl -n obzly port-forward svc/<release> 4005:4005, then openhttp://localhost:4005, or enableingress.enabled. - OTLP: gRPC on port
4317of the service, HTTP at:4005/v1/logs,/v1/traces,/v1/metrics.
The first start creates the bootstrap admin (config.adminEmail, admin by default) and logs a
one-time bootstrap token for setting its password:
kubectl -n obzly logs -l app.kubernetes.io/instance=obzly --tail=-1 | grep bootstrapTokenThe token is logged only once. If that pod is gone, print a new one (this works only while the admin has no password yet):
# ha modekubectl -n obzly exec deploy/obzly-api -- /app/main --reset-bootstrap-token# single or control-plane modekubectl -n obzly exec deploy/obzly -- /app/main --reset-bootstrap-tokenS3 permissions
Section titled “S3 permissions”On AWS, the service account’s IAM role (IRSA, set through serviceAccount.annotations) needs
s3:PutObject, s3:PutObjectTagging, s3:GetObject, s3:ListBucket and s3:DeleteObject on
the bucket.
Bring your own Secret
Section titled “Bring your own Secret”To manage the Secret yourself (External Secrets, Sealed Secrets, …), create it with the keys
DATABASE_DSN, NATS_TOKEN and QUERIER_TOKEN (ha mode), and optionally VALKEY_PASSWORD and
the GITHUB_* / GOOGLE_* OAuth settings, then set secrets.existingSecret. Otherwise the chart
creates <release>-secrets; NATS and querier tokens left empty are generated on install and kept
on upgrade.
Production settings
Section titled “Production settings”broker.nodeSelector/tolerations: on-demand nodes only. Brokers hold acknowledged batches until a worker writes them. Sizebroker.storage.sizefor about an hour of ingest and keep three timesbroker.streamMaxBytesinside it.broker.replicas:3(streams replicated three ways, one pod per zone) or1(no failover).2is refused.config.trustedProxies: your load balancer’s CIDRs, so client IPs are real.api.autoscalingandquerier.autoscaling: HPA on CPU. The HPA target is a share of the CPU request, which is 500m forapiby default since chart 0.2.0 (api.resources; at 250m it flapped between replica counts and each scale-down cut off running queries).querier.networkPolicy: limits the executors’ result port toapipods; needs a CNI that enforces NetworkPolicy.metrics.serviceMonitor: a Prometheus Operator PodMonitor for every tier. See Monitoring Obzly.config.publicUrl: the address users reach Obzly at, for MCP clients’ OAuth.
Volumes and file ownership
Section titled “Volumes and file ownership”Since chart 0.2.0, pods run with podSecurityContext.fsGroup: 1000 (and
fsGroupChangePolicy: OnRootMismatch) by default, so new volumes, such as the brokers’ JetStream store and the querier cache, are writable
by the image’s user without overrides. A fresh EBS volume is otherwise owned by root.
Other settings
Section titled “Other settings”Any setting from the configuration reference goes in
config.extra, or secrets.extra for credentials. For example:
config: extra: ALERT_EGRESS_DENYLIST: 172.20.0.0/16Email (SMTP) and notification channels are not set here: set them up in Obzly settings (see Alerts & notifications).
Use config.extra for QUERY_MAX_SCAN_GB, or for SITE_ID and CONTROL_PLANE_ISSUER to enroll
the release as a Site in a control plane.
A control plane serves SCIM at /scim/v2. If you provision users that way, keep it reachable
through the Ingress; see SSO and SCIM.
Upgrade
Section titled “Upgrade”helm upgrade obzly deploy/helm/obzly -n obzly -f values.yaml --set image.tag=vX.Y.ZThe chart rolls brokers one pod at a time and keeps generated tokens. See Upgrade for the order across Sites and the control plane.
Restore
Section titled “Restore”After a Postgres restore, reconcile the catalog with the bucket (see Backup & restore):
kubectl -n obzly exec deploy/obzly-worker -- ./main reconcileSynthetics probe chart
Section titled “Synthetics probe chart”The Synthetics probe has its own chart,
deploy/helm/obzly-probe. It
runs a probe group (three replicas sharing one token by default, spread across nodes and zones,
with a PodDisruptionBudget) and creates a service account for IRSA or Azure workload identity when
the group scans cloud connections. See
Synthetics probe.
Architectures
Section titled “Architectures”Releases from v0.47.0 are published for linux/arm64 and linux/amd64, so the chart pins no
architecture. Earlier releases are arm64 only: on amd64 nodes use v0.47.0 or later (the chart’s
default), or add nodeSelector: {kubernetes.io/arch: arm64} for an older tag.
Not included
Section titled “Not included”The chart doesn’t run a migration Job (the app migrates at startup, under a lock), in-cluster Postgres, or a Valkey operator.