Repository navigation
test(otel): add vLLM, KServe and Knative solution integration tests - #779
Conversation
4f0bfd7 to
8ae3959
Compare
Coverage gaps
Nits
|
8ae3959 to
939e916
Compare
|
Thanks, updated:
Nits: counters are now checked to increase; the cluster-scraper patch and restart fail the run instead of Chart PRs now: vLLM aws-observability/helm-charts#398, KServe aws-observability/helm-charts#400 (merged), Knative aws-observability/helm-charts#401 (after #398). |
olowosulu
left a comment
There was a problem hiding this comment.
Thanks for the thorough suite, the kserve/knative contract checks line up with the chart. One thing I think blocks merge and two I'd want sorted before we rely on the run history.
Blocker: vllm_test.go:114 asserts k8s.container.name == "kserve-container", but the chart never sets that attribute. The vllm scrape job only uses __meta_kubernetes_pod_container_name for target selection and vllm_promote promotes pod/namespace/aws.service.type only (DCGM does label the container, vllm doesn't). res["k8s.container.name"] is "" so this fails every run. Easiest fix is to drop the line (the per-pod count in TestVLLMNoDuplicateSeries already covers queue-proxy); otherwise it needs a chart change adding target_label: container plus a promote. Line 143 (NotEqual "queue-proxy") is vacuous for the same reason.
Suggestion: chart source in CI. test-artifacts.yml installs the chart from the newest release-* branch (currently release-6.7.0), which has no vllm/kserve/knative keys. So the default run fails all three suites and wip: true turns that into a warning until a release branch includes helm-charts #398/#400/#401. Could you note that in the PR / generator comment, or add a guard that fails explicitly when the installed chart has no vllm: solution?
Suggestion: negative tests are vacuous. The annotated/generic mock tests (vllm_test.go:325-344) query only pipeline="vllm" with no positive control that the pods exist, and the dropped-family checks (knative_test.go:113, kserve_test.go:134, vllm_test.go:350) assert fixed names are absent; http_request_size_bytes can't appear anyway since CloudWatch rejects Summaries. Suggest using client.MetricNames to list what's actually there, require.NotEmpty, then assert no forbidden prefixes.
Nits:
solution_helpers.go:45-47:Increasereturns 0 for both "no data" and "no increase", so the failure message is misleading.solution_helpers.go:23-35:SeriesduplicatesQueryCache.GetWithFilter; root cause isquery_cache.go:237-238not quoting@instrumentation.*keys. Adding that case letsSeries/PipelineMatchergo.client.go:171-172treats 429 as fatal and vllm fires ~66 uncached parallel queries; flake risk.main.tf:583-599: withset -ea vllm failure skips kserve/knative. Collectrcper suite instead.- Description drift: reply says one busybox control kept but
main.tf:399still deploys both; body says vllm has 9 tests, file has 11;main.tf:4-14header omits transformer/hello-ksvc. vllm/setup_test.go:99-110registry wiring is unused by the suite; attribution keys differ across suites (k8s.workload.*vsk8s.deployment.name).
|
Thanks! Updated in c5cfa07:
|
Add an EKS root, terraform/eks/daemon/otel-llm-serving, that runs KServe in
Serverless mode (Knative Serving on Istio) on CPU nodes with a vLLM
InferenceService plus a transformer, a plain vLLM Deployment, a plain Knative
Service, two annotated pods that must not be scraped (a vLLM mock from a
custom-named image and a non-vLLM exporter) and a load generator, then
installs the helm chart with otelContainerInsights enabled. helm_chart_repo
lets a fork branch be tested.
test/otel/solutions/{vllm,kserve,knative} check in CloudWatch: expected
metrics, scope and pipeline, cloud identity, pod/workload attribution with
the InferenceService from KServe's own pod label and no custom attribute
keys, aws.service.type = ai_inference on the predictor only (not the
transformer or a plain Knative Service), nothing from the transformer or
annotated pods in the vllm pipeline, request counters increasing, one series
per target, no AZ or host on cluster-scraper series, and the filtered
families (client-go, Go runtime, process, python). Knative <= 1.18 names are
not covered. Shared helpers live in util/otelmetrics.
The root is in the eks_daemon matrix as wip. Like terraform/eks/daemon/otel,
it runs test_dir (vllm) and then the kserve and knative suites on the same
cluster; the cluster-scraper image patch and restart now fail the run instead
of being skipped.
Makes the negative tests non-vacuous and moves the shared query helpers into the query cache. - Quote @instrumentation.* (any @-prefixed) keys in QueryCache.GetWithFilter and route it through the cache's concurrency limit - Retry HTTP 429 in the PromQL client like a server error - Remove Series and PipelineMatcher; suites use GetWithFilter with PipelineFilter - Make Increase fail when no series match instead of returning 0 - Add PublishedMetricNames and RequireNoPrefix; dropped-family tests list what each pipeline published - Add positive controls to the annotated-mock, generic-exporter and transformer tests - Require a non-empty k8s.container.name in TestVLLMNoDuplicateSeries and note it comes from the Prometheus receiver - Use k8s.workload.name and k8s.workload.type in the KServe and Knative control-plane suites - Drop the unused source registry from the vLLM suite and the SourceVLLM constant - Run every suite and fail at the end, and fail fast when the cloned chart has no vllm/kserve/knative solution - Note the chart-branch dependency in the generator entry and list the transformer and hello-ksvc in the root header
c5cfa07 to
f337652
Compare
Summary
End-to-end integration tests for the OTEL Container Insights LLM model-serving solutions in the helm chart: vLLM (aws-observability/helm-charts#398), KServe control plane (aws-observability/helm-charts#400, merged) and Knative Serving (aws-observability/helm-charts#401).
They follow
test/otel/solutions/kedaandkarpenter: a terraform root builds an EKS cluster, installs the workloads and the chart, then Go suites query CloudWatch's PromQL endpoint and check what the agent published.Test cluster:
terraform/eks/daemon/otel-llm-servingmetrics-protocol,request-metrics-protocol) and restarted, since it reads them at startup.public.ecr.aws, because resolving the multi-GB vLLM image's tag times out.llm. Each exercises one chart rule:vllm-isvc: InferenceService, vLLM CPU image,enable-prometheus-scrapingkserve-container; the Knative data plane; KServe's ownprometheus.io/*must not make the queue-proxy a targetvllm-isvctransformer (hello-world container,component: transformer)aws.service.typevllm-standalone: Deployment, vLLM CPU imagehello-ksvc: plain Knative Service (hello-world)aws.service.typevllm-annotated-mock: busybox serving staticvllm:*andhttp_*, withprometheus.io/*annotationsgeneric-exporter: busybox,prometheus.io/*loadgenBoth vLLM servers run Qwen2.5-0.5B-Instruct with a memory-backed
/dev/shm. The chart is cloned fromhelm_chart_repoathelm_chart_branch, so a fork branch can be tested before merge, and installed withotelContainerInsights.enabled=true(the solutions default on). The agent image is then replaced withcwagent_image_repo:cwagent_image_tag, as in the other OTEL roots.The cluster-scraper image patch and restart fail the run if the scraper is missing, since the KServe and Knative suites need it. The root also fails fast if the cloned chart has no
vllm,kserveorknativesolution. The validator waits 4 minutes for data, then runstest_dir(default./test/otel/solutions/vllm) followed bysolutions/kserveandsolutions/knativeon the same cluster; every suite runs, and the run fails at the end if any did.Suites:
test/otel/solutions/{vllm,kserve,knative}Same layout as the KEDA suite (
setup_test.go,metrics_test.go,*_test.go), usingutil/otelmetricswith newSourceVLLM,SourceKServeandSourceKnativeconstants.vllm (11 tests): 12 metrics from both real servers. Also checks:
github.com/vllm-project/vllm, pipelinevllm, and datapoint labelsservice.name, KServe's pod labelk8s.pod.label.serving.kserve.io/inferenceservice(and no custominferenceservicekey),kserve-container, the revision Deployment,aws.service.type = ai_inference, cloud identityqueue-proxycontainervllm:request_success_total,http_requests_total) increase on both serverspython_*orprocess_*nameskserve (5 tests): 8 controller-runtime and leader-election metrics. Also checks:
github.com/kserve/kserve, pipelinekserve-controlplane, labelsk8s.workload.*) attribution and cloud identityworkqueue_*,rest_client_*,go_*orprocess_*namesknative (6 tests):
kn_*metrics attributed to their component pod and workload (component also ask8s.pod.label.app, no customknative_componentkey), cloud identity, no AZ or host, and nogo_*,process_*or*_go_*names publishedkn_serving_invocation_duration_secondsattributed to the revision Deployment and InferenceService (KServe's pod labels, no custom key), withaws.service.type = ai_inferenceaws.service.typekn_*namesShared helpers (
Increase,PublishedMetricNames,RequireNoPrefix,RequireCloudIdentity,RequireNoAttribute) live inutil/otelmetrics/solution_helpers.go.QueryCache.GetWithFilternow quotes@instrumentation.*keys and shares the cache's concurrency limit, and the client retries HTTP 429.Every suite checks cloud identity as KEDA and Karpenter do:
cloud.provider,cloud.platform, region, account, and the cluster ARN incloud.resource_id.CI
Added to the
eks_daemonmatrix aseks_daemon:otel_solutions_vllm_test(m5.2xlarge, AL2023, Kubernetes 1.35) withwip: true, so failures don't block CI until it has a run history. One cluster per run covers all three suites.CI installs the chart from the newest helm-charts
release-*branch. Until a release branch includes aws-observability/helm-charts#398, aws-observability/helm-charts#400 and aws-observability/helm-charts#401, the run stops at the chart guard (a warning, withwip).Testing
terraform applyof the root: all three suites pass. As a negative check, the same cluster with attribution and filtering removed from the chart makes the attribution and filter tests fail.go vet -tags integration,gofmtandgo test ./util/otelmetrics/(newTestFilterMatchers) are clean.terraform fmtandterraform validatepass.go run ./generatoremits the new matrix entry.PR Checklist
go vet/gofmt/terraform validatepass locallyterraform applyrun aboveotelmetricssource constants