Skip to content

benchmarking/nighthawk-egress: add the adaptive capacity runner with gateway counter checks - #3629

Closed
Yuan Gao (ygao-g) wants to merge 10 commits into
agent-substrate:mainfrom
ygao-g:nighthawk-egress-2-runner
Closed

Yuan Gao (ygao-g) wants to merge 10 commits into
agent-substrate:mainfrom
ygao-g:nighthawk-egress-2-runner

Conversation

@ygao-g

@ygao-g Yuan Gao (ygao-g) commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #3624 (Stage 1, item 3): the adaptive capacity runner for atenet-egress.

Stacks on #3628 and #3627, in that order; review the last four commits.

What changes

  • nighthawk_common: per-stage queue_to_connect and sequencer.blocking telemetry, optional actors, Path arguments, public helper names, and achieved-rps from the exact stage duration (Nighthawk truncates it to whole seconds).
  • nighthawk-egress/spec.py, output.py: the egress session spec for http, mitm and passthrough, the gateway counter parser and the capacity.json summary.
  • runner.py, cluster_setup.py, Dockerfile, run-dev.sh: one adaptive run end to end, scraping atenet-egress Prometheus counters before and after through a new headless atenet-egress-metrics Service. traffic-driver-invoker gets its own ServiceAccount.
  • egress-policy.yaml: exact server hostnames instead of *; the actor's ndots:5 makes atunnel see the .cluster.local name.
  • README: objective, dataplane modes, runner lifecycle, design decisions, GKE 1 and 2 vCPU results, output artifacts.

Review guide

  1. The nighthawk_common behavior commit, with the ingress test for the new fields.
  2. Spec and output modules with their tests.
  3. Runner, image, scripts, manifests, and their tests.
  4. README only.

Testing

hack/verify/benchmarking-python.sh green (egress 24, ingress 13). GKE runs on c3-standard-22 behind the README numbers.

AI use: AI-assisted (Claude Code) for the diff, the commit split and the test runs; I reviewed the diff.

  • Tests pass
  • Docs updated

@ygao-g

Yuan Gao (ygao-g) commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator Author

Reviewer notes (Stage 1 stack guide)

Stack position: Stacks on #3628 (5d125f17c), then carries #3627's three commits as 29b7c860d..87c500c6e (the same patches as its head 8c06a5bc3). Review the last four commits (04d9a3826..991cdf5db).

Commit-by-commit checks (991cdf5db):

  1. 04d9a3826 (nighthawk_common, nighthawk-ingress test): Adds queue_to_connect and sequencer.blocking fields, optional actors, and recomputes achieved-rps and send-rate from full nanosecond execution_duration because Nighthawk truncates duration to whole seconds (metrics_plugin_impl.cc:97-98 at the pinned commit). Preserves raw C++ values under *_cpp. Cross-cutting note: also affects nighthawk-ingress stage rows.
  2. 764640946 (spec.py, output.py, unit tests): Check per-mode UpstreamTlsContext (trusted_ca.filename on /run/ate/egress-trust-bundle/trust-bundle.pem for mitm, trusted_ca.inline_string for passthrough with ValueError when empty), EGRESS_FAILURE_PREDICATES, and the 10-counter Prometheus matcher label sets against the stat_prefix names in manifests/ate-install/atenet-egress.yaml.
  3. 30ad3d5fa (runner.py, cluster_setup.py, deploy.sh, run-dev.sh, Dockerfile, manifests, Go test): Check AF_INET scraping of headless atenet-egress-metrics, pod-IP mismatch and counter-reset errors raised after artifact upload, atomic .status.json.tmp replacement, backoffLimit: 0 + servicedns.podcert.ate.dev/identity ClusterTrustBundle mount in the Job template, and exact FQDNs in egress-policy.yaml + cmd/kubectl-ate/internal/cmd/egress_policy_test.go. Behavior change: the benchmark EgressPolicy no longer permits *. Updated 017dfd4f4 -> 30ad3d5fa: shape_atenet_egress now passes --concurrency N (Envoy rejects --concurrency=N) and always waits for the rollout; tests assert the patched args.
  4. 991cdf5db: benchmarking/nighthawk-egress/README.md only. The Prerequisites section is benchmarking/nighthawk-egress: size the rig so atenet-egress is the bottleneck under test #3627's, with the traffic-driver-invoker SPIFFE id.

Local checks:

hack/verify/benchmarking-python.sh
go test ./cmd/kubectl-ate/internal/cmd/ -run TestEgressPolicyFromManifest

tests/check_descriptor.py runs the real /out/nighthawk.desc descriptor check inside the runner image (test_spec.py skips when /out/nighthawk.desc is absent on the host).

@ygao-g
Yuan Gao (ygao-g) force-pushed the nighthawk-egress-2-runner branch 2 times, most recently from 1807b45 to 6629485 Compare November 5, 2026 22:14
…f nighthawk-ingress

Move nighthawk-ingress/output.py to nighthawk_common unchanged so
nighthawk-egress can reuse it. The ingress Dockerfile copies the package
into the image and the ingress tests put benchmarking/ on sys.path.

Signed-off-by: Yuan Gao <ypgao@google.com>
… out of nighthawk-ingress

Move nighthawk-ingress/spec.py to nighthawk_common unchanged and point its importers at the new path. actors.py imported it without using it.

Signed-off-by: Yuan Gao <ypgao@google.com>
…ut of nighthawk_common

build_session_spec in nighthawk_common now takes a finished traffic template. The router SNI, the certificate paths and build_spec_dict, which assembles that template, move back to nighthawk-ingress/spec.py.

Signed-off-by: Yuan Gao <ypgao@google.com>
benchmarking/workloads/deploy.sh built kubectl-ate inline, and the
nighthawk-egress deploy script was about to carry a copy. Move the
function into benchmarking/lib/kubectl-ate.sh for both to source.

Signed-off-by: Yuan Gao <ypgao@google.com>
…ration

With a 2 vCPU actor sandbox and no requests on the worker pod or
nighthawk-server, nothing kept the load generator and the origin server
from saturating before atenet-egress, so a run could measure them
instead of the gateway. Give the sandbox 16 vCPUs, request 12 vCPUs for
the worker pod and 6 for nighthawk-server, run the server with
--concurrency 8, and move the example nighthawk_client run from one
worker to sixteen.

Signed-off-by: Yuan Gao <ypgao@google.com>
deploy-traffic-driver.sh required kubectl-ate on PATH, so a fresh
environment needed a manual go install step first. Source
build_kubectl_ate from benchmarking/lib/kubectl-ate.sh instead, and say
so in the README prerequisites in place of the install step.

Signed-off-by: Yuan Gao <ypgao@google.com>
… per stage

Add the queue_to_connect and sequencer.blocking statistics and the latency pstdev to each stage row, make actors optional in capacity_summary, accept Path for descriptor paths, and export the helpers nighthawk-egress uses. Compute achieved-rps and send-rate from the exact stage duration, because Nighthawk truncates execution_duration to whole seconds.

Signed-off-by: Yuan Gao <ypgao@google.com>
…nter parser

Define the egress-specific failure predicates and Nighthawk template
for the adaptive load search, targeting the atenet-egress gateways.
Add the prometheus output parser for the egress metrics.

Signed-off-by: Yuan Gao <ypgao@google.com>
@ygao-g
Yuan Gao (ygao-g) force-pushed the nighthawk-egress-2-runner branch from 6629485 to 688514b Compare November 5, 2026 22:54
@ygao-g
Yuan Gao (ygao-g) marked this pull request as draft November 5, 2026 22:54
…and run-dev.sh

Add runner.py, spec.py and output.py glue, cluster_setup.py, the runner image and run-dev.sh, which drives one adaptive capacity run end to end and scrapes atenet-egress counters before and after it through the atenet-egress-metrics Service. Name nighthawk-server exactly in egress-policy.yaml, with and without the cluster.local suffix, because the actor resolv.conf sets ndots:5 and atunnel sees the suffixed name.

Signed-off-by: Yuan Gao <ypgao@google.com>
…ters, and results

Signed-off-by: Yuan Gao <ypgao@google.com>
@ygao-g

Copy link
Copy Markdown
Collaborator Author

Superseded by #3707 and #3708. The split moved from runner/automation to library/launcher, which removes cluster_setup.py and the template that only the next PR used. The cluster_setup.py rollout and --concurrency fixes from this branch are carried in #3708.

shankgan pushed a commit to shankgan/substrate that referenced this pull request Nov 13, 2026
…to nighthawk_common (agent-substrate#3628)

Part of agent-substrate#3624 (Stage 1, item 2): share the adaptive load session spec
and output helpers between `nighthawk-ingress` and the coming
`nighthawk-egress` runner.

### What changes
Pure relocation, no behavior change. `nighthawk-ingress/output.py` and
`spec.py` move to `benchmarking/nighthawk_common/`. The router-specific
parts of the spec builder (router SNI, certificate paths,
`build_spec_dict`) stay in `nighthawk-ingress/spec.py`, which now calls
the generic `build_session_spec`. Callers and tests import
`nighthawk_common` directly; the ingress Dockerfile copies the package
into the image.

### Review guide
1. `output.py` rename (GitHub shows 100%), two import lines, the
Dockerfile `COPY`, two `sys.path` lines in the ingress tests.
2. `spec.py` rename at 100%, importers repointed, an unused import
dropped from `actors.py`.
3. The split: read `nighthawk_common/spec.py` as deletions and
`nighthawk-ingress/spec.py` as the same lines moving back.

### Testing
`hack/verify/benchmarking-python.sh`: the ingress suite passes at each
commit, and fails without the new `sys.path` lines, so the import path
is exercised.

Independent of agent-substrate#3627. agent-substrate#3629 and agent-substrate#3630 stack on both.

AI use: AI-assisted for the diff, the commit split and the test runs; I
reviewed the diff.

- [x] Tests pass
- [ ] Docs updated (none needed)

---------

Signed-off-by: Yuan Gao <ypgao@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants