Kubernetes Deployment
The Helm chart configures a three-replica BoilStream cluster. Object storage holds published files and completed metadata backups. Hydrated historical files are caches; unpublished hot rows have a separate durability boundary. A persistent volume does not replace the configured recovery path. For write and recovery limits, see Reliability and completion.
Use the chart and example values supplied with your server release.
OCI artifact: oci://ghcr.io/boilingdata/charts/boilstream
Prerequisites
- Kubernetes 1.27 or newer.
- cert-manager 1.13 or newer, or equivalent pre-created public and private TLS Secrets.
- Envoy Gateway 1.2 or newer with the configured
GatewayClass. - An S3-compatible bucket and workload identity or a Secret containing
access_keyandsecret_key. - A superadmin password Secret.
- A stable key Secret containing two distinct values:
encryption_key: 32 random bytes encoded as 64 hexadecimal characters;token_signing_key: 32 random bytes encoded as base64.cluster_token: an independent random token of at least 32 characters.
Keep both keys in an external secret manager and restore them unchanged. The encryption key protects recovery state. Changing the signing key invalidates outstanding HTTP ingestion, auth, and PGWire bootstrap tokens.
kubectl -n boilstream create secret generic boilstream-encryption \
--from-literal=encryption_key="$(openssl rand -hex 32)" \
--from-literal=token_signing_key="$(openssl rand -base64 32)" \
--from-literal=cluster_token="$(openssl rand -base64 32)"Production values
Start from the EKS or Hetzner example shipped with the chart. The following fields define the required topology; replace every example identity and endpoint:
replicas: 3
domain: data.example.com
image:
repository: registry.example.com/boilstream
tag: <release-version>
# Replace this non-resolving example with the published release digest.
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
pullPolicy: IfNotPresent
configRenderer:
image:
# Replace with the published Python multi-architecture manifest digest.
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
s3:
endpoint: https://s3.example.com # empty for AWS S3
bucket: company-boilstream-prod
region: eu-central-1
prefix: prod/
forcePathStyle: true
existingCredsSecret: boilstream-s3-creds
accessKey: ""
secretKey: ""
encryptionKey:
existingSecret: boilstream-encryption
secretKey: encryption_key
tokenSigningKey:
secretKey: token_signing_key # same Secret by default
cpMetadata:
enabled: true
ducklakeMultiRaft: true
usersMultiRaft: true
tokenSecretKey: cluster_token # same Secret by default
s3Dr:
enabled: true
clusterId: company-prod-eu-1
backend: primary-s3
prefix: quack-dr
durabilityMode: strict
bootstrapMode: new
recoveryEpoch: 1
recoveryId: company-prod-eu-1-first-install
clusterTls:
enabled: true
issuer:
name: boilstream-ca-issuer
kind: ClusterIssuer
httpIngestion:
enabled: true
port: 8446
allowedOrigins:
- https://data.example.com
persistence:
enabled: false
gateway:
enabled: true
className: egThe chart rejects partial clustered configurations. clusterId is the durable identity of one logical cluster and must never be reused for another. bootstrapMode: new with epoch 1 is only for the first installation. Once the first recovery generation exists, change the mode to restore. When image.digest is set, the chart renders repository@sha256:…; image.tag is ignored and remains only a readable release label. The config-renderer init image follows the same rule and must also be digest-pinned.
Install
helm install boilstream oci://ghcr.io/boilingdata/charts/boilstream \
--version '<chart-version>' \
--namespace boilstream --create-namespace \
--values my-values.yaml \
--set-string image.digest='sha256:<release-image-digest>' \
--set-string configRenderer.image.digest='sha256:<python-image-digest>'Before installing or upgrading, validate the exact values:
helm lint oci://ghcr.io/boilingdata/charts/boilstream \
--version '<chart-version>' \
--values my-values.yamlPublic endpoints
| Interface | Endpoint | Purpose |
|---|---|---|
| Web and auth | https://data.example.com/ | Sign-in, administration, and credential vending |
| HTTP/2 Arrow | https://data.example.com:8446/ingest/<token> | Browser and service ingestion with a scoped token |
| Kafka | data.example.com:9092 | Kafka-compatible produce and consume |
| FlightRPC | data.example.com:50051 | Arrow Flight ingestion |
| FlightSQL | data.example.com:50250 | Arrow Flight SQL queries |
| PGWire | per-pod ports beginning at 15432 | PostgreSQL clients using vended credentials |
| Managed DuckDB | vended by the BoilStream extension | Native DuckDB catalog queries over server TLS and a short-lived capability |
Use vended connection metadata instead of assembling PGWire or managed DuckDB endpoints. The public extension authenticates to BoilStream and handles the managed DuckDB endpoint, TLS verification, catalog identity, and capability refresh. External clients do not receive a reusable client certificate or private key.
Upgrades and failures
Upgrade one replica at a time and wait for readiness before continuing:
helm upgrade boilstream oci://ghcr.io/boilingdata/charts/boilstream \
--version '<chart-version>' \
--namespace boilstream \
--values my-values.yaml \
--set-string image.digest='sha256:<release-image-digest>' \
--set-string configRenderer.image.digest='sha256:<python-image-digest>'
kubectl -n boilstream rollout status statefulset/boilstreamThe default disruption budget keeps two of three replicas available during voluntary maintenance. Spread replicas across nodes or failure domains when the platform permits.
A client connected to a failed pod must reconnect; existing TCP sessions are not promised to migrate. With quorum, metadata operations continue through healthy replicas. Without quorum, metadata-dependent admission fails closed. A replacement pod catches up from peers without a PVC.
For complete local-state loss, fence the old incarnation, increment the recovery epoch once, set a new recovery ID on every replica, and restore with the original cluster ID, S3 prefix, and encryption key. The recovery point is the latest completed generation.
Verify
kubectl -n boilstream rollout status statefulset/boilstream
kubectl -n boilstream get pods,gateway,certificate
boilstream-admin cluster statusBefore admitting production traffic, exercise authentication, catalog vending, every enabled ingestion/query interface, a leader failover, a rolling restart, and an S3-only restore in a staging cluster built from the same release artifacts.