Skip to content

Commit 151ede1

Browse files
committed
feat: Use PartialObjectMetadata for Configmaps
1 parent f8aa7d9 commit 151ede1

File tree

9 files changed

+150
-21
lines changed

9 files changed

+150
-21
lines changed

internal/store/builder.go

+65-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ import (
3838
policyv1 "k8s.io/api/policy/v1"
3939
rbacv1 "k8s.io/api/rbac/v1"
4040
storagev1 "k8s.io/api/storage/v1"
41+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4142
clientset "k8s.io/client-go/kubernetes"
43+
"k8s.io/client-go/metadata"
4244
"k8s.io/client-go/tools/cache"
4345
"k8s.io/klog/v2"
4446

@@ -65,9 +67,10 @@ var _ ksmtypes.BuilderInterface = &Builder{}
6567
// Builder helps to build store. It follows the builder pattern
6668
// (https://en.wikipedia.org/wiki/Builder_pattern).
6769
type Builder struct {
68-
kubeClient clientset.Interface
69-
customResourceClients map[string]interface{}
70-
namespaces options.NamespaceList
70+
kubeClient clientset.Interface
71+
metadataOnlyKubeClient metadata.Interface
72+
customResourceClients map[string]interface{}
73+
namespaces options.NamespaceList
7174
// namespaceFilter is inside fieldSelectorFilter
7275
fieldSelectorFilter string
7376
ctx context.Context
@@ -78,6 +81,7 @@ type Builder struct {
7881
shard int32
7982
totalShards int
8083
buildStoresFunc ksmtypes.BuildStoresFunc
84+
buildMetadataOnlyStoresFunc ksmtypes.BuildMetadataOnlyStoresFunc
8185
buildCustomResourceStoresFunc ksmtypes.BuildCustomResourceStoresFunc
8286
allowAnnotationsList map[string][]string
8387
allowLabelsList map[string][]string
@@ -157,6 +161,11 @@ func (b *Builder) WithKubeClient(c clientset.Interface) {
157161
b.kubeClient = c
158162
}
159163

164+
// WithMetadataOnlyKubeClient sets the metadataOnlyKubeClient property of a Builder.
165+
func (b *Builder) WithMetadataOnlyKubeClient(c metadata.Interface) {
166+
b.metadataOnlyKubeClient = c
167+
}
168+
160169
// WithCustomResourceClients sets the customResourceClients property of a Builder.
161170
func (b *Builder) WithCustomResourceClients(cs map[string]interface{}) {
162171
b.customResourceClients = cs
@@ -178,6 +187,11 @@ func (b *Builder) WithGenerateStoresFunc(f ksmtypes.BuildStoresFunc) {
178187
b.buildStoresFunc = f
179188
}
180189

190+
// WithGenerateMetadataOnlyStoresFunc configures a custom generate custom resource store function
191+
func (b *Builder) WithGenerateMetadataOnlyStoresFunc(f ksmtypes.BuildMetadataOnlyStoresFunc) {
192+
b.buildMetadataOnlyStoresFunc = f
193+
}
194+
181195
// WithGenerateCustomResourceStoresFunc configures a custom generate custom resource store function
182196
func (b *Builder) WithGenerateCustomResourceStoresFunc(f ksmtypes.BuildCustomResourceStoresFunc) {
183197
b.buildCustomResourceStoresFunc = f
@@ -188,6 +202,11 @@ func (b *Builder) DefaultGenerateStoresFunc() ksmtypes.BuildStoresFunc {
188202
return b.buildStores
189203
}
190204

205+
// DefaultGenerateMetadataOnlyStoresFunc returns default buildStores function
206+
func (b *Builder) DefaultGenerateMetadataOnlyStoresFunc() ksmtypes.BuildMetadataOnlyStoresFunc {
207+
return b.buildMetadataOnlyStores
208+
}
209+
191210
// DefaultGenerateCustomResourceStoresFunc returns default buildCustomResourceStores function
192211
func (b *Builder) DefaultGenerateCustomResourceStoresFunc() ksmtypes.BuildCustomResourceStoresFunc {
193212
return b.buildCustomResourceStores
@@ -362,7 +381,7 @@ func availableResources() []string {
362381
}
363382

364383
func (b *Builder) buildConfigMapStores() []cache.Store {
365-
return b.buildStoresFunc(configMapMetricFamilies(b.allowAnnotationsList["configmaps"], b.allowLabelsList["configmaps"]), &v1.ConfigMap{}, createConfigMapListWatch, b.useAPIServerCache)
384+
return b.buildMetadataOnlyStoresFunc(configMapMetricFamilies(b.allowAnnotationsList["configmaps"], b.allowLabelsList["configmaps"]), &metav1.PartialObjectMetadata{}, createConfigMapListWatch, b.useAPIServerCache)
366385
}
367386

368387
func (b *Builder) buildCronJobStores() []cache.Store {
@@ -519,7 +538,8 @@ func (b *Builder) buildStores(
519538
if b.fieldSelectorFilter != "" {
520539
klog.InfoS("FieldSelector is used", "fieldSelector", b.fieldSelectorFilter)
521540
}
522-
listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, b.fieldSelectorFilter)
541+
kubeClient := b.kubeClient
542+
listWatcher := listWatchFunc(kubeClient, v1.NamespaceAll, b.fieldSelectorFilter)
523543
b.startReflector(expectedType, store, listWatcher, useAPIServerCache)
524544
return []cache.Store{store}
525545
}
@@ -541,6 +561,46 @@ func (b *Builder) buildStores(
541561
return stores
542562
}
543563

564+
func (b *Builder) buildMetadataOnlyStores(
565+
metricFamilies []generator.FamilyGenerator,
566+
expectedType interface{},
567+
listWatchFunc func(kubeClient metadata.Interface, ns string, fieldSelector string) cache.ListerWatcher,
568+
useAPIServerCache bool,
569+
) []cache.Store {
570+
metricFamilies = generator.FilterFamilyGenerators(b.familyGeneratorFilter, metricFamilies)
571+
composedMetricGenFuncs := generator.ComposeMetricGenFuncs(metricFamilies)
572+
familyHeaders := generator.ExtractMetricFamilyHeaders(metricFamilies)
573+
574+
if b.namespaces.IsAllNamespaces() {
575+
store := metricsstore.NewMetricsStore(
576+
familyHeaders,
577+
composedMetricGenFuncs,
578+
)
579+
if b.fieldSelectorFilter != "" {
580+
klog.InfoS("FieldSelector is used", "fieldSelector", b.fieldSelectorFilter)
581+
}
582+
listWatcher := listWatchFunc(b.metadataOnlyKubeClient, v1.NamespaceAll, b.fieldSelectorFilter)
583+
b.startReflector(expectedType, store, listWatcher, useAPIServerCache)
584+
return []cache.Store{store}
585+
}
586+
587+
stores := make([]cache.Store, 0, len(b.namespaces))
588+
for _, ns := range b.namespaces {
589+
store := metricsstore.NewMetricsStore(
590+
familyHeaders,
591+
composedMetricGenFuncs,
592+
)
593+
if b.fieldSelectorFilter != "" {
594+
klog.InfoS("FieldSelector is used", "fieldSelector", b.fieldSelectorFilter)
595+
}
596+
listWatcher := listWatchFunc(b.metadataOnlyKubeClient, ns, b.fieldSelectorFilter)
597+
b.startReflector(expectedType, store, listWatcher, useAPIServerCache)
598+
stores = append(stores, store)
599+
}
600+
601+
return stores
602+
}
603+
544604
// TODO(Garrybest): Merge `buildStores` and `buildCustomResourceStores`
545605
func (b *Builder) buildCustomResourceStores(resourceName string,
546606
metricFamilies []generator.FamilyGenerator,

internal/store/configmap.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ package store
1919
import (
2020
"context"
2121

22-
v1 "k8s.io/api/core/v1"
2322
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2423
"k8s.io/apimachinery/pkg/runtime"
24+
"k8s.io/apimachinery/pkg/runtime/schema"
2525
"k8s.io/apimachinery/pkg/watch"
26-
clientset "k8s.io/client-go/kubernetes"
26+
"k8s.io/client-go/metadata"
2727
"k8s.io/client-go/tools/cache"
2828
basemetrics "k8s.io/component-base/metrics"
2929

@@ -43,7 +43,7 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
4343
metric.Gauge,
4444
basemetrics.ALPHA,
4545
"",
46-
wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family {
46+
wrapConfigMapFunc(func(c *metav1.PartialObjectMetadata) *metric.Family {
4747
if len(allowAnnotationsList) == 0 {
4848
return &metric.Family{}
4949
}
@@ -65,7 +65,7 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
6565
metric.Gauge,
6666
basemetrics.STABLE,
6767
"",
68-
wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family {
68+
wrapConfigMapFunc(func(c *metav1.PartialObjectMetadata) *metric.Family {
6969
if len(allowLabelsList) == 0 {
7070
return &metric.Family{}
7171
}
@@ -87,7 +87,7 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
8787
metric.Gauge,
8888
basemetrics.STABLE,
8989
"",
90-
wrapConfigMapFunc(func(_ *v1.ConfigMap) *metric.Family {
90+
wrapConfigMapFunc(func(_ *metav1.PartialObjectMetadata) *metric.Family {
9191
return &metric.Family{
9292
Metrics: []*metric.Metric{{
9393
LabelKeys: []string{},
@@ -103,7 +103,7 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
103103
metric.Gauge,
104104
basemetrics.STABLE,
105105
"",
106-
wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family {
106+
wrapConfigMapFunc(func(c *metav1.PartialObjectMetadata) *metric.Family {
107107
ms := []*metric.Metric{}
108108

109109
if !c.CreationTimestamp.IsZero() {
@@ -125,7 +125,7 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
125125
metric.Gauge,
126126
basemetrics.ALPHA,
127127
"",
128-
wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family {
128+
wrapConfigMapFunc(func(c *metav1.PartialObjectMetadata) *metric.Family {
129129
return &metric.Family{
130130
Metrics: resourceVersionMetric(c.ObjectMeta.ResourceVersion),
131131
}
@@ -134,22 +134,22 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
134134
}
135135
}
136136

137-
func createConfigMapListWatch(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher {
137+
func createConfigMapListWatch(kubeClient metadata.Interface, ns string, fieldSelector string) cache.ListerWatcher {
138138
return &cache.ListWatch{
139139
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
140140
opts.FieldSelector = fieldSelector
141-
return kubeClient.CoreV1().ConfigMaps(ns).List(context.TODO(), opts)
141+
return kubeClient.Resource(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}).Namespace(ns).List(context.TODO(), opts)
142142
},
143143
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
144144
opts.FieldSelector = fieldSelector
145-
return kubeClient.CoreV1().ConfigMaps(ns).Watch(context.TODO(), opts)
145+
return kubeClient.Resource(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}).Namespace(ns).Watch(context.TODO(), opts)
146146
},
147147
}
148148
}
149149

150-
func wrapConfigMapFunc(f func(*v1.ConfigMap) *metric.Family) func(interface{}) *metric.Family {
150+
func wrapConfigMapFunc(f func(*metav1.PartialObjectMetadata) *metric.Family) func(interface{}) *metric.Family {
151151
return func(obj interface{}) *metric.Family {
152-
configMap := obj.(*v1.ConfigMap)
152+
configMap := obj.(*metav1.PartialObjectMetadata)
153153

154154
metricFamily := f(configMap)
155155

internal/store/configmap_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package store
1919
import (
2020
"testing"
2121

22-
v1 "k8s.io/api/core/v1"
2322
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2423

2524
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
@@ -37,7 +36,7 @@ func TestConfigMapStore(t *testing.T) {
3736
AllowLabelsList: []string{
3837
"app",
3938
},
40-
Obj: &v1.ConfigMap{
39+
Obj: &metav1.PartialObjectMetadata{
4140
ObjectMeta: metav1.ObjectMeta{
4241
Name: "configmap1",
4342
Namespace: "ns1",
@@ -73,7 +72,7 @@ func TestConfigMapStore(t *testing.T) {
7372
},
7473
},
7574
{
76-
Obj: &v1.ConfigMap{
75+
Obj: &metav1.PartialObjectMetadata{
7776
ObjectMeta: metav1.ObjectMeta{
7877
Name: "configmap2",
7978
Namespace: "ns2",

pkg/app/server.go

+7
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error {
266266

267267
storeBuilder.WithUsingAPIServerCache(opts.UseAPIServerCache)
268268
storeBuilder.WithGenerateStoresFunc(storeBuilder.DefaultGenerateStoresFunc())
269+
storeBuilder.WithGenerateMetadataOnlyStoresFunc(storeBuilder.DefaultGenerateMetadataOnlyStoresFunc())
269270
proc.StartReaper()
270271

271272
storeBuilder.WithUtilOptions(opts)
@@ -275,6 +276,12 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error {
275276
}
276277
storeBuilder.WithKubeClient(kubeClient)
277278

279+
metadataOnlyKubeClient, err := util.CreateMetadataOnlyKubeClient(opts.Apiserver, opts.Kubeconfig)
280+
if err != nil {
281+
return fmt.Errorf("failed to create metadata-only client: %v", err)
282+
}
283+
storeBuilder.WithMetadataOnlyKubeClient(metadataOnlyKubeClient)
284+
278285
storeBuilder.WithSharding(opts.Shard, opts.TotalShards)
279286
if err := storeBuilder.WithAllowAnnotations(opts.AnnotationsAllowList); err != nil {
280287
return fmt.Errorf("failed to set up annotations allowlist: %v", err)

pkg/app/server_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func BenchmarkKubeStateMetrics(b *testing.B) {
8484
builder.WithContext(ctx)
8585
builder.WithNamespaces(options.DefaultNamespaces)
8686
builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc())
87+
builder.WithGenerateMetadataOnlyStoresFunc(builder.DefaultGenerateMetadataOnlyStoresFunc())
8788

8889
allowDenyListFilter, err := allowdenylist.New(map[string]struct{}{}, map[string]struct{}{})
8990
if err != nil {
@@ -159,6 +160,7 @@ func TestFullScrapeCycle(t *testing.T) {
159160
builder.WithKubeClient(kubeClient)
160161
builder.WithNamespaces(options.DefaultNamespaces)
161162
builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc())
163+
builder.WithGenerateMetadataOnlyStoresFunc(builder.DefaultGenerateMetadataOnlyStoresFunc())
162164

163165
l, err := allowdenylist.New(map[string]struct{}{}, map[string]struct{}{})
164166
if err != nil {
@@ -463,6 +465,7 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) {
463465
unshardedBuilder.WithFamilyGeneratorFilter(l)
464466
unshardedBuilder.WithAllowLabels(map[string][]string{})
465467
unshardedBuilder.WithGenerateStoresFunc(unshardedBuilder.DefaultGenerateStoresFunc())
468+
unshardedBuilder.WithGenerateMetadataOnlyStoresFunc(unshardedBuilder.DefaultGenerateMetadataOnlyStoresFunc())
466469

467470
unshardedHandler := metricshandler.New(&options.Options{}, kubeClient, unshardedBuilder, false)
468471
unshardedHandler.ConfigureSharding(ctx, 0, 1)
@@ -479,6 +482,7 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) {
479482
shardedBuilder1.WithFamilyGeneratorFilter(l)
480483
shardedBuilder1.WithAllowLabels(map[string][]string{})
481484
shardedBuilder1.WithGenerateStoresFunc(shardedBuilder1.DefaultGenerateStoresFunc())
485+
shardedBuilder1.WithGenerateMetadataOnlyStoresFunc(shardedBuilder1.DefaultGenerateMetadataOnlyStoresFunc())
482486

483487
shardedHandler1 := metricshandler.New(&options.Options{}, kubeClient, shardedBuilder1, false)
484488
shardedHandler1.ConfigureSharding(ctx, 0, 2)
@@ -495,6 +499,7 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) {
495499
shardedBuilder2.WithFamilyGeneratorFilter(l)
496500
shardedBuilder2.WithAllowLabels(map[string][]string{})
497501
shardedBuilder2.WithGenerateStoresFunc(shardedBuilder2.DefaultGenerateStoresFunc())
502+
shardedBuilder2.WithGenerateMetadataOnlyStoresFunc(shardedBuilder2.DefaultGenerateMetadataOnlyStoresFunc())
498503

499504
shardedHandler2 := metricshandler.New(&options.Options{}, kubeClient, shardedBuilder2, false)
500505
shardedHandler2.ConfigureSharding(ctx, 1, 2)
@@ -635,6 +640,7 @@ func TestCustomResourceExtension(t *testing.T) {
635640
builder.WithCustomResourceClients(customResourceClients)
636641
builder.WithNamespaces(options.DefaultNamespaces)
637642
builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc())
643+
builder.WithGenerateMetadataOnlyStoresFunc(builder.DefaultGenerateMetadataOnlyStoresFunc())
638644
builder.WithGenerateCustomResourceStoresFunc(builder.DefaultGenerateCustomResourceStoresFunc())
639645

640646
l, err := allowdenylist.New(map[string]struct{}{}, map[string]struct{}{})

pkg/builder/builder.go

+16
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/prometheus/client_golang/prometheus"
2323
clientset "k8s.io/client-go/kubernetes"
24+
"k8s.io/client-go/metadata"
2425
"k8s.io/client-go/tools/cache"
2526

2627
internalstore "k8s.io/kube-state-metrics/v2/internal/store"
@@ -84,6 +85,11 @@ func (b *Builder) WithKubeClient(c clientset.Interface) {
8485
b.internal.WithKubeClient(c)
8586
}
8687

88+
// WithMetadataOnlyKubeClient sets the metadataOnlyKubeClient property of a Builder.
89+
func (b *Builder) WithMetadataOnlyKubeClient(c metadata.Interface) {
90+
b.internal.WithMetadataOnlyKubeClient(c)
91+
}
92+
8793
// WithCustomResourceClients sets the customResourceClients property of a Builder.
8894
func (b *Builder) WithCustomResourceClients(cs map[string]interface{}) {
8995
b.internal.WithCustomResourceClients(cs)
@@ -120,6 +126,16 @@ func (b *Builder) DefaultGenerateStoresFunc() ksmtypes.BuildStoresFunc {
120126
return b.internal.DefaultGenerateStoresFunc()
121127
}
122128

129+
// WithGenerateMetadataOnlyStoresFunc configures a custom generate metadataonly store function
130+
func (b *Builder) WithGenerateMetadataOnlyStoresFunc(f ksmtypes.BuildMetadataOnlyStoresFunc) {
131+
b.internal.WithGenerateMetadataOnlyStoresFunc(f)
132+
}
133+
134+
// DefaultGenerateMetadataOnlyStoresFunc returns default buildMetadataOnlyStore function
135+
func (b *Builder) DefaultGenerateMetadataOnlyStoresFunc() ksmtypes.BuildMetadataOnlyStoresFunc {
136+
return b.internal.DefaultGenerateMetadataOnlyStoresFunc()
137+
}
138+
123139
// DefaultGenerateCustomResourceStoresFunc returns default buildStores function
124140
func (b *Builder) DefaultGenerateCustomResourceStoresFunc() ksmtypes.BuildCustomResourceStoresFunc {
125141
return b.internal.DefaultGenerateCustomResourceStoresFunc()

pkg/builder/types/interfaces.go

+11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"github.com/prometheus/client_golang/prometheus"
2525
clientset "k8s.io/client-go/kubernetes"
26+
"k8s.io/client-go/metadata"
2627
"k8s.io/client-go/tools/cache"
2728

2829
"k8s.io/kube-state-metrics/v2/pkg/customresource"
@@ -38,6 +39,7 @@ type BuilderInterface interface {
3839
WithFieldSelectorFilter(fieldSelectors string)
3940
WithSharding(shard int32, totalShards int)
4041
WithContext(ctx context.Context)
42+
WithMetadataOnlyKubeClient(c metadata.Interface)
4143
WithKubeClient(c clientset.Interface)
4244
WithCustomResourceClients(cs map[string]interface{})
4345
WithUsingAPIServerCache(u bool)
@@ -46,6 +48,8 @@ type BuilderInterface interface {
4648
WithAllowLabels(l map[string][]string) error
4749
WithGenerateStoresFunc(f BuildStoresFunc)
4850
DefaultGenerateStoresFunc() BuildStoresFunc
51+
WithGenerateMetadataOnlyStoresFunc(f BuildMetadataOnlyStoresFunc)
52+
DefaultGenerateMetadataOnlyStoresFunc() BuildMetadataOnlyStoresFunc
4953
DefaultGenerateCustomResourceStoresFunc() BuildCustomResourceStoresFunc
5054
WithCustomResourceStoreFactories(fs ...customresource.RegistryFactory)
5155
Build() metricsstore.MetricsWriterList
@@ -60,6 +64,13 @@ type BuildStoresFunc func(metricFamilies []generator.FamilyGenerator,
6064
useAPIServerCache bool,
6165
) []cache.Store
6266

67+
// BuildMetadataOnlyStoresFunc function signature that is used to return a list of cache.Store
68+
type BuildMetadataOnlyStoresFunc func(metricFamilies []generator.FamilyGenerator,
69+
expectedType interface{},
70+
listWatchFunc func(kubeClient metadata.Interface, ns string, fieldSelector string) cache.ListerWatcher,
71+
useAPIServerCache bool,
72+
) []cache.Store
73+
6374
// BuildCustomResourceStoresFunc function signature that is used to return a list of custom resource cache.Store
6475
type BuildCustomResourceStoresFunc func(resourceName string,
6576
metricFamilies []generator.FamilyGenerator,

0 commit comments

Comments
 (0)