Deploy on Kubernetes
Deploy the release-matched Helm chart with three replicas, trusted TLS, stable encryption and signing keys, and S3-compatible recovery storage. Pin image digests and validate the exact values before installation. Keep a healthy majority during updates, and verify authentication, data access and recovery before sending production traffic.
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
Section titled “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
Section titled “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: 3domain: 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
# Explicit operator acceptance: use only with a continuous-clock rate of 0.9–1.1.# The chart default stays untrusted and rejects clustered startup.quack: sharedSupport: profile: clock-profile-1
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
Section titled “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
Section titled “Public endpoints”| Interface | Endpoint | Purpose |
|---|---|---|
| Web and auth | https://data.example.com/ |
Sign-in, administration, and issuing credentials |
| 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 | supplied by the BoilStream extension | Native DuckDB catalog queries over server TLS and a short-lived capability |
Use returned 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
Section titled “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
Section titled “Verify”kubectl -n boilstream rollout status statefulset/boilstreamkubectl -n boilstream get pods,gateway,certificateboilstream-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.