Repository navigation
feat: filter out Karpenter node labels and pod-label counterparts from Container Insights metrics - #383
Conversation
| - "k8s.pod.label.topology.kubernetes.io/region" | ||
| - "k8s.pod.label.topology.kubernetes.io/zone" | ||
| - "k8s.pod.label.helm.sh/chart" | ||
| - "k8s.pod.label.release" |
There was a problem hiding this comment.
Is this a node label already?
There was a problem hiding this comment.
Yes, k8s.node.label.release is already on the denylist a few lines above, so this is its pod-side counterpart.
Align the recommended label exclusions with #383 and add the EKS Auto Mode equivalents: - Node prefix karpenter.k8s.aws/instance- and keys karpenter.sh/ do-not-sync-taints, initialized and registered (#383). - Pod keys pod-template-generation, topology.kubernetes.io/region, topology.kubernetes.io/zone, helm.sh/chart and release (#383). - Node prefix eks.amazonaws.com/instance-: the instance-type labels EKS Auto Mode sets, the counterpart of the Karpenter instance labels. - Node key topology.k8s.aws/zone-id, duplicated by cloud.availability_zone.
|
A warning from my Agent: Are we sure about this one? |
|
The test PR (#775) is stale against the final design. deniedKarpenterNodeLabels still says it "mirrors ... unconditional_removal_keys |
98b364a to
d613374
Compare
|
Do we want to exclude from this change the pod zone label until cloud.availability_zone is fixed? |
Align the recommended label exclusions with the denylist in #383: - Node prefixes karpenter.k8s.aws/instance- and eks.amazonaws.com/instance-: the instance-type labels set by Karpenter and by EKS Auto Mode. - Node keys karpenter.sh/do-not-sync-taints, initialized and registered. - Pod keys pod-template-generation, topology.kubernetes.io/region and topology.kubernetes.io/zone. topology.k8s.aws/zone-id, and the pod labels helm.sh/chart and release, are kept, as in #383: the zone ID is the only attribute that identifies the same physical zone across accounts, and release often carries user intent such as canary deployments.
Raised the fix: #405 |
Align the recommended label exclusions with the denylist in #383: - Node prefixes karpenter.k8s.aws/instance- and eks.amazonaws.com/instance-: the instance-type labels set by Karpenter and by EKS Auto Mode. - Node keys karpenter.sh/do-not-sync-taints, initialized and registered. - Pod keys pod-template-generation, topology.kubernetes.io/region and topology.kubernetes.io/zone. topology.k8s.aws/zone-id, and the pod labels helm.sh/chart and release, are kept, as in #383: the zone ID is the only attribute that identifies the same physical zone across accounts, and release often carries user intent such as canary deployments.
| - "k8s.node.label.beta.kubernetes.io/" | ||
| - "k8s.node.label.failure-domain.beta.kubernetes.io/" | ||
| - "k8s.node.label.alpha.eksctl.io/" | ||
| - "k8s.node.label.karpenter.k8s.aws/instance-" |
There was a problem hiding this comment.
This prefix also matches karpenter.k8s.aws/instance-tenancy. That's a well-known Karpenter label, and it's set on both Karpenter and Auto Mode nodes. Unlike the other instance-* labels, it can't be derived from host.type. It's a launch property, which is the same reason capacity-reservation-* and placement-group-* are kept. With this prefix, customers running dedicated-tenancy NodePools lose the only per-node tenancy dimension. Was that intended? If not, could we list the instance-type-derived keys explicitly instead of using the prefix, or exclude instance-tenancy from it?
There was a problem hiding this comment.
Not intended, thanks. Tenancy is a launch property, so the denylist now keeps it. The single prefix is replaced by instance-cpu, instance-gpu- and instance-accelerator- plus 11 exact keys, which still deny the other 21 instance labels. The Auto Mode prefix stays, because the documented eks.amazonaws.com/instance-* labels include no tenancy key.
| - "k8s.pod.label.controller-revision-hash" | ||
| - "k8s.pod.label.pod-template-generation" | ||
| - "k8s.pod.label.topology.kubernetes.io/region" | ||
| - "k8s.pod.label.topology.kubernetes.io/zone" |
There was a problem hiding this comment.
Dropping k8s.pod.label.topology.kubernetes.io/zone and /region removes the only zone source in pipelines where nothing carries it into cloud.availability_zone. #405 does that only for the KSM pipeline, and not on AKS. The affected cases:
- AKS: the node-agent config has no cloud.availability_zone source, the node zone label is already denied, and fix(container-insights): take each series' availability zone and region from its node and pod, not the cluster scraper #405's copy is skipped on AKS. So AKS series end up with no zone at all.
- k8sMode=K8S off EC2: the ec2 detector fails, so these pod labels were the only region and zone info.
- Cluster-scraper Karpenter/KEDA/KServe/Knative pipelines: their resourcedetection turns off cloud.availability_zone, so the pod label was the only zone on those series.
This only affects clusters where the KEP-4742 PodTopologyLabels admission plugin is on, which is beta and on by default from 1.35. Is that loss acceptable, or should these platforms and pipelines keep the label, or get a copy into cloud.availability_zone like #405 does for KSM?
There was a problem hiding this comment.
Good catch, all three cases are real. #405 now copies the pod's region and zone labels into cloud.region and cloud.availability_zone before the denylist runs, in every pipeline that adds pod labels, on both collectors. It skips digit-only zones, because on AKS nodes outside availability zones the label holds the fault domain. This PR ships in the same release as #405.
…abels and pod-label counterparts
d613374 to
ee72202
Compare
Important
Breaking change. This change needs a major chart version bump, from
6.xto7.0.0. It removes the instance-derived node labels that Karpenter and EKS Auto Mode set on the nodes they manage. It also removes 3 pod labels from every pod, whether or not either provisioner is in use. There is no deprecation window and novalues.yamlopt-out, so it must not be picked into a minor or patch release.Issue #, if available:
n/a
Description of changes:
Extends the denylist in
awsattributelimit/cw_k8s_ci_v0in both collector configurations:templates/linux/_otel-container-insights-config.tpl(node agent) and_otel-container-insights-cluster-scraper-config.tpl(cluster scraper). It denies the 21 Karpenter instance labels derived from the instance type and their 16 EKS Auto Mode copies. It also denies 3karpenter.sh/node-management flags and the 3 pod labels below. There is no other change in behavior.Karpenter applies its labels to every node it manages, and the Kubernetes attribute enrichment copies them onto the resource block. So their key text rides every datapoint from a Karpenter-managed node. Most of them are derived from instance type details, so they restate
host.type, which these pipelines already publish. The denylist already removes comparable platform-injected families (feature.node.kubernetes.io/,beta.kubernetes.io/,alpha.eksctl.io/,sourceLaunchTemplateId). The Karpenter equivalents were never added.What is removed and what is kept
The list is complete against upstream's
WellKnownLabels. Karpenter defines 28 labels underkarpenter.k8s.aws/and 5 underkarpenter.sh/. This change denies 21 and 3. It keeps the other 9, because they are not derived from the instance type:karpenter.sh/nodepool,karpenter.k8s.aws/ec2nodeclassandkarpenter.sh/capacity-typeidentify how the node was provisioned.capacity-typeis the only spot or on-demand signal.karpenter.k8s.aws/capacity-reservation-id,-typeand-interruptibledescribe the reservation a node consumed. They tell whether it is an ODCR or a Capacity Block, and whether EC2 can reclaim it.karpenter.k8s.aws/placement-group-idand-partitiontell which placement group and partition the instance launched into. A partition is an independent failure domain.karpenter.k8s.aws/instance-tenancyisdefaultordedicated. Tenancy is a launch property: the same instance type runs on shared or dedicated hardware, sohost.typedoes not give it.Because of these 9, neither domain is denied by prefix. A single
karpenter.k8s.aws/instance-prefix also removesinstance-tenancy. So the 21 labels are denied by three narrower prefixes and 11 exact keys:instance-cpu,instance-gpu-andinstance-accelerator-cover 10 labels. They also cover CPU, GPU and accelerator labels that Karpenter adds in the future.instance-{category,family,generation,size,memory,hypervisor,local-nvme,ebs-bandwidth,network-bandwidth,encryption-in-transit-supported,capability-flex}.The 3
karpenter.sh/keys are exact keys, becausenodepoolandcapacity-typeare kept in that domain.EKS Auto Mode
Auto Mode is AWS-managed Karpenter. It sets the same instance-derived labels under
eks.amazonaws.com/instead ofkarpenter.k8s.aws/. The supported-labels table lists 16 keys:eks.amazonaws.com/instance-{category,family,size,generation,cpu,cpu-manufacturer,memory,hypervisor,local-nvme,ebs-bandwidth,network-bandwidth,encryption-in-transit-supported}and fourgpu-*keys. Each restateshost.type, as its Karpenter counterpart does, and the table lists no tenancy label. One prefix entry,k8s.node.label.eks.amazonaws.com/instance-, denies them.The other labels in that domain do not begin with
instance-, so the prefix does not catch them. They arecompute-type,nodegroup,capacityType,fargate-profileand twocapacity-reservation-*labels.compute-typeis kept, because it identifies a node as managed by Auto Mode. Auto Mode useskarpenter.sh/capacity-typefor the spot or on-demand signal, which this denylist keeps.The integration tests do not cover the Auto Mode half. None of the clusters available to run them uses Auto Mode. On those clusters, an absence assertion passes even though the keys were never there. It rests on the label table and on the prefix being structurally equivalent to the Karpenter one.
GPU and Neuron dashboards are unaffected. Device identity travels on the datapoint attributes of the
DCGM_FI_DEV_*andneuroncore_*metrics, which this change does not touch. Karpenter's Neuron branch also sets theinstance-accelerator-*labels, so the accelerator prefix covers Trainium and Inferentia2 as well as Inferentia1.Pod-label counterparts of already-denied node labels
It also denies three
k8s.pod.label.*keys, on every cluster, with or without Karpenter:topology.kubernetes.io/regionandtopology.kubernetes.io/zoneare pod-side copies of node labels that this denylist already removes. The admission plugin behind KEP-4742 copies the node's topology labels onto the pod, so they arrive in addition to the denied node form.pod-template-generationis a DaemonSet controller revision marker, from the same family as the already-deniedpod-template-hashandcontroller-revision-hash.Note
This change ships in the same release as #405. On some platforms and pipelines, the pod topology labels are the only region and zone a series has. #405 copies them into
cloud.regionandcloud.availability_zonebefore this denylist runs, so no series loses its region or zone.What a consumer sees. The dimensions surface as the
k8s_node_label_karpenter_*,k8s_node_label_eks_amazonaws_com_*andk8s_pod_label_*metric labels, and under the@resource.prefix in PromQL. Both stop resolving for every denied key. For example, a query that groups bykarpenter.k8s.aws/instance-familyreturns one unlabelled series, and an alarm scoped to oneinstance-sizestops matching anything. Queries on a pod's region or zone usecloud.regionandcloud.availability_zoneinstead. Worth a release note.Testing:
helm lintpasses with a region set. The rendered configuration of both collectors contains the threekarpenter.k8s.aws/instance-prefixes, theeks.amazonaws.com/instance-prefix and the 17 exact keys. It denies none of the 9 kept Karpenter labels and none of the kept Auto Mode labels. The chart suites pass:flag_matrix.sh8/8,pod_level_values.sh22/22,yaml_document_injection.sh17/17, and the KServe, Knative, vLLM and Neuron pipeline shape tests.aws/amazon-cloudwatch-agent-test#775 adds four integration tests. Each removal assertion has a guard:
TestKarpenterInstanceLabelsRemovedchecks that no label under the twoinstance-prefixes remains, exceptinstance-tenancy.TestKarpenterGroupingLabelsRetainedrequiresnodepool,capacity-type,ec2nodeclassandinstance-tenancy.TestPodLabelCounterpartsRemovedchecks the 3 pod labels.TestPodLabelsStillEnrichedrequires other pod labels to stay.The guards make the kept-key decisions testable. If a regression widens either denylist to a domain prefix, the removal tests pass and the guards fail.
The tests ran on a live EKS cluster, because the claim is about what reaches CloudWatch, not what the configuration renders to. We applied the configuration to the running agent and cluster scraper and restarted the pods. After 30 minutes,
test/otel/standard -computeType=EKSasserted on datapoints read back from CloudWatch.TestKarpenterInstanceLabelsRemovedTestKarpenterGroupingLabelsRetained(guard)TestPodLabelCounterpartsRemovedTestPodLabelsStillEnriched(guard)There were no failures and no skips. The Karpenter pair also ran before the change, because an "attribute is absent" assertion passes trivially against empty data. The guard passing on both sides shows that only the intended keys went. The counterpart pair has no baseline from before the change. Its result shows that the keys are absent now, not that they were present before. In this run the denylist also removed
instance-tenancy. So the removal results hold for every denied label that the cluster's nodes carry, and the retention ofinstance-tenancyis checked on the rendered configuration.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Related pull requests
PR Checklist