Repository navigation
Add OTel Container Insights filters EKS integration test - #782
Conversation
4a047df to
fc94301
Compare
| "k8s.node.label.filters-e2e-node-drop", | ||
| "k8s.node.label.filters-e2e.example.com/drop-a", | ||
| "k8s.node.label.filters-e2e.example.com/drop-b", | ||
| "k8s.node.label.kubernetes.io/arch", |
There was a problem hiding this comment.
The Terraform config uses "filters-e2e.example.com/*" as a dotted prefix in the exclude list, but the include list only has "filters-e2e*" (no dots) and "kubernetes.io/os" (exact match). So the key_regex rendering path, the one with the double-escaping concern in the helm chart change, is never exercised by a presence check. If that path is broken, dotted prefix includes would silently fail to extract labels and this test wouldn't catch it.
Should we add one dotted-prefix include case?
In main.tf, add a keep label to node_labels:
+ "filters-e2e.example.com/keep-x" = "v"
In the chart values, add it to both include lists:
- include: ["filters-e2e*", "kubernetes.io/os"]
+ include: ["filters-e2e*", "filters-e2e.example.com/keep*", "kubernetes.io/os"]
And in filters_test.go:
keptLabels = []string{
"k8s.node.label.filters-e2e-node-keep",
+ "k8s.node.label.filters-e2e.example.com/keep-x",
"k8s.node.label.kubernetes.io/os",
This directly exercises the key_regex + regexQuoteMeta code path and would catch the escaping bug as a failing assertLabels call rather than needing a manual cluster test.
There was a problem hiding this comment.
Added, with one change: the node exclude filters-e2e.example.com/* removes that node label, so the test uses the pod label filters-e2e.example.com/keep-x with the include filters-e2e.example.com/keep*.
|
|
||
| // markerLogs returns the test workloads' log records from the last | ||
| // logLookback. | ||
| func markerLogs() ([]logRecord, error) { |
There was a problem hiding this comment.
This only queries the application log group. The transform/cw_k8s_ci_v0_logs_labels processor is also wired into the host logs pipeline, but host log resource attributes are never checked. Should we add a small helper that queries /aws/otel/containerinsights/%s/host and asserts that k8s.node.label.filters-e2e-node-keep is present and k8s.node.label.filters-e2e-node-drop is absent?
There was a problem hiding this comment.
Added TestLabelFilterHostLogs. The AL2023 nodes have no /var/log/messages by default, so a small DaemonSet writes a marker line there on each node.
| assert.Empty(t, byNamespace(records, ns), "logs present for filtered namespace %s", ns) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
resources here come entirely from container_cpu_usage_seconds_total, which is a node agent metric. The cluster scraper (deployment, not daemonset) has its own k8sattributes processor instances and its own awsattributelimit, both rendered from the same template helpers. Should we add kube_pod_info to the assertLabels check, querying its resources in filters-keep-a and asserting the same kept/dropped labels? It would close the loop on the scraper side I believe.
There was a problem hiding this comment.
Added: the label test now also checks kube_pod_info from the cluster scraper, next to container_cpu_usage_seconds_total from the node agent.
| assertLabels(t, "logs", resources, concat(keptLabels, []string{recommendedLabel}), droppedLabels) | ||
| } | ||
|
|
||
| func TestMetricNameFilter(t *testing.T) { |
There was a problem hiding this comment.
The optional solution pipelines (DCGM, Neuron, EFA, vLLM, KServe, Knative) aren't enabled in the Terraform config, so the metric name filter's wiring into those pipelines isn't covered here.
There was a problem hiding this comment.
The e2e cluster runs none of those workloads, so their pipelines stay off. The chart suite asserts the metric name filter in every metrics pipeline with DCGM, Neuron, EFA, vLLM, KServe and Knative on.
11ff306 to
ad396d2
Compare
…lters on EKS, with EFA, GPU and Neuron devices
ad396d2 to
3b105e7
Compare
bhavya76
left a comment
There was a problem hiding this comment.
does PR description need an update since our new commits?
|
Yes, thanks. I updated it for the Neuron suite, the vLLM, Knative and metric name case tests, and the merged chart PRs. The Tests section links the passing jobs on the current head. |
Description of the issue
The Helm chart adds the
otelFiltersblock for OTel Container Insights: namespaces (aws-observability/helm-charts#393), pod and node labels (aws-observability/helm-charts#394) and metric names (aws-observability/helm-charts#395). Those PRs test how the values become the generated OTel configuration. This PR makes sure, on a real EKS cluster, that the telemetry that reaches CloudWatch matches the filter values.The suites need the chart changes of aws-observability/helm-charts#393, aws-observability/helm-charts#394 and aws-observability/helm-charts#395, which are on
main. The Terraform clones the chart fromhelm_chart_branch, and the default ismain.Description of changes
terraform/eks/daemon/otel-filters, patterned onotel-attr-limit: its own cluster with one 2-node group that carries test node labels. The chart values are oneotelFiltersblock with an include list and an exclude list for each filter, each with at least one prefix entry. A logging workload with test pod labels runs one pod per node in each of 4 namespaces, 2 kept and 2 filtered. A small DaemonSet writes a marker line to/var/log/messageson every node, because the AL2023 nodes have no host log files by default. A stand-in inference pod runs on each node in one kept and one filtered namespace. It looks like a KServe predictor with a queue-proxy, and two nginx containers serve fixed vLLM and Knative data plane metrics.test/otel/filtersreads metrics from kube-state-metrics, cAdvisor, kubelet stats and node exporter, and the application and host logs, from the node agents and the cluster scraper:filters-exact-othermakes the test fail if the exact entryfilters-exactmatches as a prefix.filters-e2e-otheroutsidepodLabels.include, are absent. With"*"innodeLabels.include,kubernetes.io/archandkubernetes.io/osare present. The built-in labelskubernetes.io/hostname,node.kubernetes.io/instance-type,topology.kubernetes.io/regionandtopology.kubernetes.io/zoneare absent.pod-template-hashis on the include list and on the built-in list, and it is present, because a named include entry wins over the built-in list. Two fixture node labels fall inside the built-in prefixkarpenter.k8s.aws/instance-gpu-. The namedinstance-gpu-nameis present andinstance-gpu-countis absent, which teststransform/cw_k8s_ci_v0_metrics_labelsand the logs transform. Other cases fail if the escapedkey_regexof a dotted prefix does not match, or if an exact entry matches as a prefix.k8s.pod.*. The excluded names, the names outside the include list, andnode_load15, which starts with the exact include entrynode_load1, are absent, from both agents.vllm:num_requests_runningandrevision_request_countare present for the kept namespace and absent for the filtered one. The test fails iffilter/cw_k8s_ci_v0_metrics_namespacesis missing from either pipeline or runs before the promote transform.client.Queryper name rather thanqueryCache. The absence checks need fresh results, and the source registry expects every metric of a source, which a metric name filter removes by design.terraform/eks/daemon/otel-multi-efa-filters, patterned onotel-multi-efa: its own cluster with two nodes that have two EFA cards each, andotelFilters.namespaces.excludenamesefa-drop. On node 1, oneefaburnpod inefa-keepand one inefa-dropuse one card each. On node 2, one moreefa-droppod uses one card, and the other card is free. The chart installs only after all three pods run. Theefaburnimage defaults toefaburn:latestin the ECR registry of the account and region that run the test.test/otel/multi_efa_filters: the setup fails unless node 1 runs only theefa-keepandefa-droppods, node 2 runs only the secondefa-droppod, and each node has two EFA devices. Each check is scoped to one node, for each of 4 EFA metrics. On node 1, one card carries theefa-keeppod and namespace, and the other card has nok8s.pod.name,k8s.namespace.nameork8s.container.nameat resource or data point scope. This tests the per-card pods ofgroupbyattrs/cw_k8s_ci_v0_efa, and the oldtransform/cw_k8s_ci_v0_efa_promotefails it in either card order. On node 2, both cards are present and neither has pod attributes, so the old drop filter fails it. On both nodes, no series carries anefa-dropnamespace, pod name or pod UID. Because no agent runs before every pod holds its card, series without a pod from the agent start cannot hide a dropped card on node 1. On node 2, the checks wait until the agent has run longer than the query lookback.terraform/eks/daemon/otel-gpu-filters, patterned onotel-gpu: its own cluster with one g4dn.12xlarge node (4 GPUs). Onegpu-burnpod ingpu-keepand one ingpu-dropuse one GPU each, two GPUs are free, andotelFilters.namespaces.excludenamesgpu-drop.otelFilters.metricNames.excludenamesDCGM_FI_DEV_SM_CLOCKanddcgm_fi_dev_gpu_temp. The chart installs only after both pods run.test/otel/gpu_filters: the setup fails unless both pods run on the GPU node and it has 4 GPUs. For 3 DCGM metrics, the test expects 4 GPU UUIDs. One GPU carries thegpu-keeppod and namespace at resource scope and as the rawpodandnamespaceat data point scope. The other three have no pod attributes at either scope, and no series carries agpu-dropnamespace, pod name or pod UID. The old drop filter fails it, and so does a transform that cleans only the resource, becausetransform/cw_k8s_ci_v0_dcgm_promotecopies the pod keys onto every DCGM data point. Metric names are case-sensitive:DCGM_FI_DEV_SM_CLOCKis absent, andDCGM_FI_DEV_GPU_TEMPis present from all 4 GPUs.terraform/eks/daemon/otel-neuron-filters, patterned onotel-neuron: its own cluster with one standard node and one inf2.xlarge Neuron node (2 cores) with test node labels. Oneneuron-burnpod inneuron-keepand one inneuron-dropuse one core each and carry test pod labels.otelFilters.namespaces.excludenamesneuron-drop, andpodLabelsandnodeLabelseach have exact, prefix and exclude entries. The chart installs only after both pods run.test/otel/neuron_filters: for 2 core metrics, the test expects 2 cores. One core carries theneuron-keeppod, namespace and container and every kept pod label. The other core has no pod attributes at resource or data point scope and no pod labels. Both cores carry the kept node labels. No series has a dropped label or aneuron-dropnamespace, pod name or pod UID, except inaws.neuron.runtime.tag.eks_daemon:otel/filtersnext tootel/attr_limit,otel/multi_efa_filtersnext tootel/multi_efa,otel/gpu_filters(g4dn.12xlarge) next tootel/gpu, andotel/neuron_filters(inf2.xlarge) next tootel/neuron.License
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Tests
gofmt -l: no files.go vet -tags integrationon./test/otel/filters/,./test/otel/multi_efa_filters/,./test/otel/gpu_filters/,./test/otel/neuron_filters/and./generator/: passes. The four test packages compile with theintegrationtag.groupbyattrsandtransformv0.150.0, ran on one node with four cards for exclude, include and prefix lists and all 24 card orders. Every data point stayed. Only the cards of filtered pods lost their pod attributes, andk8sattributesadded none back.helm_chart_branch=glf-dra-off-test, which ismainat 57ef424 withotelContainerInsights.enableDRACorrelation: false, because the agent build that the tests use does not accept the DRA settings ofawsdevicepodcorrelationyet.test_repo_branch=otel-ci-filters-e2e,helm_chart_branch=glf-dra-off-testandtest_dir_filter=./test/otel/filters: EKS job: all 7 tests pass (TestNamespaceFilterMetrics,TestNamespaceFilterInferenceMetrics,TestNamespaceFilterLogs,TestLabelFilterMetrics,TestLabelFilterLogs,TestLabelFilterHostLogsandTestMetricNameFilter).test_repo_branch=otel-ci-filters-e2e,helm_chart_branch=glf-dra-off-testandtest_dir_filter=./test/otel/multi_efa_filters: EKS job: both tests pass (TestEFANamespaceFilterandTestEFAFreeCardNamespaceFilter), each for all 4 EFA metrics.test_repo_branch=otel-ci-filters-e2e,helm_chart_branch=glf-dra-off-testandtest_dir_filter=./test/otel/gpu_filters: EKS job: both tests pass (TestGPUNamespaceFilter, for all 3 DCGM metrics, andTestMetricNameFilterCase).test_repo_branch=otel-ci-filters-e2e,helm_chart_branch=glf-dra-off-testandtest_dir_filter=./test/otel/neuron_filters: EKS job:TestNeuronFilterspasses for both Neuron core metrics.PR Checklist
makepasses locally (build, unit tests, lint):go vet