Repository navigation
feat: TCP, Kubernetes (DOKS and kind) and capacity callees in one run - #26
Conversation
…h benchmark's target on the page
|
Review: Changes needed (round 1 of 2) Committee: QA engineer, software architect, release engineer, security engineer. Left out: performance engineer, realtime-comms engineer ( Blocking:
|
|
Review: Ready for human review (round 2 of 2) Committee: the chair re-checked round 1's two blocking findings and the new commits (96b65b7, 5ef5e61, 209a933) against the code. Round 1's committee: QA engineer, software architect, release engineer, security engineer. Round 1's findings:
Also checked:
Blocking: none. |
Closes #24
Closes #25
perfkit now runs a project's benchmarks over TCP, on one server and on Kubernetes, in one run, and capacity benchmarks can register callees (#24, folded into #25).
What changed
perfkit.yaml v1 (additive; every existing config validates unchanged)
load.transport: udp | tcp(defaultudp). TCP: every SIPp role runs-t tnwith-max_socket= its-l+ 100 (at most 60000) and--ulimit nofile=65536:65536.infra.cluster: { size, nodes, version = "latest" }, required when a benchmark hasuut.helm.uutis either the existing{ compose, setup?, processes }or{ helm: { chart, values, entry: { service, port }, setup?, pods: [{ name, selector }] } }.load.register/load.uason capacity benchmarks too (A capacity benchmark can't register callee agents or ramp calls to them #24): register role-l rows + ceil(max × (hold + 20)), uas-only-l ceil(max × (hold + 20)); every capacity uac gets-recv_timeout 10000and-l ceil(max × (hold + 20)); the uac starts only after every callee registered (soak's timeout and abort reason); a step is invalid when any SIPp role (sipp-register,sipp-uastoo) is over 80% of one core; raw capacitymeta.jsongainsregisterUsers.rateis{ cps }or{ fromCapacity, fraction, fallbackCps }.Runs
perfkit-<run id lowercase>in the run's VPC, taggedperfkit+perfkit-run-<id>, created with the droplets and waited for in parallel (20 min). The firewall opens all tcp/udp from its node droplets; the kubeconfig (valid formaxLifetime) goes to/opt/perfkit/keys/kubeconfig(600) on the load generator only.destroy_with_associated_resources/dangerousin parallel with the droplets (VPC wait 10 min after a cluster).perfkit sweepfinds clusters taggedperfkitnamedperfkit-<run id>;collect's teardown (sweep by run id) covers them.--local: kindperfkit-<run id>withinfra.cluster.nodesnodes, MetalLB v0.14.9 L2, images the charts use (helm template) orimages:names that exist locally loaded withkind load docker-image; deleted by the local teardown.PERFKIT_ENTRY_IP=0.0.0.0), wait for the entry Service's LB address,helm upgrade --waitwith it resolved, every pod Ready, setup, then SIPp to<lb ip>:<entry.port>;helm uninstall+ namespace delete at the end. Cluster health check is/readyz.kube-uut.jsonl, converted to the usual sampler lines (summed CPU integrated into ticks, working-set memory, pid bumps on container restarts).report.json v1 (optional fields):
run.infra.cluster,benchmarks[].target, soakload.rateSource. The page puts the target in each section's eyebrow (01 · CAPACITY · Single server,02 · SOAK · Kubernetes, 3 × c-8); old reports render with no label.Decisions
-cid_str, which now carries the run id on every role, soak and capacity alike (<role>-<run id>-%u-%p@%s, requested mid-task so Call-IDs never repeat across runs). Capacity uac args differ further only by A capacity benchmark can't register callee agents or ramp calls to them #24's-recv_timeout 10000and the new-l.k8s-Call-ID prefix, so the samplers of a server soak and a cluster soak on one load generator tell them apart.alpine/k8s:1.33.4(digest-pinned) on the load generator, not on the CLI machine, so the workflow needs no new tools. The helmsetupscript runs in that samealpine/k8scontainer on the load generator (not on the machine that runsperfkit run, whatever Routr'sperf/k8s/seed.shheader says), asbash <setup> <namespace> <register users> <uac users>with KUBECONFIG andPERFKIT_*set.perfkit, namespace = benchmark id.entry.servicematches the Service name with or withoutperfkit-in front (Routr'sroutr-edgeport-tcpfindsperfkit-routr-edgeport-tcp)..200-.250of the kind network's second-to-last /24 (172.18.254.200-250on 172.18.0.0/16), SIPp gets fixed.251-.253there, to stay clear of another cluster's MetalLB in the last /24.--kubelet-insecure-tlson both DOKS and kind (ephemeral clusters; it also works with valid kubelet certs).--force-conflictsis added only whenhelm versionreports v4 (the pinned image ships Helm 3.18).rateSource.lowerBound: true, and the progress line says "the lower-bound limit ... at least N calls/s").fallbackCpswhen it failed, was aborted, was inconclusive with no passing step, did not run, orfloor(fraction × limit) < 1.rateSource.limitis null when there was no limit.Promise.allSettled; a failing cluster soak doesn't cut the server soak short (it keeps its own results), then the run fails with the first failure.sweep, collect's teardown and run.yaml'ssweep --runkeep working with a token scoped for droplets only.net.ipv4.ip_local_port_range = 1024 65535andnet.ipv4.tcp_tw_reuse = 1, so-t tnto one LB address doesn't run out of ephemeral ports (~470 calls/s with the defaults and 60 s TIME_WAIT).PERFKIT_ENTRY_IP,PERFKIT_TARGET_VERSION,PERFKIT_IMAGE_<NAME>; any other${PERFKIT_…}fails the benchmark naming the placeholder.charts/(nohelm dependency buildat run time);perfkit validatechecks<chart>/Chart.yaml.benchmarks[].targetis written for every benchmark, server ones included, so the page always labels; the measurements of existing benchmarks don't change.benchmarks[0].uut.helm.pods: required) instead of "does not match any allowed shape" (ties keep the old message).Verify
npm test(735 passing),npm run typecheck,npm run lint,npm run schemaswith no diff.perfkit validateon Routr'sperf/perfkit.yaml,perf/perfkit.local.yaml,perfkit.smoke.yaml,perfkit.calibration.yaml(routr-v3 working copy): valid.--run,--dry-run.perfkit run --local --benchmarks k8s-simpleof Routr's local config on this Mac: kind (2 nodes) + MetalLB came up, 9 local images loaded, entry at172.18.254.200:5060, 200 callees registered over TCP, one step measured, report written withinfra.clusterand the pods' resources, kind cluster and containers deleted. No DigitalOcean resource was created.Not done / follow-ups
k8s-simple. Its result was failed: 61.8% of calls at 20 calls/s got503 Service unavailableon the BYE (then 481), andperfkit-routr-edgeport-0grew to ~2.8 GB working set within a minute. That looks like Routr's multi-EdgePort TCP behavior (2 replicas behind the LB), not perfkit, but needs a look.transport: tcp,uut.helm,infra.cluster,rate.fromCapacity, capacityregister/uas; capacity uacs get-recv_timeout 10000and-l max × (hold + 20); every SIPp-cid_strcarries the run id; report.json gains optionalrun.infra.cluster,benchmarks[].target, soakload.rateSource(withlowerBound); droplets get the full ephemeral port range and TIME_WAIT reuse; the DigitalOcean token needs the Kubernetes scopes foruut.helm; no new workflow inputs.