Skip to content

Commit e08282e

Browse files
odubajDTChrsMark
authored andcommitted
[processor/resourcedetection] introduce kubeadm detector (open-telemetry#35450)
**Description:** <Describe what has changed.> <!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> - introduce `kubeadm` detector to detect local cluster name **Link to tracking Issue:** open-telemetry#35116 --------- Signed-off-by: odubajDT <[email protected]> Co-authored-by: Christos Markou <[email protected]>
1 parent d27ea62 commit e08282e

File tree

20 files changed

+615
-0
lines changed

20 files changed

+615
-0
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: resourcedetectionprocessor
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "Introduce kubeadm detector to retrieve local cluster name."
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: [35116]
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: []
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package kubeadm // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders/kubeadm"
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/client-go/kubernetes"
12+
13+
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig"
14+
)
15+
16+
type Provider interface {
17+
// ClusterName returns the current K8S cluster name
18+
ClusterName(ctx context.Context) (string, error)
19+
}
20+
21+
type LocalCache struct {
22+
ClusterName string
23+
}
24+
25+
type kubeadmProvider struct {
26+
kubeadmClient kubernetes.Interface
27+
configMapName string
28+
configMapNamespace string
29+
cache LocalCache
30+
}
31+
32+
func NewProvider(configMapName string, configMapNamespace string, apiConf k8sconfig.APIConfig) (Provider, error) {
33+
k8sAPIClient, err := k8sconfig.MakeClient(apiConf)
34+
if err != nil {
35+
return nil, fmt.Errorf("failed to create K8s API client: %w", err)
36+
}
37+
return &kubeadmProvider{
38+
kubeadmClient: k8sAPIClient,
39+
configMapName: configMapName,
40+
configMapNamespace: configMapNamespace,
41+
}, nil
42+
}
43+
44+
func (k *kubeadmProvider) ClusterName(ctx context.Context) (string, error) {
45+
if k.cache.ClusterName != "" {
46+
return k.cache.ClusterName, nil
47+
}
48+
configmap, err := k.kubeadmClient.CoreV1().ConfigMaps(k.configMapNamespace).Get(ctx, k.configMapName, metav1.GetOptions{})
49+
if err != nil {
50+
return "", fmt.Errorf("failed to fetch ConfigMap with name %s and namespace %s from K8s API: %w", k.configMapName, k.configMapNamespace, err)
51+
}
52+
53+
k.cache.ClusterName = configmap.Data["clusterName"]
54+
55+
return k.cache.ClusterName, nil
56+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package kubeadm
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
corev1 "k8s.io/api/core/v1"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
"k8s.io/client-go/kubernetes/fake"
14+
15+
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig"
16+
)
17+
18+
func TestNewProvider(t *testing.T) {
19+
// set k8s cluster env variables to make the API client happy
20+
t.Setenv("KUBERNETES_SERVICE_HOST", "127.0.0.1")
21+
t.Setenv("KUBERNETES_SERVICE_PORT", "6443")
22+
23+
_, err := NewProvider("name", "ns", k8sconfig.APIConfig{AuthType: k8sconfig.AuthTypeNone})
24+
assert.NoError(t, err)
25+
}
26+
27+
func TestClusterName(t *testing.T) {
28+
client := fake.NewSimpleClientset()
29+
err := setupConfigMap(client)
30+
assert.NoError(t, err)
31+
32+
tests := []struct {
33+
testName string
34+
CMname string
35+
CMnamespace string
36+
clusterName string
37+
errMsg string
38+
}{
39+
{
40+
testName: "valid",
41+
CMname: "cm",
42+
CMnamespace: "ns",
43+
clusterName: "myClusterName",
44+
errMsg: "",
45+
},
46+
{
47+
testName: "configmap not found",
48+
CMname: "cm2",
49+
CMnamespace: "ns",
50+
errMsg: "failed to fetch ConfigMap with name cm2 and namespace ns from K8s API: configmaps \"cm2\" not found",
51+
},
52+
}
53+
54+
for _, tt := range tests {
55+
t.Run(tt.testName, func(t *testing.T) {
56+
kubeadmP := &kubeadmProvider{
57+
kubeadmClient: client,
58+
configMapName: tt.CMname,
59+
configMapNamespace: tt.CMnamespace,
60+
}
61+
clusterName, err := kubeadmP.ClusterName(context.Background())
62+
if tt.errMsg != "" {
63+
assert.EqualError(t, err, tt.errMsg)
64+
} else {
65+
assert.NoError(t, err)
66+
assert.Equal(t, clusterName, tt.clusterName)
67+
}
68+
})
69+
}
70+
}
71+
72+
func setupConfigMap(client *fake.Clientset) error {
73+
cm := &corev1.ConfigMap{
74+
ObjectMeta: metav1.ObjectMeta{
75+
Name: "cm",
76+
Namespace: "ns",
77+
},
78+
Data: map[string]string{
79+
"clusterName": "myClusterName",
80+
},
81+
}
82+
_, err := client.CoreV1().ConfigMaps("ns").Create(context.Background(), cm, metav1.CreateOptions{})
83+
if err != nil {
84+
return err
85+
}
86+
return nil
87+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package kubeadm
5+
6+
import (
7+
"testing"
8+
9+
"go.uber.org/goleak"
10+
)
11+
12+
func TestMain(m *testing.M) {
13+
goleak.VerifyTestMain(m)
14+
}

processor/resourcedetectionprocessor/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,43 @@ processors:
426426
override: false
427427
```
428428

429+
### Kubeadm Metadata
430+
431+
Queries the K8S API server to retrieve kubeadm resource attributes:
432+
433+
The list of the populated resource attributes can be found at [kubeadm Detector Resource Attributes](./internal/kubeadm/documentation.md).
434+
435+
The following permissions are required:
436+
```yaml
437+
kind: Role
438+
metadata:
439+
name: otel-collector
440+
namespace: kube-system
441+
rules:
442+
- apiGroups: [""]
443+
resources: ["configmaps"]
444+
resourceNames: ["kubeadm-config"]
445+
verbs: ["get"]
446+
---
447+
apiVersion: rbac.authorization.k8s.io/v1
448+
kind: RoleBinding
449+
metadata:
450+
name: otel-collector-rolebinding
451+
namespace: kube-system
452+
subjects:
453+
- kind: ServiceAccount
454+
name: default
455+
namespace: default
456+
roleRef:
457+
kind: Role
458+
name: otel-collector
459+
apiGroup: rbac.authorization.k8s.io
460+
```
461+
462+
| Name | Type | Required | Default | Docs |
463+
| ---- | ---- |----------|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
464+
| auth_type | string | No | `serviceAccount` | How to authenticate to the K8s API server. This can be one of `none` (for no auth), `serviceAccount` (to use the standard service account token provided to the agent pod), or `kubeConfig` to use credentials from `~/.kube/config`. |
465+
429466
### K8S Node Metadata
430467

431468
Queries the K8S api server to retrieve node resource attributes.

processor/resourcedetectionprocessor/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp"
2020
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku"
2121
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/k8snode"
22+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/kubeadm"
2223
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift"
2324
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system"
2425
)
@@ -85,6 +86,9 @@ type DetectorConfig struct {
8586

8687
// K8SNode contains user-specified configurations for the K8SNode detector
8788
K8SNodeConfig k8snode.Config `mapstructure:"k8snode"`
89+
90+
// Kubeadm contains user-specified configurations for the Kubeadm detector
91+
KubeadmConfig kubeadm.Config `mapstructure:"kubeadm"`
8892
}
8993

9094
func detectorCreateDefaultConfig() DetectorConfig {
@@ -103,6 +107,7 @@ func detectorCreateDefaultConfig() DetectorConfig {
103107
SystemConfig: system.CreateDefaultConfig(),
104108
OpenShiftConfig: openshift.CreateDefaultConfig(),
105109
K8SNodeConfig: k8snode.CreateDefaultConfig(),
110+
KubeadmConfig: kubeadm.CreateDefaultConfig(),
106111
}
107112
}
108113

@@ -136,6 +141,8 @@ func (d *DetectorConfig) GetConfigFromType(detectorType internal.DetectorType) i
136141
return d.OpenShiftConfig
137142
case k8snode.TypeStr:
138143
return d.K8SNodeConfig
144+
case kubeadm.TypeStr:
145+
return d.KubeadmConfig
139146
default:
140147
return nil
141148
}

processor/resourcedetectionprocessor/doc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//go:generate mdatagen internal/openshift/metadata.yaml
1717
//go:generate mdatagen internal/system/metadata.yaml
1818
//go:generate mdatagen internal/k8snode/metadata.yaml
19+
//go:generate mdatagen internal/kubeadm/metadata.yaml
1920

2021
// package resourcedetectionprocessor implements a processor
2122
// which can be used to detect resource information from the host,

processor/resourcedetectionprocessor/factory.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp"
3333
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku"
3434
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/k8snode"
35+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/kubeadm"
3536
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/metadata"
3637
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift"
3738
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system"
@@ -66,6 +67,7 @@ func NewFactory() processor.Factory {
6667
system.TypeStr: system.NewDetector,
6768
openshift.TypeStr: openshift.NewDetector,
6869
k8snode.TypeStr: k8snode.NewDetector,
70+
kubeadm.TypeStr: kubeadm.NewDetector,
6971
})
7072

7173
f := &factory{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package kubeadm // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/kubeadm"
5+
6+
import (
7+
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig"
8+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/kubeadm/internal/metadata"
9+
)
10+
11+
type Config struct {
12+
k8sconfig.APIConfig `mapstructure:",squash"`
13+
ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"`
14+
}
15+
16+
func CreateDefaultConfig() Config {
17+
return Config{
18+
APIConfig: k8sconfig.APIConfig{AuthType: k8sconfig.AuthTypeServiceAccount},
19+
ResourceAttributes: metadata.DefaultResourceAttributesConfig(),
20+
}
21+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
2+
3+
# resourcedetectionprocessor/kubeadm
4+
5+
**Parent Component:** resourcedetection
6+
7+
## Resource Attributes
8+
9+
| Name | Description | Values | Enabled |
10+
| ---- | ----------- | ------ | ------- |
11+
| k8s.cluster.name | The Kubernetes cluster name | Any Str | true |

processor/resourcedetectionprocessor/internal/kubeadm/generated_package_test.go

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

processor/resourcedetectionprocessor/internal/kubeadm/internal/metadata/generated_config.go

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)