Storage
Local disks of Berserk services — the query segment cache, working storage, encryption at rest and node scheduling
Berserk services use local disk for caching and working storage. S3 holds all segment data (Dependencies), so losing a local disk means a cold cache, not data loss.
Query Service
The query service keeps a local segment cache, so it does not fetch segments from S3 on every query. Use a local SSD or NVMe disk. The cache is mounted at /segment_cache.
The cache is partitioned across query nodes rather than replicated — each segment has one owning node that caches and scans it. Segment Placement covers how ownership is decided and what adding or removing a node does.
Size the cache for the days of data you want available for fast searches: ingest per day / compression x cache days, with compression around 10x depending on your data. One TB/day of ingest with a 7-day cache is about 700 GB. With multiple query nodes, each node holds its own share of that total. Hardware Sizing has the full model and a calculator.
Ephemeral node storage. The cache is lost when the pod is rescheduled.
query:
cache:
enabled: true
persistent: false
size: "128Gi"A local NVMe disk, through hostPath or emptyDir, gives the lowest query latency.
Other Services
The janitor, nursery and ingest services use local disk for working storage: merge scratch space and baby segments. Node storage is fast enough.
All three use emptyDir volumes, with no storage class or provisioning. The nursery's working directory also holds its node identity. The volume belongs to the pod, so a restarted container keeps its identity and cache. Replacing the pod (a deploy, an eviction, a node failure) loses the disk: the nursery mints a new identity, its stream groups fail over in about 30 seconds, and it rebuilds its baby-segment cache from object storage.
janitor:
cache:
size: "30Gi" # merge scratch: at least 6x the meta max_segment_size (5 GB default); a hard cap
nursery:
workingDir:
size: "50Gi" # baby segment buffer + node identity (emptyDir size limit)
# ingest uses a small emptyDir with no size limit by defaultWith a local-path storage class, a PVC pins the nursery pod to the node that holds the volume. If that node or volume is lost, the nursery mints a new identity on the empty disk and its stream groups fail over, with no manual step.
Encryption at rest
The local volumes above hold unencrypted copies of your telemetry: the query segment cache, the nursery's baby segments and the janitor's merge scratch. Berserk does not encrypt them; encrypt them below the filesystem:
- Cloud volumes: use your provider's volume encryption, through an encrypted
storageClassfor the query PVC and encrypted node disks foremptyDir. - Bare metal and
hostPath: put the cache directory and the kubelet's storage on a dm-crypt/LUKS device.
Berserk's sparse files and hole punching work on an encrypted filesystem as on any other.
Node Scheduling
nodeSelector, tolerations and affinity choose the nodes Berserk services run on. Each can be set globally or per service; a per-service value wins.
Global defaults
For every service:
global:
nodeSelector:
disktype: ssd
tolerations:
- key: "dedicated"
operator: "Equal"
value: "berserk"
effect: "NoSchedule"
affinity: {}Per-service overrides
For one service:
query:
nodeSelector:
kubernetes.io/hostname: my-dedicated-nodePinning to a specific node
By hostname:
query:
nodeSelector:
kubernetes.io/hostname: my-node-name
nursery:
nodeSelector:
kubernetes.io/hostname: my-node-nameIngest Endpoints
The ingest APIs and their listeners, the Ingresses that route to them, what Settings → Endpoints shows, anonymous ingest, acknowledgement and batching
Segment Placement
How Berserk decides which query node owns each segment — weighting by CPU, cache seeding, and what adding or removing a node does