master
go 140 lines 3.52 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package k8s_apiserver
4
5 import (
6 "context"
7 _ "embed"
8 "errors"
9 "fmt"
10 "time"
11
12 "github.com/netdata/netdata/go/plugins/pkg/confopt"
13 "github.com/netdata/netdata/go/plugins/pkg/prometheus"
14 "github.com/netdata/netdata/go/plugins/pkg/tlscfg"
15 "github.com/netdata/netdata/go/plugins/pkg/web"
16 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
17 )
18
19 //go:embed "config_schema.json"
20 var configSchema string
21
22 func init() {
23 collectorapi.Register("k8s_apiserver", collectorapi.Creator{
24 JobConfigSchema: configSchema,
25 Defaults: collectorapi.Defaults{
26 Priority: 50100,
27 },
28 Create: func() collectorapi.CollectorV1 { return New() },
29 Config: func() any { return &Config{} },
30 })
31 }
32
33 func New() *Collector {
34 return &Collector{
35 Config: Config{
36 HTTPConfig: web.HTTPConfig{
37 RequestConfig: web.RequestConfig{
38 URL: "https://kubernetes.default.svc:443/metrics",
39 Headers: make(map[string]string),
40 BearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token",
41 },
42 ClientConfig: web.ClientConfig{
43 Timeout: confopt.Duration(time.Second * 2),
44 TLSConfig: tlscfg.TLSConfig{
45 TLSCA: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
46 },
47 },
48 },
49 },
50 charts: baseCharts.Copy(),
51 collectedResources: make(map[string]int64),
52 collectedVerbs: make(map[string]int64),
53 collectedCodes: make(map[string]int64),
54 collectedWorkqueues: make(map[string]int64),
55 collectedAdmissionCtrl: make(map[string]int64),
56 collectedAdmissionWH: make(map[string]int64),
57 collectedRESTCodes: make(map[string]int64),
58 collectedRESTMethods: make(map[string]int64),
59 }
60 }
61
62 type Config struct {
63 Vnode string `yaml:"vnode,omitempty" json:"vnode"`
64 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
65 AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
66 web.HTTPConfig `yaml:",inline" json:""`
67 }
68
69 type Collector struct {
70 collectorapi.Base
71 Config `yaml:",inline" json:""`
72
73 charts *Charts
74
75 prom prometheus.Prometheus
76
77 // Collection cycle counter for staleness tracking
78 collectCycle int64
79
80 // Track collected dynamic dimensions/charts with last-seen cycle
81 // Maps dimension name to the cycle number when it was last seen
82 collectedResources map[string]int64
83 collectedVerbs map[string]int64
84 collectedCodes map[string]int64
85 collectedWorkqueues map[string]int64
86 collectedAdmissionCtrl map[string]int64
87 collectedAdmissionWH map[string]int64
88 collectedRESTCodes map[string]int64
89 collectedRESTMethods map[string]int64
90 }
91
92 func (c *Collector) Configuration() any {
93 return c.Config
94 }
95
96 func (c *Collector) Init(context.Context) error {
97 if err := c.validateConfig(); err != nil {
98 return fmt.Errorf("config validation: %v", err)
99 }
100
101 prom, err := c.initPrometheusClient()
102 if err != nil {
103 return fmt.Errorf("init prometheus client: %v", err)
104 }
105 c.prom = prom
106
107 return nil
108 }
109
110 func (c *Collector) Check(context.Context) error {
111 mx, err := c.collect()
112 if err != nil {
113 return err
114 }
115 if len(mx) == 0 {
116 return errors.New("no metrics collected")
117 }
118 return nil
119 }
120
121 func (c *Collector) Charts() *Charts {
122 return c.charts
123 }
124
125 func (c *Collector) Collect(context.Context) map[string]int64 {
126 mx, err := c.collect()
127
128 if err != nil {
129 c.Error(err)
130 return nil
131 }
132
133 return mx
134 }
135
136 func (c *Collector) Cleanup(context.Context) {
137 if c.prom != nil && c.prom.HTTPClient() != nil {
138 c.prom.HTTPClient().CloseIdleConnections()
139 }
140 }