Skip to content

Commit 5818256

Browse files
authored
Support OTel Container Insights on AKS (#348)
1 parent 222cc32 commit 5818256

7 files changed

Lines changed: 330 additions & 5 deletions

File tree

.github/workflows/amazon-cloudwatch-observability-integration-test.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ jobs:
4444
# Keep sorted alphabetically.
4545
scenario:
4646
- agent-config-merge-isolation
47+
- aks-otel-container-insights
4748
- appsignals-disabled
4849
- appsignals-disabled-multi-agents
4950
- appsignals-enabled-multi-agents

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,26 @@ processors:
291291
- set(resource.attributes["k8s.component.name"], attributes["component"])
292292

293293
resourcedetection/cw_k8s_ci_v0:
294+
{{- if eq .Values.k8sMode "AKS" }}
295+
detectors: [aks, azure]
296+
aks:
297+
resource_attributes:
298+
cloud.platform: { enabled: true }
299+
cloud.provider: { enabled: true }
300+
k8s.cluster.name: { enabled: false }
301+
azure:
302+
resource_attributes:
303+
azure.resourcegroup.name: { enabled: true }
304+
azure.vm.name: { enabled: false }
305+
azure.vm.scaleset.name: { enabled: false }
306+
azure.vm.size: { enabled: false }
307+
cloud.account.id: { enabled: true }
308+
cloud.platform: { enabled: true }
309+
cloud.provider: { enabled: true }
310+
cloud.region: { enabled: true }
311+
host.id: { enabled: false }
312+
host.name: { enabled: false }
313+
{{- else }}
294314
detectors: [eks, ec2]
295315
ec2:
296316
resource_attributes:
@@ -303,6 +323,7 @@ processors:
303323
cloud.region: { enabled: true }
304324
cloud.availability_zone: { enabled: true }
305325
cloud.account.id: { enabled: true }
326+
{{- end }}
306327

307328
nodemetadataenricher/cw_k8s_ci_v0: {}
308329

@@ -340,8 +361,19 @@ processors:
340361
metric_statements:
341362
- context: resource
342363
statements:
364+
{{- if eq .Values.k8sMode "AKS" }}
365+
{{/* azure.resourcegroup.name is the node's group, not the cluster's: AKS nodes live in an
366+
auto-generated MC_<clusterResourceGroup>_<cluster>_<region> group. */}}
367+
- set(resource.attributes["_tmp.azure.resourcegroup.name"], resource.attributes["azure.resourcegroup.name"])
368+
where resource.attributes["azure.resourcegroup.name"] != nil
369+
- replace_pattern(resource.attributes["_tmp.azure.resourcegroup.name"], "^MC_(.+)_{{ .Values.clusterName }}_[^_]+$", "$$$1")
370+
- set(resource.attributes["cloud.resource_id"], Concat(["/subscriptions/", resource.attributes["cloud.account.id"], "/resourceGroups/", resource.attributes["_tmp.azure.resourcegroup.name"], "/providers/Microsoft.ContainerService/managedClusters/", resource.attributes["k8s.cluster.name"]], ""))
371+
where resource.attributes["cloud.account.id"] != nil and resource.attributes["_tmp.azure.resourcegroup.name"] != nil and resource.attributes["k8s.cluster.name"] != nil
372+
- delete_key(resource.attributes, "_tmp.azure.resourcegroup.name")
373+
{{- else }}
343374
- set(resource.attributes["cloud.resource_id"], Concat(["arn:aws:eks:", resource.attributes["cloud.region"], ":", resource.attributes["cloud.account.id"], ":cluster/", resource.attributes["k8s.cluster.name"]], ""))
344375
where resource.attributes["cloud.region"] != nil and resource.attributes["cloud.account.id"] != nil and resource.attributes["k8s.cluster.name"] != nil
376+
{{- end }}
345377

346378
batch/cw_k8s_ci_v0_cwotel:
347379
send_batch_size: 500

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,26 @@ processors:
374374
- set(resource.attributes["k8s.node.name"], attributes["node_name"]) where attributes["node_name"] != nil
375375
376376
resourcedetection/cw_k8s_ci_v0:
377+
{{- if eq .Values.k8sMode "AKS" }}
378+
detectors: [aks, azure]
379+
aks:
380+
resource_attributes:
381+
cloud.platform: { enabled: true }
382+
cloud.provider: { enabled: true }
383+
k8s.cluster.name: { enabled: false }
384+
azure:
385+
resource_attributes:
386+
azure.resourcegroup.name: { enabled: true }
387+
azure.vm.name: { enabled: true }
388+
azure.vm.scaleset.name: { enabled: true }
389+
azure.vm.size: { enabled: true }
390+
cloud.account.id: { enabled: true }
391+
cloud.platform: { enabled: true }
392+
cloud.provider: { enabled: true }
393+
cloud.region: { enabled: true }
394+
host.id: { enabled: true }
395+
host.name: { enabled: true }
396+
{{- else }}
377397
detectors: [eks, ec2]
378398
ec2:
379399
resource_attributes:
@@ -386,6 +406,7 @@ processors:
386406
cloud.region: { enabled: true }
387407
cloud.availability_zone: { enabled: true }
388408
cloud.account.id: { enabled: true }
409+
{{- end }}
389410
390411
transform/cw_k8s_ci_v0_clear_schema_url:
391412
error_mode: ignore
@@ -464,8 +485,19 @@ processors:
464485
metric_statements:
465486
- context: resource
466487
statements:
488+
{{- if eq .Values.k8sMode "AKS" }}
489+
{{/* azure.resourcegroup.name is the node's group, not the cluster's: AKS nodes live in an
490+
auto-generated MC_<clusterResourceGroup>_<cluster>_<region> group. */}}
491+
- set(resource.attributes["_tmp.azure.resourcegroup.name"], resource.attributes["azure.resourcegroup.name"])
492+
where resource.attributes["azure.resourcegroup.name"] != nil
493+
- replace_pattern(resource.attributes["_tmp.azure.resourcegroup.name"], "^MC_(.+)_{{ .Values.clusterName }}_[^_]+$", "$$$1")
494+
- set(resource.attributes["cloud.resource_id"], Concat(["/subscriptions/", resource.attributes["cloud.account.id"], "/resourceGroups/", resource.attributes["_tmp.azure.resourcegroup.name"], "/providers/Microsoft.ContainerService/managedClusters/", resource.attributes["k8s.cluster.name"]], ""))
495+
where resource.attributes["cloud.account.id"] != nil and resource.attributes["_tmp.azure.resourcegroup.name"] != nil and resource.attributes["k8s.cluster.name"] != nil
496+
- delete_key(resource.attributes, "_tmp.azure.resourcegroup.name")
497+
{{- else }}
467498
- set(resource.attributes["cloud.resource_id"], Concat(["arn:aws:eks:", resource.attributes["cloud.region"], ":", resource.attributes["cloud.account.id"], ":cluster/", resource.attributes["k8s.cluster.name"]], ""))
468499
where resource.attributes["cloud.region"] != nil and resource.attributes["cloud.account.id"] != nil and resource.attributes["k8s.cluster.name"] != nil
500+
{{- end }}
469501

470502
metricstarttime/cw_k8s_ci_v0:
471503

@@ -486,6 +518,11 @@ processors:
486518
- set(resource.attributes["k8s.workload.type"], "CronJob") where resource.attributes["k8s.cronjob.name"] != nil and resource.attributes["k8s.workload.type"] == nil
487519
- 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
488520
- set(resource.attributes["k8s.workload.type"], "ReplicaSet") where resource.attributes["k8s.replicaset.name"] != nil and resource.attributes["k8s.workload.type"] == nil
521+
{{- if eq .Values.k8sMode "AKS" }}
522+
- set(resource.attributes["service.name"], resource.attributes["k8s.workload.name"]) where resource.attributes["service.name"] == nil and resource.attributes["k8s.workload.name"] != nil
523+
- set(resource.attributes["service.namespace"], resource.attributes["k8s.namespace.name"]) where resource.attributes["service.namespace"] == nil and resource.attributes["k8s.namespace.name"] != nil
524+
- set(resource.attributes["deployment.environment.name"], Concat([resource.attributes["cloud.platform"], Concat([resource.attributes["k8s.cluster.name"], resource.attributes["k8s.namespace.name"]], "/")], ":")) where resource.attributes["deployment.environment.name"] == nil and resource.attributes["cloud.platform"] != nil and resource.attributes["k8s.cluster.name"] != nil and resource.attributes["k8s.namespace.name"] != nil
525+
{{- end }}
489526

490527
batch/cw_k8s_ci_v0_metrics_dest:
491528
send_batch_size: 500
@@ -667,8 +704,13 @@ processors:
667704
- set(attributes["k8s.workload.name"], attributes["k8s.replicaset.name"]) where attributes["k8s.workload.name"] == nil and attributes["k8s.replicaset.name"] != nil
668705
- set(attributes["k8s.workload.type"], "ReplicaSet") where attributes["k8s.replicaset.name"] != nil and attributes["k8s.workload.type"] == nil
669706
# Derive service.name from k8s.workload.name (OTEL logs semconv).
670-
# Logs need service.name; metrics use k8s.workload.name directly.
707+
# Logs need service.name; metrics use k8s.workload.name directly, except on
708+
# AKS — see transform/cw_k8s_ci_v0_set_workload.
671709
- set(attributes["service.name"], attributes["k8s.workload.name"]) where attributes["service.name"] == nil and attributes["k8s.workload.name"] != nil
710+
{{- if eq .Values.k8sMode "AKS" }}
711+
- set(attributes["service.namespace"], attributes["k8s.namespace.name"]) where attributes["service.namespace"] == nil and attributes["k8s.namespace.name"] != nil
712+
- set(attributes["deployment.environment.name"], Concat([attributes["cloud.platform"], Concat([attributes["k8s.cluster.name"], attributes["k8s.namespace.name"]], "/")], ":")) where attributes["deployment.environment.name"] == nil and attributes["cloud.platform"] != nil and attributes["k8s.cluster.name"] != nil and attributes["k8s.namespace.name"] != nil
713+
{{- end }}
672714

673715
transform/cw_k8s_ci_v0_logs_set_cluster_and_node:
674716
error_mode: ignore
@@ -683,8 +725,18 @@ processors:
683725
log_statements:
684726
- context: resource
685727
statements:
728+
{{- if eq .Values.k8sMode "AKS" }}
729+
{{/* Node group -> cluster group, as in transform/cw_k8s_ci_v0_set_cloud_resource_id. */}}
730+
- set(attributes["_tmp.azure.resourcegroup.name"], attributes["azure.resourcegroup.name"])
731+
where attributes["azure.resourcegroup.name"] != nil
732+
- replace_pattern(attributes["_tmp.azure.resourcegroup.name"], "^MC_(.+)_{{ .Values.clusterName }}_[^_]+$", "$$$1")
733+
- set(attributes["cloud.resource_id"], Concat(["/subscriptions/", attributes["cloud.account.id"], "/resourceGroups/", attributes["_tmp.azure.resourcegroup.name"], "/providers/Microsoft.ContainerService/managedClusters/", attributes["k8s.cluster.name"]], ""))
734+
where attributes["cloud.account.id"] != nil and attributes["_tmp.azure.resourcegroup.name"] != nil and attributes["k8s.cluster.name"] != nil
735+
- delete_key(attributes, "_tmp.azure.resourcegroup.name")
736+
{{- else }}
686737
- set(attributes["cloud.resource_id"], Concat(["arn:aws:eks:", attributes["cloud.region"], ":", attributes["cloud.account.id"], ":cluster/", attributes["k8s.cluster.name"]], ""))
687738
where attributes["cloud.region"] != nil and attributes["cloud.account.id"] != nil and attributes["k8s.cluster.name"] != nil
739+
{{- end }}
688740

689741
transform/cw_k8s_ci_v0_logs_clear_schema_url:
690742
error_mode: ignore
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
module "base" {
5+
source = "../.."
6+
helm_values_file = "${path.module}/values.yaml"
7+
helm_dir = var.helm_dir
8+
}
9+
10+
resource "null_resource" "validator" {
11+
depends_on = [module.base.helm_release]
12+
13+
provisioner "local-exec" {
14+
command = "go test ${var.test_dir} -v -run=TestAKSOtelContainerInsights"
15+
}
16+
}
17+
18+
variable "test_dir" {
19+
type = string
20+
default = "../../../../validations/minikube/scenarios"
21+
}
22+
23+
variable "helm_dir" {
24+
type = string
25+
default = "../../../../../../charts/amazon-cloudwatch-observability"
26+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
k8sMode: AKS
2+
# roleArn is required when k8sMode is AKS. The agent pods will not become healthy on minikube
3+
# (no Azure IMDS / workload identity), but the AmazonCloudWatchAgent CRs are rendered by the chart
4+
# and applied by helm regardless — the operator does not gate the helm release on pod readiness —
5+
# so the test validates the AKS-specific config baked into the CRs.
6+
roleArn: arn:aws:iam::123456789012:role/CloudWatchAgentServerRole
7+
region: us-east-1
8+
clusterName: minikube
9+
# Exercise the OTEL CI path (metrics + logs), which is where the AKS resource-detection and
10+
# cloud.resource_id derivation live.
11+
otelContainerInsights:
12+
enabled: true
13+
logs:
14+
enabled: true

0 commit comments

Comments
 (0)