Skip to content

Commit 6b9e959

Browse files
authored
[processor/k8sattributes] support extracting labels and annotations from Deployments (#38343)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Add support for extraction of labels and annotations from Deployments. This change comes with elevated RBAC permissions - adding Deployment permissions to the ClusterRole <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes #37957 --------- Signed-off-by: odubajDT <[email protected]>
1 parent 6e092c1 commit 6b9e959

20 files changed

+721
-176
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: processor/k8sattributes
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "Support extracting labels and annotations from k8s Deployments"
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [37957]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

processor/k8sattributesprocessor/README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,12 @@ wait_for_metadata_timeout: 10s
227227

228228
## Extracting attributes from pod labels and annotations
229229

230-
The k8sattributesprocessor can also set resource attributes from k8s labels and annotations of pods, namespaces and nodes.
231-
The config for associating the data passing through the processor (spans, metrics and logs) with specific Pod/Namespace/Node annotations/labels is configured via "annotations" and "labels" keys.
232-
This config represents a list of annotations/labels that are extracted from pods/namespaces/nodes and added to spans, metrics and logs.
230+
The k8sattributesprocessor can also set resource attributes from k8s labels and annotations of pods, namespaces, deployments and nodes.
231+
The config for associating the data passing through the processor (spans, metrics and logs) with specific Pod/Namespace/Deployment/Node annotations/labels is configured via "annotations" and "labels" keys.
232+
This config represents a list of annotations/labels that are extracted from pods/namespaces/deployments/nodes and added to spans, metrics and logs.
233233
Each item is specified as a config of tag_name (representing the tag name to tag the spans with),
234234
key (representing the key used to extract value) and from (representing the kubernetes object used to extract the value).
235-
The "from" field has only three possible values "pod", "namespace" and "node" and defaults to "pod" if none is specified.
235+
The "from" field has only three possible values "pod", "namespace", "deployment" and "node" and defaults to "pod" if none is specified.
236236

237237
A few examples to use this config are as follows:
238238

@@ -344,7 +344,7 @@ rules:
344344
resources: ["pods", "namespaces", "nodes"]
345345
verbs: ["get", "watch", "list"]
346346
- apiGroups: ["apps"]
347-
resources: ["replicasets"]
347+
resources: ["replicasets", "deployments"]
348348
verbs: ["get", "list", "watch"]
349349
- apiGroups: ["extensions"]
350350
resources: ["replicasets"]
@@ -373,6 +373,8 @@ k8sattributes:
373373
```
374374
With the namespace filter set, the processor will only look up pods and replicasets in the selected namespace. Note that with just a role binding, the processor cannot query metadata such as labels and annotations from k8s `nodes` and `namespaces` which are cluster-scoped objects. This also means that the processor cannot set the value for `k8s.cluster.uid` attribute if enabled, since the `k8s.cluster.uid` attribute is set to the uid of the namespace `kube-system` which is not queryable with namespaced rbac.
375375

376+
Please note, when extracting the workload related attributes, these workloads need to be present in the `Role` with the correct permissions. For example, an extraction of `k8s.deployment.label.*` attributes, `deployments` need to be present in `Role`.
377+
376378
Example `Role` and `RoleBinding` to create in the namespace being watched.
377379
```yaml
378380
apiVersion: v1
@@ -391,7 +393,7 @@ rules:
391393
resources: ["pods"]
392394
verbs: ["get", "watch", "list"]
393395
- apiGroups: ["apps"]
394-
resources: ["replicasets"]
396+
resources: ["replicasets", "deployments"]
395397
verbs: ["get", "list", "watch"]
396398
---
397399
apiVersion: rbac.authorization.k8s.io/v1

processor/k8sattributesprocessor/client_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type fakeClient struct {
2828
NodeInformer cache.SharedInformer
2929
Namespaces map[string]*kube.Namespace
3030
Nodes map[string]*kube.Node
31+
Deployments map[string]*kube.Deployment
3132
StopCh chan struct{}
3233
}
3334

@@ -37,7 +38,7 @@ func selectors() (labels.Selector, fields.Selector) {
3738
}
3839

3940
// newFakeClient instantiates a new FakeClient object and satisfies the ClientProvider type
40-
func newFakeClient(_ component.TelemetrySettings, _ k8sconfig.APIConfig, rules kube.ExtractionRules, filters kube.Filters, associations []kube.Association, _ kube.Excludes, _ kube.APIClientsetProvider, _ kube.InformerProvider, _ kube.InformerProviderNamespace, _ kube.InformerProviderReplicaSet, _ bool, _ time.Duration) (kube.Client, error) {
41+
func newFakeClient(_ component.TelemetrySettings, _ k8sconfig.APIConfig, rules kube.ExtractionRules, filters kube.Filters, associations []kube.Association, _ kube.Excludes, _ kube.APIClientsetProvider, _ kube.InformersFactoryList, _ bool, _ time.Duration) (kube.Client, error) {
4142
cs := fake.NewSimpleClientset()
4243

4344
ls, fs := selectors()
@@ -71,6 +72,11 @@ func (f *fakeClient) GetNode(nodeName string) (*kube.Node, bool) {
7172
return node, ok
7273
}
7374

75+
func (f *fakeClient) GetDeployment(deploymentUID string) (*kube.Deployment, bool) {
76+
d, ok := f.Deployments[deploymentUID]
77+
return d, ok
78+
}
79+
7480
// Start is a noop for FakeClient.
7581
func (f *fakeClient) Start() error {
7682
if f.Informer != nil {

processor/k8sattributesprocessor/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ func (cfg *Config) Validate() error {
7575
}
7676

7777
switch f.From {
78-
case "", kube.MetadataFromPod, kube.MetadataFromNamespace, kube.MetadataFromNode:
78+
case "", kube.MetadataFromPod, kube.MetadataFromNamespace, kube.MetadataFromNode, kube.MetadataFromDeployment:
7979
default:
80-
return fmt.Errorf("%s is not a valid choice for From. Must be one of: pod, namespace, node", f.From)
80+
return fmt.Errorf("%s is not a valid choice for From. Must be one of: pod, namespace, deployment, node", f.From)
8181
}
8282

8383
if f.KeyRegex != "" {

0 commit comments

Comments
 (0)