Skip to content

Commit 5c193a9

Browse files
Add Karpenter metrics integration to OTEL Container Insights (#325)
1 parent 93a934e commit 5c193a9

2 files changed

Lines changed: 135 additions & 16 deletions

File tree

charts/amazon-cloudwatch-observability/templates/linux/_otel-container-insights-cluster-scraper-config.tpl

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,34 @@ receivers:
5454
- {{ include "kube-state-metrics.name" . }}.{{ .Release.Namespace }}.svc:{{ .Values.kubeStateMetrics.service.port }}
5555
{{- end }}
5656

57+
{{- if and .Values.otelContainerInsights.solutions.enabled .Values.otelContainerInsights.solutions.karpenter.enabled }}
58+
prometheus/cw_k8s_ci_v0_karpenter:
59+
config:
60+
scrape_configs:
61+
- job_name: karpenter
62+
scrape_interval: {{ .Values.otelContainerInsights.metricResolution }}
63+
scrape_timeout: {{ include "otel-container-insights.scrapeTimeout" . }}
64+
metrics_path: /metrics
65+
kubernetes_sd_configs:
66+
- role: pod
67+
namespaces:
68+
names:
69+
- {{ .Values.otelContainerInsights.solutions.karpenter.namespace }}
70+
relabel_configs:
71+
- source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name]
72+
regex: karpenter
73+
action: keep
74+
- source_labels: [__meta_kubernetes_pod_container_port_name]
75+
regex: http-metrics
76+
action: keep
77+
- source_labels: [__meta_kubernetes_pod_name]
78+
target_label: pod
79+
- source_labels: [__meta_kubernetes_namespace]
80+
target_label: namespace
81+
- source_labels: [__meta_kubernetes_pod_node_name]
82+
target_label: node
83+
{{- end }}
84+
5785
processors:
5886
filter/cw_k8s_ci_v0_scrape_metadata:
5987
error_mode: ignore
@@ -140,6 +168,61 @@ processors:
140168
- set(attributes["cloudwatch.pipeline"], "kube-state-metrics")
141169
{{- end }}
142170

171+
{{- if and .Values.otelContainerInsights.solutions.enabled .Values.otelContainerInsights.solutions.karpenter.enabled }}
172+
transform/cw_k8s_ci_v0_set_scope_karpenter:
173+
error_mode: ignore
174+
metric_statements:
175+
- context: scope
176+
statements:
177+
- set(scope.name, "github.com/aws/karpenter")
178+
- set(scope.schema_url, "")
179+
- set(attributes["cloudwatch.source"], "cloudwatch-agent")
180+
- set(attributes["cloudwatch.solution"], "k8s-otel-container-insights")
181+
- set(attributes["cloudwatch.pipeline"], "karpenter")
182+
183+
# Promote scraped pod/namespace/node labels to OTel K8s resource attributes.
184+
# This allows the shared k8sattributes processor to enrich with deployment/workload info.
185+
groupbyattrs/cw_k8s_ci_v0_karpenter:
186+
keys:
187+
- pod
188+
- namespace
189+
- node
190+
191+
transform/cw_k8s_ci_v0_karpenter_promote:
192+
error_mode: ignore
193+
metric_statements:
194+
- context: resource
195+
statements:
196+
- set(attributes["k8s.pod.name"], attributes["pod"]) where attributes["pod"] != nil
197+
- set(attributes["k8s.namespace.name"], attributes["namespace"]) where attributes["namespace"] != nil
198+
- set(attributes["k8s.node.name"], attributes["node"]) where attributes["node"] != nil
199+
# Remove deprecated/unwanted attributes auto-injected by the Prometheus receiver.
200+
- delete_key(attributes, "net.host.name") where attributes["net.host.name"] != nil
201+
- delete_key(attributes, "net.host.port") where attributes["net.host.port"] != nil
202+
- delete_key(attributes, "url.scheme") where attributes["url.scheme"] != nil
203+
- context: datapoint
204+
statements:
205+
- set(attributes["pod"], resource.attributes["pod"]) where resource.attributes["pod"] != nil
206+
- set(attributes["namespace"], resource.attributes["namespace"]) where resource.attributes["namespace"] != nil
207+
- set(attributes["node"], resource.attributes["node"]) where resource.attributes["node"] != nil
208+
209+
# Karpenter-specific resource detection: only cloud-level attributes (region, account).
210+
# No host/AZ attributes — those would incorrectly reflect the scraper's node, not Karpenter's.
211+
resourcedetection/cw_k8s_ci_v0_karpenter:
212+
detectors: [eks, ec2]
213+
ec2:
214+
resource_attributes:
215+
host.id: { enabled: false }
216+
host.type: { enabled: false }
217+
host.name: { enabled: false }
218+
host.image.id: { enabled: false }
219+
cloud.provider: { enabled: true }
220+
cloud.platform: { enabled: true }
221+
cloud.region: { enabled: true }
222+
cloud.availability_zone: { enabled: false }
223+
cloud.account.id: { enabled: true }
224+
{{- end }}
225+
143226
transform/cw_k8s_ci_v0_set_cluster_name:
144227
error_mode: ignore
145228
metric_statements:
@@ -223,6 +306,22 @@ processors:
223306
- set(attributes["owner_name"], resource.attributes["owner_name"]) where resource.attributes["owner_name"] != nil
224307
- set(attributes["owner_kind"], resource.attributes["owner_kind"]) where resource.attributes["owner_kind"] != nil
225308

309+
k8sattributes/cw_k8s_ci_v0_node:
310+
auth_type: serviceAccount
311+
passthrough: false
312+
extract:
313+
metadata:
314+
- k8s.node.name
315+
labels:
316+
- tag_name: "k8s.node.label.$$$1"
317+
key_regex: "(.*)"
318+
from: node
319+
pod_association:
320+
- sources:
321+
- from: resource_attribute
322+
name: k8s.node.name
323+
{{- end }}
324+
226325
k8sattributes/cw_k8s_ci_v0_pod:
227326
auth_type: serviceAccount
228327
passthrough: false
@@ -266,22 +365,6 @@ processors:
266365
- set(resource.attributes["k8s.workload.name"], resource.attributes["k8s.replicaset.name"]) where resource.attributes["k8s.workload.name"] == nil and resource.attributes["k8s.replicaset.name"] != nil
267366
- set(resource.attributes["k8s.workload.type"], "ReplicaSet") where resource.attributes["k8s.workload.type"] == nil and resource.attributes["k8s.replicaset.name"] != nil
268367

269-
k8sattributes/cw_k8s_ci_v0_node:
270-
auth_type: serviceAccount
271-
passthrough: false
272-
extract:
273-
metadata:
274-
- k8s.node.name
275-
labels:
276-
- tag_name: "k8s.node.label.$$$1"
277-
key_regex: "(.*)"
278-
from: node
279-
pod_association:
280-
- sources:
281-
- from: resource_attribute
282-
name: k8s.node.name
283-
{{- end }}
284-
285368
transform/cw_k8s_ci_v0_set_component:
286369
error_mode: ignore
287370
metric_statements:
@@ -449,5 +532,26 @@ service:
449532
exporters:
450533
- otlphttp/cw_k8s_ci_v0_cwotel
451534
{{- end }}
535+
{{- if and .Values.otelContainerInsights.solutions.enabled .Values.otelContainerInsights.solutions.karpenter.enabled }}
536+
metrics/cw_k8s_ci_v0_karpenter:
537+
receivers: [prometheus/cw_k8s_ci_v0_karpenter]
538+
processors:
539+
- filter/cw_k8s_ci_v0_scrape_metadata
540+
- transform/cw_k8s_ci_v0_set_unit
541+
- metricstarttime/cw_k8s_ci_v0
542+
- transform/cw_k8s_ci_v0_set_scope_karpenter
543+
- transform/cw_k8s_ci_v0_set_cluster_name
544+
- groupbyattrs/cw_k8s_ci_v0_karpenter
545+
- transform/cw_k8s_ci_v0_karpenter_promote
546+
- k8sattributes/cw_k8s_ci_v0_pod
547+
- transform/cw_k8s_ci_v0_set_workload
548+
- resourcedetection/cw_k8s_ci_v0_karpenter
549+
- transform/cw_k8s_ci_v0_clear_schema_url
550+
- transform/cw_k8s_ci_v0_set_cloud_resource_id
551+
- awsattributelimit/cw_k8s_ci_v0
552+
- batch/cw_k8s_ci_v0_cwotel
553+
exporters:
554+
- otlphttp/cw_k8s_ci_v0_cwotel
555+
{{- end }}
452556
{{- end -}}
453557

charts/amazon-cloudwatch-observability/values.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,3 +1173,18 @@ otelContainerInsights:
11731173
cloudwatchMetricsEndpoint: ""
11741174
# Override the CloudWatch Logs OTLP endpoint. If empty, defaults to logs.<region>.amazonaws.com.
11751175
cloudwatchLogsEndpoint: ""
1176+
## ── Solutions ──────────────────────────────────────────────────────────
1177+
## Optional Prometheus metric scraping for well-known cluster components.
1178+
## Each solution is gated by its own enabled flag so customers only scrape
1179+
## what they actually run. Solutions only take effect when
1180+
## otelContainerInsights.enabled is true.
1181+
solutions:
1182+
## Global toggle: set to false to disable ALL solutions at once.
1183+
## Individual solutions won't activate even if their own enabled flag is true.
1184+
enabled: true
1185+
## Karpenter — cluster autoscaler for Kubernetes.
1186+
## Scrapes the Prometheus metrics endpoint exposed by the Karpenter controller.
1187+
karpenter:
1188+
enabled: true
1189+
## Namespace where Karpenter is deployed.
1190+
namespace: "kube-system"

0 commit comments

Comments
 (0)