mirror of
https://github.com/prometheus/prometheus.git
synced 2026-06-09 08:32:26 -04:00
discovery/kubernetes: keep SD client from defeating dead-code elimination
The Kubernetes SD Discovery struct held the clientset as a kubernetes.Interface field. Boxing the concrete *kubernetes.Clientset into an interface marks it <UsedInIface>, so the Go linker conservatively retains every API-group accessor and, transitively, every resource client and its apply configurations, even though discovery only touches the core, apps, batch, discovery and networking v1 groups. Wrap the clientset in an adapter that captures only the used API-group accessors as method-value closures and exposes them through a narrow k8sClient interface. The concrete clientset now lives only inside closure contexts, which reflection cannot traverse, so dead-code elimination drops the unused groups. The fake clientset still satisfies the narrow interface, so tests are unchanged. This trims about 10 MB from each of the prometheus and promtool binaries. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
This commit is contained in:
parent
55226fb8b2
commit
da7be2b867
2 changed files with 78 additions and 2 deletions
76
discovery/kubernetes/client.go
Normal file
76
discovery/kubernetes/client.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
appsv1client "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
batchv1client "k8s.io/client-go/kubernetes/typed/batch/v1"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
discoveryv1client "k8s.io/client-go/kubernetes/typed/discovery/v1"
|
||||
networkingv1client "k8s.io/client-go/kubernetes/typed/networking/v1"
|
||||
)
|
||||
|
||||
// k8sClient exposes only the API-group accessors discovery uses. It is
|
||||
// satisfied by both clientAdapter and the fake clientset used in tests.
|
||||
type k8sClient interface {
|
||||
CoreV1() corev1client.CoreV1Interface
|
||||
AppsV1() appsv1client.AppsV1Interface
|
||||
BatchV1() batchv1client.BatchV1Interface
|
||||
DiscoveryV1() discoveryv1client.DiscoveryV1Interface
|
||||
NetworkingV1() networkingv1client.NetworkingV1Interface
|
||||
}
|
||||
|
||||
// clientAdapter captures the used API-group accessors as method-value closures.
|
||||
// Keeping the concrete clientset out of an interface-typed field avoids forcing
|
||||
// the linker, via reflection, to retain every API group and resource client,
|
||||
// which reduces the binary size.
|
||||
type clientAdapter struct {
|
||||
coreV1 func() corev1client.CoreV1Interface
|
||||
appsV1 func() appsv1client.AppsV1Interface
|
||||
batchV1 func() batchv1client.BatchV1Interface
|
||||
discoveryV1 func() discoveryv1client.DiscoveryV1Interface
|
||||
networkingV1 func() networkingv1client.NetworkingV1Interface
|
||||
}
|
||||
|
||||
// newClientAdapter wraps a concrete clientset, exposing only the API groups
|
||||
// discovery uses.
|
||||
func newClientAdapter(c *kubernetes.Clientset) *clientAdapter {
|
||||
return &clientAdapter{
|
||||
coreV1: c.CoreV1,
|
||||
appsV1: c.AppsV1,
|
||||
batchV1: c.BatchV1,
|
||||
discoveryV1: c.DiscoveryV1,
|
||||
networkingV1: c.NetworkingV1,
|
||||
}
|
||||
}
|
||||
|
||||
// CoreV1 returns the core/v1 API-group client.
|
||||
func (a *clientAdapter) CoreV1() corev1client.CoreV1Interface { return a.coreV1() }
|
||||
|
||||
// AppsV1 returns the apps/v1 API-group client.
|
||||
func (a *clientAdapter) AppsV1() appsv1client.AppsV1Interface { return a.appsV1() }
|
||||
|
||||
// BatchV1 returns the batch/v1 API-group client.
|
||||
func (a *clientAdapter) BatchV1() batchv1client.BatchV1Interface { return a.batchV1() }
|
||||
|
||||
// DiscoveryV1 returns the discovery/v1 API-group client.
|
||||
func (a *clientAdapter) DiscoveryV1() discoveryv1client.DiscoveryV1Interface {
|
||||
return a.discoveryV1()
|
||||
}
|
||||
|
||||
// NetworkingV1 returns the networking/v1 API-group client.
|
||||
func (a *clientAdapter) NetworkingV1() networkingv1client.NetworkingV1Interface {
|
||||
return a.networkingV1()
|
||||
}
|
||||
|
|
@ -254,7 +254,7 @@ func (c *NamespaceDiscovery) UnmarshalYAML(unmarshal func(any) error) error {
|
|||
// targets from Kubernetes.
|
||||
type Discovery struct {
|
||||
sync.RWMutex
|
||||
client kubernetes.Interface
|
||||
client k8sClient
|
||||
role Role
|
||||
logger *slog.Logger
|
||||
namespaceDiscovery *NamespaceDiscovery
|
||||
|
|
@ -341,7 +341,7 @@ func New(l *slog.Logger, metrics discovery.DiscovererMetrics, conf *SDConfig) (*
|
|||
}
|
||||
|
||||
d := &Discovery{
|
||||
client: c,
|
||||
client: newClientAdapter(c),
|
||||
logger: l,
|
||||
role: conf.Role,
|
||||
namespaceDiscovery: &conf.NamespaceDiscovery,
|
||||
|
|
|
|||
Loading…
Reference in a new issue