Skip to content

Commit c8cf780

Browse files
authored
[receiver/k8s_cluster] Do not store unused data in k8s API cache (part 2) (open-telemetry#23432)
Do not store unused data for deployments, statefulsets and daemonsets in k8s API cache to reduce RAM usage. Updates open-telemetry#23433
1 parent 0ccde43 commit c8cf780

15 files changed

+378
-41
lines changed

.chloggen/k8scluster-dont-store-unused-data-cache.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ component: receiver/k8s_cluster
1212
note: Do not store unused data in the k8s API cache to reduce RAM usage
1313

1414
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
15-
issues: [23417]
15+
issues: [23433]

receiver/k8sclusterreceiver/informer_transform.go

+9
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import (
88
batchv1 "k8s.io/api/batch/v1"
99
corev1 "k8s.io/api/core/v1"
1010

11+
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/demonset"
12+
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/deployment"
1113
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/jobs"
1214
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/node"
1315
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/pod"
1416
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/replicaset"
17+
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/statefulset"
1518
)
1619

1720
// transformObject transforms the k8s object by removing the data that is not utilized by the receiver.
@@ -26,6 +29,12 @@ func transformObject(object interface{}) (interface{}, error) {
2629
return replicaset.Transform(o), nil
2730
case *batchv1.Job:
2831
return jobs.Transform(o), nil
32+
case *appsv1.Deployment:
33+
return deployment.Transform(o), nil
34+
case *appsv1.DaemonSet:
35+
return demonset.Transform(o), nil
36+
case *appsv1.StatefulSet:
37+
return statefulset.Transform(o), nil
2938
}
3039
return object, nil
3140
}

receiver/k8sclusterreceiver/informer_transform_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"testing"
88

99
"github.com/stretchr/testify/assert"
10+
appsv1 "k8s.io/api/apps/v1"
1011
corev1 "k8s.io/api/core/v1"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1113

1214
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/testutils"
1315
)
@@ -58,6 +60,39 @@ func TestTransformObject(t *testing.T) {
5860
want: testutils.NewJob("1"),
5961
same: false,
6062
},
63+
{
64+
name: "deployment",
65+
object: testutils.NewDeployment("1"),
66+
want: testutils.NewDeployment("1"),
67+
same: false,
68+
},
69+
{
70+
name: "daemonset",
71+
object: testutils.NewDaemonset("1"),
72+
want: testutils.NewDaemonset("1"),
73+
same: false,
74+
},
75+
{
76+
name: "statefulset",
77+
object: &appsv1.StatefulSet{
78+
Spec: appsv1.StatefulSetSpec{
79+
Replicas: func() *int32 { i := int32(3); return &i }(),
80+
Template: corev1.PodTemplateSpec{
81+
ObjectMeta: metav1.ObjectMeta{
82+
Labels: map[string]string{
83+
"app": "my-app",
84+
},
85+
},
86+
},
87+
},
88+
},
89+
want: &appsv1.StatefulSet{
90+
Spec: appsv1.StatefulSetSpec{
91+
Replicas: func() *int32 { i := int32(3); return &i }(),
92+
},
93+
},
94+
same: false,
95+
},
6196
{
6297
// This is a case where we don't transform the object.
6398
name: "hpa",

receiver/k8sclusterreceiver/internal/demonset/daemonsets.go

+14
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ var daemonSetReadyMetric = &metricspb.MetricDescriptor{
4444
Type: metricspb.MetricDescriptor_GAUGE_INT64,
4545
}
4646

47+
// Transform transforms the pod to remove the fields that we don't use to reduce RAM utilization.
48+
// IMPORTANT: Make sure to update this function before using new daemonset fields.
49+
func Transform(ds *appsv1.DaemonSet) *appsv1.DaemonSet {
50+
return &appsv1.DaemonSet{
51+
ObjectMeta: metadata.TransformObjectMeta(ds.ObjectMeta),
52+
Status: appsv1.DaemonSetStatus{
53+
CurrentNumberScheduled: ds.Status.CurrentNumberScheduled,
54+
DesiredNumberScheduled: ds.Status.DesiredNumberScheduled,
55+
NumberMisscheduled: ds.Status.NumberMisscheduled,
56+
NumberReady: ds.Status.NumberReady,
57+
},
58+
}
59+
}
60+
4761
func GetMetrics(ds *appsv1.DaemonSet) []*agentmetricspb.ExportMetricsServiceRequest {
4862
metrics := []*metricspb.Metric{
4963
{

receiver/k8sclusterreceiver/internal/demonset/daemonsets_test.go

+74
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import (
77
"testing"
88

99
metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
10+
"github.com/stretchr/testify/assert"
1011
"github.com/stretchr/testify/require"
12+
appsv1 "k8s.io/api/apps/v1"
13+
corev1 "k8s.io/api/core/v1"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1115

1216
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/constants"
1317
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/testutils"
@@ -42,3 +46,73 @@ func TestDaemonsetMetrics(t *testing.T) {
4246
testutils.AssertMetricsInt(t, rm.Metrics[3], "k8s.daemonset.ready_nodes",
4347
metricspb.MetricDescriptor_GAUGE_INT64, 2)
4448
}
49+
50+
func TestTransform(t *testing.T) {
51+
originalDS := &appsv1.DaemonSet{
52+
ObjectMeta: metav1.ObjectMeta{
53+
Name: "my-daemonset",
54+
Namespace: "default",
55+
Labels: map[string]string{
56+
"app": "my-app",
57+
},
58+
},
59+
Spec: appsv1.DaemonSetSpec{
60+
Selector: &metav1.LabelSelector{
61+
MatchLabels: map[string]string{
62+
"app": "my-app",
63+
},
64+
},
65+
Template: corev1.PodTemplateSpec{
66+
ObjectMeta: metav1.ObjectMeta{
67+
Labels: map[string]string{
68+
"app": "my-app",
69+
},
70+
},
71+
Spec: corev1.PodSpec{
72+
Containers: []corev1.Container{
73+
{
74+
Name: "my-container",
75+
Image: "nginx:latest",
76+
ImagePullPolicy: corev1.PullAlways,
77+
Ports: []corev1.ContainerPort{
78+
{
79+
Name: "http",
80+
ContainerPort: 80,
81+
Protocol: corev1.ProtocolTCP,
82+
},
83+
},
84+
},
85+
},
86+
},
87+
},
88+
},
89+
Status: appsv1.DaemonSetStatus{
90+
CurrentNumberScheduled: 3,
91+
NumberReady: 3,
92+
DesiredNumberScheduled: 3,
93+
NumberMisscheduled: 0,
94+
Conditions: []appsv1.DaemonSetCondition{
95+
{
96+
Type: "Available",
97+
Status: corev1.ConditionTrue,
98+
},
99+
},
100+
},
101+
}
102+
wantDS := &appsv1.DaemonSet{
103+
ObjectMeta: metav1.ObjectMeta{
104+
Name: "my-daemonset",
105+
Namespace: "default",
106+
Labels: map[string]string{
107+
"app": "my-app",
108+
},
109+
},
110+
Status: appsv1.DaemonSetStatus{
111+
CurrentNumberScheduled: 3,
112+
NumberReady: 3,
113+
DesiredNumberScheduled: 3,
114+
NumberMisscheduled: 0,
115+
},
116+
}
117+
assert.Equal(t, wantDS, Transform(originalDS))
118+
}

receiver/k8sclusterreceiver/internal/deployment/deployments.go

+14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ import (
1818
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata"
1919
)
2020

21+
// Transform transforms the pod to remove the fields that we don't use to reduce RAM utilization.
22+
// IMPORTANT: Make sure to update this function before using new deployment fields.
23+
func Transform(deployment *appsv1.Deployment) *appsv1.Deployment {
24+
return &appsv1.Deployment{
25+
ObjectMeta: metadata.TransformObjectMeta(deployment.ObjectMeta),
26+
Spec: appsv1.DeploymentSpec{
27+
Replicas: deployment.Spec.Replicas,
28+
},
29+
Status: appsv1.DeploymentStatus{
30+
AvailableReplicas: deployment.Status.AvailableReplicas,
31+
},
32+
}
33+
}
34+
2135
func GetMetrics(set receiver.CreateSettings, dep *appsv1.Deployment) pmetric.Metrics {
2236
mb := imetadata.NewMetricsBuilder(imetadata.DefaultMetricsBuilderConfig(), set)
2337
ts := pcommon.NewTimestampFromTime(time.Now())

receiver/k8sclusterreceiver/internal/deployment/deployments_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import (
1111
"github.com/stretchr/testify/require"
1212
"go.opentelemetry.io/collector/pdata/pmetric"
1313
"go.opentelemetry.io/collector/receiver/receivertest"
14+
appsv1 "k8s.io/api/apps/v1"
15+
v1 "k8s.io/api/core/v1"
16+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1417

1518
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/golden"
1619
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest"
@@ -61,3 +64,75 @@ func TestGoldenFile(t *testing.T) {
6164
),
6265
)
6366
}
67+
68+
func TestTransform(t *testing.T) {
69+
origDeployment := &appsv1.Deployment{
70+
ObjectMeta: metav1.ObjectMeta{
71+
Name: "my-deployment",
72+
UID: "my-deployment-uid",
73+
Namespace: "default",
74+
Labels: map[string]string{
75+
"app": "my-app",
76+
},
77+
},
78+
Spec: appsv1.DeploymentSpec{
79+
Replicas: func() *int32 { replicas := int32(3); return &replicas }(),
80+
Selector: &metav1.LabelSelector{
81+
MatchLabels: map[string]string{
82+
"app": "my-app",
83+
},
84+
},
85+
Template: v1.PodTemplateSpec{
86+
ObjectMeta: metav1.ObjectMeta{
87+
Labels: map[string]string{
88+
"app": "my-app",
89+
},
90+
},
91+
Spec: v1.PodSpec{
92+
Containers: []v1.Container{
93+
{
94+
Name: "my-container",
95+
Image: "nginx:latest",
96+
ImagePullPolicy: v1.PullAlways,
97+
Ports: []v1.ContainerPort{
98+
{
99+
Name: "http",
100+
ContainerPort: 80,
101+
Protocol: v1.ProtocolTCP,
102+
},
103+
},
104+
},
105+
},
106+
},
107+
},
108+
},
109+
Status: appsv1.DeploymentStatus{
110+
Replicas: 3,
111+
ReadyReplicas: 3,
112+
AvailableReplicas: 3,
113+
Conditions: []appsv1.DeploymentCondition{
114+
{
115+
Type: appsv1.DeploymentAvailable,
116+
Status: v1.ConditionTrue,
117+
},
118+
},
119+
},
120+
}
121+
wantDeployment := &appsv1.Deployment{
122+
ObjectMeta: metav1.ObjectMeta{
123+
Name: "my-deployment",
124+
UID: "my-deployment-uid",
125+
Namespace: "default",
126+
Labels: map[string]string{
127+
"app": "my-app",
128+
},
129+
},
130+
Spec: appsv1.DeploymentSpec{
131+
Replicas: func() *int32 { replicas := int32(3); return &replicas }(),
132+
},
133+
Status: appsv1.DeploymentStatus{
134+
AvailableReplicas: 3,
135+
},
136+
}
137+
assert.Equal(t, wantDeployment, Transform(origDeployment))
138+
}

receiver/k8sclusterreceiver/internal/jobs/jobs.go

+2-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1"
1010
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
1111
batchv1 "k8s.io/api/batch/v1"
12-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1312

1413
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/experimentalmetricmetadata"
1514
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/constants"
@@ -53,15 +52,10 @@ var podsSuccessfulMetric = &metricspb.MetricDescriptor{
5352
}
5453

5554
// Transform transforms the job to remove the fields that we don't use to reduce RAM utilization.
56-
// IMPORTANT: Make sure to update this function when using a new job fields.
55+
// IMPORTANT: Make sure to update this function before using new job fields.
5756
func Transform(job *batchv1.Job) *batchv1.Job {
5857
return &batchv1.Job{
59-
ObjectMeta: metav1.ObjectMeta{
60-
Name: job.ObjectMeta.Name,
61-
Namespace: job.ObjectMeta.Namespace,
62-
UID: job.ObjectMeta.UID,
63-
Labels: job.ObjectMeta.Labels,
64-
},
58+
ObjectMeta: metadata.TransformObjectMeta(job.ObjectMeta),
6559
Spec: batchv1.JobSpec{
6660
Completions: job.Spec.Completions,
6761
Parallelism: job.Spec.Parallelism,

receiver/k8sclusterreceiver/internal/metadata/metadata.go

+18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,24 @@ type KubernetesMetadata struct {
2626
Metadata map[string]string
2727
}
2828

29+
func TransformObjectMeta(om v1.ObjectMeta) v1.ObjectMeta {
30+
newOM := v1.ObjectMeta{
31+
Name: om.Name,
32+
Namespace: om.Namespace,
33+
UID: om.UID,
34+
CreationTimestamp: om.CreationTimestamp,
35+
Labels: om.Labels,
36+
}
37+
for _, or := range om.OwnerReferences {
38+
newOM.OwnerReferences = append(newOM.OwnerReferences, v1.OwnerReference{
39+
Kind: or.Kind,
40+
Name: or.Name,
41+
UID: or.UID,
42+
})
43+
}
44+
return newOM
45+
}
46+
2947
// GetGenericMetadata is responsible for collecting metadata from K8s resources that
3048
// live on v1.ObjectMeta.
3149
func GetGenericMetadata(om *v1.ObjectMeta, resourceType string) *KubernetesMetadata {

receiver/k8sclusterreceiver/internal/metadata/metadata_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,42 @@ func TestGetMetadataUpdate(t *testing.T) {
224224
})
225225
}
226226
}
227+
228+
func TestTransformObjectMeta(t *testing.T) {
229+
in := v1.ObjectMeta{
230+
Name: "my-pod",
231+
UID: "12345678-1234-1234-1234-123456789011",
232+
Namespace: "default",
233+
Labels: map[string]string{
234+
"app": "my-app",
235+
},
236+
Annotations: map[string]string{
237+
"version": "1.0",
238+
"description": "Sample resource",
239+
},
240+
OwnerReferences: []v1.OwnerReference{
241+
{
242+
APIVersion: "apps/v1",
243+
Kind: "ReplicaSet",
244+
Name: "my-replicaset-1",
245+
UID: "12345678-1234-1234-1234-123456789012",
246+
},
247+
},
248+
}
249+
want := v1.ObjectMeta{
250+
Name: "my-pod",
251+
UID: "12345678-1234-1234-1234-123456789011",
252+
Namespace: "default",
253+
Labels: map[string]string{
254+
"app": "my-app",
255+
},
256+
OwnerReferences: []v1.OwnerReference{
257+
{
258+
Kind: "ReplicaSet",
259+
Name: "my-replicaset-1",
260+
UID: "12345678-1234-1234-1234-123456789012",
261+
},
262+
},
263+
}
264+
assert.Equal(t, want, TransformObjectMeta(in))
265+
}

0 commit comments

Comments
 (0)