Repository: open-telemetry/opentelemetry-operator (2025-08-03T10:47:52Z)

Issue:
K8sattributes: Add automatic RBAC for new `service.name` resource attribute generator
The k8sattributes processor recently added support for automatic the `service.name` resource attribute:

* https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/39335

According to https://opentelemetry.io/docs/specs/semconv/non-normative/k8s-attributes/#how-servicename-should-be-calculated, the `service.name` is extract from the first of these attributes:

* pod.annotation[resource.opentelemetry.io/service.name]
* pod.label[app.kubernetes.io/instance]
* pod.label[app.kubernetes.io/name]
* k8s.deployment.name
* k8s.replicaset.name
* k8s.statefulset.name
* k8s.daemonset.name
* k8s.cronjob.name
* k8s.job.name
* k8s.pod.name
* k8s.container.name

This means that, if k8sprocessor has been configured with `service.name`, https://github.com/open-telemetry/opentelemetry-operator/blob/149d03c1b291be5bd3dd116783f443d4fc63c6fb/internal/components/processors/k8sattribute.go#L34 should automatically add RBAC for `replicasets` (to access `k8s.deployment.name`).


Discussion:
/assign



Patch:
diff --git a/.chloggen/rbac-for-service.name.yaml b/.chloggen/rbac-for-service.name.yaml
new file mode 100644
index 0000000000..1e008fe8b8
--- /dev/null
+++ b/.chloggen/rbac-for-service.name.yaml
@@ -0,0 +1,20 @@
+# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
+change_type: enhancement
+
+# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
+component: collector
+
+# A brief description of the change. Surround your text with quotes ("") if you need to start with a backtick (`).
+note: "k8sattributes: Add automatic RBAC for new service.name resource attribute generator"
+
+# One or more tracking issues related to the change
+issues: [4131]
+
+# (Optional) One or more lines of additional information to render under the primary note.
+# These lines will be padded with 2 spaces and then inserted directly into the document.
+# Use pipe (|) for multiline entries.
+subtext: |
+  The k8sattributes processor recently added support for automatic service.name resource attribute generation.
+  This change ensures that when service.name is configured in the k8sattributes processor, the operator
+  automatically adds the necessary RBAC rules for replicasets access, which is required for extracting
+  k8s.deployment.name.
\ No newline at end of file
diff --git a/internal/components/processors/k8sattribute.go b/internal/components/processors/k8sattribute.go
index 84a76c36e1..3e84d1de3a 100644
--- a/internal/components/processors/k8sattribute.go
+++ b/internal/components/processors/k8sattribute.go
@@ -53,7 +53,7 @@ func GenerateK8SAttrRbacRules(_ logr.Logger, config K8sAttributeConfig) ([]rbacv
 	addedReplicasetPolicy := false
 	for _, m := range config.Extract.Metadata {
 		metadataField := fmt.Sprint(m)
-		if (metadataField == "k8s.deployment.uid" || metadataField == "k8s.deployment.name") && !addedReplicasetPolicy {
+		if (metadataField == "k8s.deployment.uid" || metadataField == "k8s.deployment.name" || metadataField == "service.name") && !addedReplicasetPolicy {
 			prs = append(prs, replicasetPolicy)
 			addedReplicasetPolicy = true
 		} else if strings.Contains(metadataField, "k8s.node") {


Test patch:
diff --git a/internal/components/processors/k8sattribute_test.go b/internal/components/processors/k8sattribute_test.go
index 95db1c1b68..45eaf204fa 100644
--- a/internal/components/processors/k8sattribute_test.go
+++ b/internal/components/processors/k8sattribute_test.go
@@ -126,6 +126,31 @@ func TestGenerateK8SAttrRbacRules(t *testing.T) {
 			},
 			wantErr: assert.NoError,
 		},
+		{
+			name: "config with service.name metadata",
+			args: args{
+				config: map[string]interface{}{
+					"extract": map[string]interface{}{
+						"metadata":    []string{"service.name"},
+						"labels":      []interface{}{},
+						"annotations": []interface{}{},
+					},
+				},
+			},
+			want: []rbacv1.PolicyRule{
+				{
+					APIGroups: []string{""},
+					Resources: []string{"pods", "namespaces"},
+					Verbs:     []string{"get", "watch", "list"},
+				},
+				{
+					APIGroups: []string{"apps"},
+					Resources: []string{"replicasets"},
+					Verbs:     []string{"get", "watch", "list"},
+				},
+			},
+			wantErr: assert.NoError,
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/internal/manifests/collector/rbac_test.go b/internal/manifests/collector/rbac_test.go
index d80bd9ff45..d16f115d28 100644
--- a/internal/manifests/collector/rbac_test.go
+++ b/internal/manifests/collector/rbac_test.go
@@ -80,6 +80,22 @@ func TestDesiredClusterRoles(t *testing.T) {
 				},
 			},
 		},
+		{
+			desc:       "k8sattributes processor - service.name metadata",
+			configPath: "testdata/rbac_k8sattributes_service_name.yaml",
+			expectedRules: []rbacv1.PolicyRule{
+				{
+					APIGroups: []string{""},
+					Resources: []string{"pods", "namespaces"},
+					Verbs:     []string{"get", "watch", "list"},
+				},
+				{
+					APIGroups: []string{"apps"},
+					Resources: []string{"replicasets"},
+					Verbs:     []string{"get", "watch", "list"},
+				},
+			},
+		},
 	}
 
 	for _, test := range tests {
diff --git a/internal/manifests/collector/testdata/rbac_k8sattributes_service_name.yaml b/internal/manifests/collector/testdata/rbac_k8sattributes_service_name.yaml
new file mode 100644
index 0000000000..576219efab
--- /dev/null
+++ b/internal/manifests/collector/testdata/rbac_k8sattributes_service_name.yaml
@@ -0,0 +1,18 @@
+receivers:
+  otlp:
+    protocols:
+      grpc:
+processors:
+  k8sattributes:
+    extract:
+      metadata:
+        - service.name
+exporters:
+  otlp:
+    endpoint: "otlp:4317"
+service:
+  pipelines:
+    traces:
+      receivers: [otlp]
+      processors: [k8sattributes]
+      exporters: [otlp] 
\ No newline at end of file