tidaldb/tidal-stress/k8s/stress-job-t5.yaml
jx12n 31ee612f27 feat(m12p4): sharded ingestion — scatter-gather pool + cross-shard unified reads (L4)
Scale write throughput across data-shard groups while keeping a single unified
read surface:

- scatter_gather.rs: pooled fan-out across shard groups (replaces per-request
  client construction); cross-shard query results merged on one node
- cluster/node.rs: cross-shard read routing — a read on any node gathers from
  every shard group's leader and unions results
- cluster/forward.rs: fix h2 204 forward-relay bug (relay_forwarded skips body
  for 1xx/204/304 — synthesized JSON body on a 204 triggered HTTP/2 RST_STREAM
  on the real mTLS plane)
- dto.rs: cross-shard query/result DTOs
- k8s/cluster/: enable 3-group `shards:` topology (statefulset, service-peers,
  topology-configmap)
- k8s/cluster-local-kind/: local-kind overlay to run the T5 gate without Ref-A
- tidal-stress/k8s/stress-job-t5.yaml: 2-generator sharded throughput job
- tests: cluster_cross_shard_reads.rs + multiproc support; ran real on kind
- docs/profiling/m12p4-t5-sharded-throughput.md: T5 throughput findings
2026-06-14 15:17:35 -06:00

146 lines
5.7 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# T5 — sharded quorum-write throughput at scale (m12p4 / G3).
#
# Goal: prove the 3-group × RF=3 topology scales WRITES ~S× over a single group.
# With `shards:` enabled (k8s/cluster/topology-configmap.yaml) the regular
# `/signals`//`/items`//`/embeddings` surface hash-routes each entity's write to
# its OWNING group's leader, so the three balanced leaders (tidaldb-0/1/2 lead
# shards 0/1/2) absorb writes in parallel instead of one leader funnelling all.
#
# TWO generators. The m11p6 knee was the GENERATOR's in-flight cap (~4k rps),
# not the engine (~30% CPU at 3k/s). A single generator cannot saturate three
# parallel leaders, so this Job runs `parallelism: 2` (completionMode: Indexed):
# two generator pods drive the ramp concurrently and their throughput sums.
# Both spread writes across all three `--target`s (no `--leader-url` pin), so
# every pod gateways AND leads one group — no single forwarding bottleneck.
#
# Aggregate the two pods' `ok_per_sec` (each logs its own JSON summary) for the
# cluster total. Gate: aggregate ≥ 5,000 quorum signal writes/s AND ≥ 2.5× the
# single-group baseline (stress-job-m11p6-baseline.yaml), zero acked loss per
# group, 0% error. The single-generator absolute on constrained hardware may sit
# below 5k; the SCALING RATIO (3-group vs single-group) is the architecture
# proof and is hardware-independent.
#
# TLS: the :9500 plane serves a private-CA cert (tidaldb-cluster-tls). Each
# generator trusts it via the mounted ca.crt (--ca-cert) — verified TLS, never
# --insecure. Targets are the pod-DNS SANs (https://), never pod IPs.
#
# Apply: kubectl apply -f tidal-stress/k8s/stress-job-t5.yaml
# Watch: kubectl logs -f job/tidal-stress-t5 -n tidaldb-cluster --all-containers --prefix
# Sum: grep '"ok_per_sec"' across both pods' --json-summary outputs
# Rearm: kubectl delete job tidal-stress-t5 -n tidaldb-cluster
apiVersion: batch/v1
kind: Job
metadata:
name: tidal-stress-t5
namespace: tidaldb-cluster
labels:
app.kubernetes.io/name: tidal-stress
app.kubernetes.io/part-of: tidaldb
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 7200
# Two generator pods, both running to completion — the "second stress
# generator" m12p4 calls for. Indexed so each pod has a stable
# JOB_COMPLETION_INDEX (0/1) in its logs for per-generator attribution.
completions: 2
parallelism: 2
completionMode: Indexed
template:
metadata:
labels:
app.kubernetes.io/name: tidal-stress
app.kubernetes.io/part-of: tidaldb
spec:
restartPolicy: Never
automountServiceAccountToken: false
# Spread the two generators onto distinct nodes so neither generator pod
# competes with the other for CPU — each must be free to drive its full
# in-flight budget (the m11p6 knee was generator CPU/in-flight, not engine).
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: tidal-stress
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: stress
image: registry.threesix.ai/tidal/stress@sha256:e130aa871f5df17a14a9e13e7df606c602b95a03d8eba49490ff7481e6e2b2b3 # m11-44b768b (TLS-aware)
imagePullPolicy: IfNotPresent
args:
# Spread writes across all three pods (each gateways + leads one
# group); NO --leader-url pin, so the forwarding load is balanced.
- --target
- https://tidaldb-0.tidaldb-peers.tidaldb-cluster.svc.cluster.local:9500
- --target
- https://tidaldb-1.tidaldb-peers.tidaldb-cluster.svc.cluster.local:9500
- --target
- https://tidaldb-2.tidaldb-peers.tidaldb-cluster.svc.cluster.local:9500
- --ca-cert
- /etc/tidaldb/tls/ca.crt
- --ack
- quorum
- --ramp
- peach-100k
- --stage-secs
- "120"
- --mix
- writes
- --corpus
- "20000"
- --users
- "100000"
# Each generator drives its own in-flight budget; two pods double the
# aggregate offered load over a single generator.
- --max-inflight
- "5000"
- --poll-status
# m11p9 machine-readable gates: a per-generator JSON summary plus
# hard ceilings. 0% error + no knee are the per-group zero-acked-loss
# / SLO bar; aggregate the two pods' ok_per_sec for the 5k/2.5x gate.
- --json-summary
- /tmp/t5-summary.json
- --max-error-pct
- "0"
env:
- name: TIDAL_API_KEY
valueFrom:
secretKeyRef:
name: tidaldb-credentials
key: TIDAL_API_KEY
- name: TIDAL_STRESS_LOG
value: warn
resources:
requests:
cpu: 500m
memory: 256Mi
limits:
cpu: "3"
memory: 1Gi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: cluster-tls
mountPath: /etc/tidaldb/tls
readOnly: true
- name: tmp
mountPath: /tmp
volumes:
- name: cluster-tls
secret:
secretName: tidaldb-cluster-tls
items:
- key: ca.crt
path: ca.crt
- name: tmp
emptyDir: {}