Kubernetes
Pika ships with a Kustomize bundle in ci/kubernetes/. It includes:
- A
Namespace(pika). - A
ServiceAccount. - A
ConfigMapwithpika.yaml. - A
Secretcarrying the cluster pre-shared key. - A
StatefulSetwith 3 replicas and per-pod PVCs (volumeClaimTemplates). - A
ClusterIPServicefor internal admin HTTP traffic (8080) and optional Endpoint traffic (9090). - A headless
Servicefor cluster peer discovery on QUIC (5000/UDP).
Ingress / Gateway is intentionally not included — bring your own (Ingress, Gateway API HTTPRoute, etc.) and point it at the pika Service on port 8080. The Kubernetes bundle disables Pika's in-pod HTTPS so the Gateway can terminate and renew public TLS certificates.
TIP
The standalone Pika binary still defaults to HTTPS. The Kubernetes manifests set server.tls.enabled: false specifically for the common Gateway / cert-manager model where the in-cluster upstream is HTTP.
Quick deploy
Apply directly from the repository:
kubectl apply -k https://github.com/rakunlabs/pika/ci/kubernetesPin to a specific version:
kubectl apply -k "https://github.com/rakunlabs/pika/ci/kubernetes?ref=v0.1.0"WARNING
Before deploying, change the placeholder security_key in secret.yaml to a real random value (e.g. openssl rand -base64 48). All replicas must share the same key.
Customising with a remote base
Create your own kustomization.yaml that references the upstream manifests and overrides what you need:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/rakunlabs/pika/ci/kubernetes?ref=main
images:
- name: ghcr.io/rakunlabs/pika
newTag: v0.3.0
patches:
- target:
kind: ConfigMap
name: pika
patch: |
- op: replace
path: /data/pika.yaml
value: |
server:
port: "8080"
tls:
enabled: false
storage:
bw:
path: /data/pika
cluster:
enabled: true
dns_addr: pika-cluster.pika.svc.cluster.local
replicas: 3
port: 5000
- target:
kind: Secret
name: pika-cluster
patch: |
- op: replace
path: /stringData/security_key
value: "your-long-random-string-here"Then apply:
kubectl apply -k .Replicas and quorum
The default deploys a 3-replica cluster (see Clustering). If you change spec.replicas on the StatefulSet, also update cluster.replicas in the ConfigMap — both must match for the quorum math.
Endpoints
Endpoints are operator-defined listeners configured at runtime (Settings → Endpoints) — each binds its own port and can serve HTTP or HTTPS using the managed certificate. To expose one in Kubernetes:
- Pick a deterministic port per endpoint (e.g.
9090for Consul mode). - Add the port to the StatefulSet
containerPortlist and to thepikaService. - Add an Ingress / HTTPRoute if you want external access.
The endpoint configuration itself is stored in pika (not Kubernetes), so a single ConfigMap change is not enough — you also need to add the entry from the UI on a running pod.
Gateway TLS
The default Kubernetes shape is:
client --HTTPS--> Gateway / Ingress --HTTP--> pika Service:8080Use cert-manager, your cloud Gateway integration, or your GatewayClass-specific certificate mechanism to populate the Gateway listener certificate. Pika does not need to manage the public certificate in this mode.
If you want the Gateway to re-encrypt to Pika instead, override the ConfigMap with server.tls.enabled: true and configure backend TLS trust in your Gateway implementation (for Gateway API this is commonly done with BackendTLSPolicy, when supported).
Runtime database settings under settings.server_tls only apply when process-level server.tls.enabled is true. Because this bundle sets server.tls.enabled: false, the pod serves HTTP immediately on first install and does not wait for a DB setting.
When server.tls.enabled: false, the Pika UI hides Settings → Certificates because the managed HTTPS listener and runtime TLS policy are disabled by process config. Certificate lifecycle should be managed on the Gateway / cert-manager side instead.
Sub-path routing
If your Gateway / Ingress serves Pika under a sub-path and forwards that prefix to the Service, set server.base_path in the ConfigMap:
server:
port: "8080"
base_path: /pika
tls:
enabled: falseUse this for a public URL like https://example.com/pika/ when the backend still receives /pika/... paths. If the Gateway strips /pika before proxying to Pika, leave server.base_path unset. The Kubernetes /healthz probes continue to work at the root path even when server.base_path is set.
Encryption key
Pika no longer reads its at-rest master key from environment or config — see Encryption. On every pod restart an administrator must unlock the server through POST /api/v1/key/unlock or the web UI before any non-allowlisted request will succeed.
Operationally this means:
- Rolling updates require an unlock per pod. Plan maintenance windows accordingly, or scale to zero and back so only one unlock per upgrade is needed if your business model tolerates the downtime.
- OOM / liveness restarts also require manual unlock — keep the runbook accessible to the on-call rotation.
- Headless auto-unseal (Vault transit, KMS) is not currently supported. If you need it, file an issue describing your threat model.
A readinessProbe against /api/v1/key/status can keep traffic off locked pods until they are unlocked:
- target:
kind: StatefulSet
name: pika
patch: |
- op: add
path: /spec/template/spec/containers/0/readinessProbe
value:
httpGet:
path: /api/v1/key/status
port: 8080
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 10Combine with a JSON-aware probe (e.g. an ExecAction running curl
jq '.unlocked == true') if you need the readiness gate to wait for the unlock too rather than just for the endpoint to answer.
External Secrets Operator
If you use External Secrets Operator, ci/kubernetes/examples/ contains examples for pulling pika-stored configs and TLS material into Kubernetes Secrets via a SecretStore / ExternalSecret pair. This lets you keep the source of truth in pika while still feeding existing workloads that consume native Secrets.
Observability
Pika emits metrics, traces, and logs through tell (OpenTelemetry under the hood). Configure exporters under the telemetry: key in the ConfigMap, or via PIKA_TELEMETRY_* environment variables.
Probes
The admin /healthz (port 8080) returns 200 OK once the storage is open. The default bundle probes over HTTP because public TLS terminates at Gateway / Ingress:
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
periodSeconds: 5