@@ -19,65 +19,21 @@ package main
19
19
import (
20
20
"context"
21
21
"fmt"
22
- "net"
23
- "net/http"
24
- "net/http/pprof"
25
22
"os"
26
- "strconv"
27
- "time"
28
23
29
- "github.com/oklog/run"
30
- "github.com/pkg/errors"
31
- "github.com/prometheus/client_golang/prometheus"
32
- "github.com/prometheus/client_golang/prometheus/collectors"
33
- "github.com/prometheus/client_golang/prometheus/promauto"
34
- "github.com/prometheus/client_golang/prometheus/promhttp"
35
24
"github.com/prometheus/common/version"
36
- "github.com/prometheus/exporter-toolkit/web"
37
- vpaclientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned"
38
- clientset "k8s.io/client-go/kubernetes"
39
- _ "k8s.io/client-go/plugin/pkg/client/auth"
40
- "k8s.io/client-go/tools/clientcmd"
41
25
"k8s.io/klog/v2"
42
26
43
- "k8s.io/kube-state-metrics/v2/internal/store"
44
- "k8s.io/kube-state-metrics/v2/pkg/allowdenylist"
45
- generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
46
- "k8s.io/kube-state-metrics/v2/pkg/metricshandler"
47
- "k8s.io/kube-state-metrics/v2/pkg/optin"
27
+ "k8s.io/kube-state-metrics/v2/pkg/app"
48
28
"k8s.io/kube-state-metrics/v2/pkg/options"
49
- "k8s.io/kube-state-metrics/v2/pkg/util/proc"
50
29
)
51
30
52
- const (
53
- metricsPath = "/metrics"
54
- healthzPath = "/healthz"
55
- )
56
-
57
- // promLogger implements promhttp.Logger
58
- type promLogger struct {}
59
-
60
- func (pl promLogger ) Println (v ... interface {}) {
61
- klog .Error (v ... )
62
- }
63
-
64
- // promLogger implements the Logger interface
65
- func (pl promLogger ) Log (v ... interface {}) error {
66
- klog .Info (v ... )
67
- return nil
68
- }
69
-
70
31
func main () {
71
32
opts := options .NewOptions ()
72
33
opts .AddFlags ()
73
34
74
- promLogger := promLogger {}
75
-
76
- ctx := context .Background ()
77
-
78
- err := opts .Parse ()
79
- if err != nil {
80
- klog .Fatalf ("Error: %s" , err )
35
+ if err := opts .Parse (); err != nil {
36
+ klog .Fatalf ("Parsing flag definitions error: %v" , err )
81
37
}
82
38
83
39
if opts .Version {
@@ -89,222 +45,9 @@ func main() {
89
45
opts .Usage ()
90
46
os .Exit (0 )
91
47
}
92
- storeBuilder := store .NewBuilder ()
93
-
94
- ksmMetricsRegistry := prometheus .NewRegistry ()
95
- ksmMetricsRegistry .MustRegister (version .NewCollector ("kube_state_metrics" ))
96
- durationVec := promauto .With (ksmMetricsRegistry ).NewHistogramVec (
97
- prometheus.HistogramOpts {
98
- Name : "http_request_duration_seconds" ,
99
- Help : "A histogram of requests for kube-state-metrics metrics handler." ,
100
- Buckets : prometheus .DefBuckets ,
101
- ConstLabels : prometheus.Labels {"handler" : "metrics" },
102
- }, []string {"method" },
103
- )
104
- storeBuilder .WithMetrics (ksmMetricsRegistry )
105
-
106
- var resources []string
107
- if len (opts .Resources ) == 0 {
108
- klog .Info ("Using default resources" )
109
- resources = options .DefaultResources .AsSlice ()
110
- } else {
111
- klog .Infof ("Using resources %s" , opts .Resources .String ())
112
- resources = opts .Resources .AsSlice ()
113
- }
114
-
115
- if err := storeBuilder .WithEnabledResources (resources ); err != nil {
116
- klog .Fatalf ("Failed to set up resources: %v" , err )
117
- }
118
-
119
- namespaces := opts .Namespaces .GetNamespaces ()
120
- nsFieldSelector := namespaces .GetExcludeNSFieldSelector (opts .NamespacesDenylist )
121
- storeBuilder .WithNamespaces (namespaces , nsFieldSelector )
122
-
123
- allowDenyList , err := allowdenylist .New (opts .MetricAllowlist , opts .MetricDenylist )
124
- if err != nil {
125
- klog .Fatal (err )
126
- }
127
-
128
- err = allowDenyList .Parse ()
129
- if err != nil {
130
- klog .Fatalf ("error initializing the allowdeny list : %v" , err )
131
- }
132
-
133
- klog .Infof ("metric allow-denylisting: %v" , allowDenyList .Status ())
134
-
135
- optInMetricFamilyFilter , err := optin .NewMetricFamilyFilter (opts .MetricOptInList )
136
- if err != nil {
137
- klog .Fatalf ("error initializing the opt-in metric list : %v" , err )
138
- }
139
-
140
- if optInMetricFamilyFilter .Count () > 0 {
141
- klog .Infof ("metrics which were opted into: %v" , optInMetricFamilyFilter .Status ())
142
- }
143
-
144
- storeBuilder .WithFamilyGeneratorFilter (generator .NewCompositeFamilyGeneratorFilter (
145
- allowDenyList ,
146
- optInMetricFamilyFilter ,
147
- ))
148
-
149
- storeBuilder .WithGenerateStoresFunc (storeBuilder .DefaultGenerateStoresFunc (), opts .UseAPIServerCache )
150
-
151
- proc .StartReaper ()
152
-
153
- kubeClient , vpaClient , err := createKubeClient (opts .Apiserver , opts .Kubeconfig )
154
- if err != nil {
155
- klog .Fatalf ("Failed to create client: %v" , err )
156
- }
157
- storeBuilder .WithKubeClient (kubeClient )
158
- storeBuilder .WithVPAClient (vpaClient )
159
- storeBuilder .WithSharding (opts .Shard , opts .TotalShards )
160
- storeBuilder .WithAllowAnnotations (opts .AnnotationsAllowList )
161
- storeBuilder .WithAllowLabels (opts .LabelsAllowList )
162
48
163
- ksmMetricsRegistry .MustRegister (
164
- collectors .NewProcessCollector (collectors.ProcessCollectorOpts {}),
165
- collectors .NewGoCollector (),
166
- )
167
-
168
- var g run.Group
169
-
170
- m := metricshandler .New (
171
- opts ,
172
- kubeClient ,
173
- storeBuilder ,
174
- opts .EnableGZIPEncoding ,
175
- )
176
- // Run MetricsHandler
177
- {
178
- ctxMetricsHandler , cancel := context .WithCancel (ctx )
179
- g .Add (func () error {
180
- return m .Run (ctxMetricsHandler )
181
- }, func (error ) {
182
- cancel ()
183
- })
184
- }
185
-
186
- tlsConfig := opts .TLSConfig
187
-
188
- telemetryMux := buildTelemetryServer (ksmMetricsRegistry )
189
- telemetryListenAddress := net .JoinHostPort (opts .TelemetryHost , strconv .Itoa (opts .TelemetryPort ))
190
- telemetryServer := http.Server {Handler : telemetryMux , Addr : telemetryListenAddress }
191
-
192
- metricsMux := buildMetricsServer (m , durationVec )
193
- metricsServerListenAddress := net .JoinHostPort (opts .Host , strconv .Itoa (opts .Port ))
194
- metricsServer := http.Server {Handler : metricsMux , Addr : metricsServerListenAddress }
195
-
196
- // Run Telemetry server
197
- {
198
- g .Add (func () error {
199
- klog .Infof ("Starting kube-state-metrics self metrics server: %s" , telemetryListenAddress )
200
- return web .ListenAndServe (& telemetryServer , tlsConfig , promLogger )
201
- }, func (error ) {
202
- ctxShutDown , cancel := context .WithTimeout (ctx , 3 * time .Second )
203
- defer cancel ()
204
- telemetryServer .Shutdown (ctxShutDown )
205
- })
206
- }
207
- // Run Metrics server
208
- {
209
- g .Add (func () error {
210
- klog .Infof ("Starting metrics server: %s" , metricsServerListenAddress )
211
- return web .ListenAndServe (& metricsServer , tlsConfig , promLogger )
212
- }, func (error ) {
213
- ctxShutDown , cancel := context .WithTimeout (ctx , 3 * time .Second )
214
- defer cancel ()
215
- metricsServer .Shutdown (ctxShutDown )
216
- })
217
- }
218
-
219
- if err := g .Run (); err != nil {
220
- klog .Fatalf ("RunGroup Error: %v" , err )
221
- }
222
- klog .Info ("Exiting" )
223
- }
224
-
225
- func createKubeClient (apiserver string , kubeconfig string ) (clientset.Interface , vpaclientset.Interface , error ) {
226
- config , err := clientcmd .BuildConfigFromFlags (apiserver , kubeconfig )
227
- if err != nil {
228
- return nil , nil , err
229
- }
230
-
231
- config .UserAgent = version .Version
232
- config .AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
233
- config .ContentType = "application/vnd.kubernetes.protobuf"
234
-
235
- kubeClient , err := clientset .NewForConfig (config )
236
- if err != nil {
237
- return nil , nil , err
238
- }
239
-
240
- vpaClient , err := vpaclientset .NewForConfig (config )
241
- if err != nil {
242
- return nil , nil , err
243
- }
244
- // Informers don't seem to do a good job logging error messages when it
245
- // can't reach the server, making debugging hard. This makes it easier to
246
- // figure out if apiserver is configured incorrectly.
247
- klog .Infof ("Testing communication with server" )
248
- v , err := kubeClient .Discovery ().ServerVersion ()
249
- if err != nil {
250
- return nil , nil , errors .Wrap (err , "error while trying to communicate with apiserver" )
49
+ ctx := context .Background ()
50
+ if err := app .RunKubeStateMetrics (ctx , opts ); err != nil {
51
+ klog .Fatalf ("Failed to run kube-state-metrics: %v" , err )
251
52
}
252
- klog .Infof ("Running with Kubernetes cluster version: v%s.%s. git version: %s. git tree state: %s. commit: %s. platform: %s" ,
253
- v .Major , v .Minor , v .GitVersion , v .GitTreeState , v .GitCommit , v .Platform )
254
- klog .Infof ("Communication with server successful" )
255
-
256
- return kubeClient , vpaClient , nil
257
- }
258
-
259
- func buildTelemetryServer (registry prometheus.Gatherer ) * http.ServeMux {
260
- mux := http .NewServeMux ()
261
-
262
- // Add metricsPath
263
- mux .Handle (metricsPath , promhttp .HandlerFor (registry , promhttp.HandlerOpts {ErrorLog : promLogger {}}))
264
- // Add index
265
- mux .HandleFunc ("/" , func (w http.ResponseWriter , r * http.Request ) {
266
- w .Write ([]byte (`<html>
267
- <head><title>Kube-State-Metrics Metrics Server</title></head>
268
- <body>
269
- <h1>Kube-State-Metrics Metrics</h1>
270
- <ul>
271
- <li><a href='` + metricsPath + `'>metrics</a></li>
272
- </ul>
273
- </body>
274
- </html>` ))
275
- })
276
- return mux
277
- }
278
-
279
- func buildMetricsServer (m * metricshandler.MetricsHandler , durationObserver prometheus.ObserverVec ) * http.ServeMux {
280
- mux := http .NewServeMux ()
281
-
282
- // TODO: This doesn't belong into serveMetrics
283
- mux .Handle ("/debug/pprof/" , http .HandlerFunc (pprof .Index ))
284
- mux .Handle ("/debug/pprof/cmdline" , http .HandlerFunc (pprof .Cmdline ))
285
- mux .Handle ("/debug/pprof/profile" , http .HandlerFunc (pprof .Profile ))
286
- mux .Handle ("/debug/pprof/symbol" , http .HandlerFunc (pprof .Symbol ))
287
- mux .Handle ("/debug/pprof/trace" , http .HandlerFunc (pprof .Trace ))
288
-
289
- mux .Handle (metricsPath , promhttp .InstrumentHandlerDuration (durationObserver , m ))
290
-
291
- // Add healthzPath
292
- mux .HandleFunc (healthzPath , func (w http.ResponseWriter , r * http.Request ) {
293
- w .WriteHeader (http .StatusOK )
294
- w .Write ([]byte (http .StatusText (http .StatusOK )))
295
- })
296
- // Add index
297
- mux .HandleFunc ("/" , func (w http.ResponseWriter , r * http.Request ) {
298
- w .Write ([]byte (`<html>
299
- <head><title>Kube Metrics Server</title></head>
300
- <body>
301
- <h1>Kube Metrics</h1>
302
- <ul>
303
- <li><a href='` + metricsPath + `'>metrics</a></li>
304
- <li><a href='` + healthzPath + `'>healthz</a></li>
305
- </ul>
306
- </body>
307
- </html>` ))
308
- })
309
- return mux
310
53
}
0 commit comments