Skip to content

Commit 2e3afdf

Browse files
author
Sunil Thaha
authored
Merge pull request #2127 from vimalk78/pod-power
feat(pod): added pod power
2 parents 2d33e25 + b0c0f99 commit 2e3afdf

File tree

19 files changed

+1899
-23
lines changed

19 files changed

+1899
-23
lines changed

cmd/kepler/main.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/sustainable-computing-io/kepler/internal/device"
1616
"github.com/sustainable-computing-io/kepler/internal/exporter/prometheus"
1717
"github.com/sustainable-computing-io/kepler/internal/exporter/stdout"
18+
"github.com/sustainable-computing-io/kepler/internal/k8s/pod"
1819
"github.com/sustainable-computing-io/kepler/internal/logger"
1920
"github.com/sustainable-computing-io/kepler/internal/monitor"
2021
"github.com/sustainable-computing-io/kepler/internal/resource"
@@ -126,10 +127,21 @@ func createServices(logger *slog.Logger, cfg *config.Config) ([]service.Service,
126127
if err != nil {
127128
return nil, fmt.Errorf("failed to create CPU power meter: %w", err)
128129
}
130+
var services []service.Service
129131

130-
resouceInformer, err := resource.NewInformer(
132+
var podInformer pod.Informer
133+
if *cfg.Kube.Enabled {
134+
podInformer = pod.NewInformer(
135+
pod.WithLogger(logger),
136+
pod.WithKubeConfig(cfg.Kube.Config),
137+
pod.WithNodeName(cfg.Kube.Node),
138+
)
139+
services = append(services, podInformer)
140+
}
141+
resourceInformer, err := resource.NewInformer(
131142
resource.WithLogger(logger),
132143
resource.WithProcFSPath(cfg.Host.ProcFS),
144+
resource.WithPodInformer(podInformer),
133145
)
134146
if err != nil {
135147
return nil, fmt.Errorf("failed to create resource informer: %w", err)
@@ -138,7 +150,7 @@ func createServices(logger *slog.Logger, cfg *config.Config) ([]service.Service,
138150
pm := monitor.NewPowerMonitor(
139151
cpuPowerMeter,
140152
monitor.WithLogger(logger),
141-
monitor.WithResourceInformer(resouceInformer),
153+
monitor.WithResourceInformer(resourceInformer),
142154
monitor.WithInterval(cfg.Monitor.Interval),
143155
monitor.WithMaxStaleness(cfg.Monitor.Staleness),
144156
)
@@ -147,12 +159,12 @@ func createServices(logger *slog.Logger, cfg *config.Config) ([]service.Service,
147159
server.WithLogger(logger),
148160
)
149161

150-
services := []service.Service{
162+
services = append(services,
163+
resourceInformer,
151164
cpuPowerMeter,
152-
resouceInformer,
153165
apiServer,
154166
pm,
155-
}
167+
)
156168

157169
// Add Prometheus exporter if enabled
158170
if *cfg.Exporter.Prometheus.Enabled {

config/config.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ type (
7171
Pprof PprofDebug `yaml:"pprof"`
7272
}
7373

74+
Kube struct {
75+
Enabled *bool `yaml:"enabled"`
76+
Config string `yaml:"config"`
77+
Node string `yaml:"nodeName"`
78+
}
79+
7480
Config struct {
7581
Log Log `yaml:"log"`
7682
Host Host `yaml:"host"`
@@ -80,13 +86,16 @@ type (
8086
Web Web `yaml:"web"`
8187
Debug Debug `yaml:"debug"`
8288
Dev Dev `yaml:"dev"` // WARN: do not expose dev settings as flags
89+
90+
Kube Kube `yaml:"kube"`
8391
}
8492
)
8593

8694
type SkipValidation int
8795

8896
const (
8997
SkipHostValidation SkipValidation = 1
98+
SkipKubeValidation SkipValidation = 2
9099
)
91100

92101
const (
@@ -114,6 +123,11 @@ const (
114123
// NOTE: not a flag
115124
ExporterPrometheusDebugCollectors = "exporter.prometheus.debug-collectors"
116125

126+
// kubernetes flags
127+
KubernetesFlag = "kube.enable"
128+
KubeConfigFlag = "kube.config"
129+
KubeNodeNameFlag = "kube.node-name"
130+
117131
// WARN: dev settings shouldn't be exposed as flags as flags are intended for end users
118132
)
119133

@@ -149,6 +163,9 @@ func DefaultConfig() *Config {
149163
Enabled: ptr.To(false),
150164
},
151165
},
166+
Kube: Kube{
167+
Enabled: ptr.To(false),
168+
},
152169
}
153170

154171
cfg.Dev.FakeCpuMeter.Enabled = ptr.To(false)
@@ -235,6 +252,10 @@ func RegisterFlags(app *kingpin.Application) ConfigUpdaterFn {
235252

236253
prometheusExporterEnabled := app.Flag(ExporterPrometheusEnabledFlag, "Enable Prometheus exporter").Default("true").Bool()
237254

255+
kubernetes := app.Flag(KubernetesFlag, "Monitor kubernetes").Default("false").Bool()
256+
kubeconfig := app.Flag(KubeConfigFlag, "Path to a kubeconfig. Only required if out-of-cluster.").ExistingFile()
257+
nodeName := app.Flag(KubeNodeNameFlag, "Name of kubernetes node on which kepler is running.").String()
258+
238259
return func(cfg *Config) error {
239260
// Logging settings
240261
if flagsSet[LogLevelFlag] {
@@ -274,6 +295,18 @@ func RegisterFlags(app *kingpin.Application) ConfigUpdaterFn {
274295
cfg.Exporter.Prometheus.Enabled = prometheusExporterEnabled
275296
}
276297

298+
if flagsSet[KubernetesFlag] {
299+
cfg.Kube.Enabled = kubernetes
300+
}
301+
302+
if flagsSet[KubeConfigFlag] {
303+
cfg.Kube.Config = *kubeconfig
304+
}
305+
306+
if flagsSet[KubeNodeNameFlag] {
307+
cfg.Kube.Node = *nodeName
308+
}
309+
277310
cfg.sanitize()
278311
return cfg.Validate()
279312
}
@@ -293,6 +326,7 @@ func (c *Config) sanitize() {
293326
for i := range c.Exporter.Prometheus.DebugCollectors {
294327
c.Exporter.Prometheus.DebugCollectors[i] = strings.TrimSpace(c.Exporter.Prometheus.DebugCollectors[i])
295328
}
329+
c.Kube.Config = strings.TrimSpace(c.Kube.Config)
296330
}
297331

298332
// Validate checks for configuration errors
@@ -351,6 +385,19 @@ func (c *Config) Validate(skips ...SkipValidation) error {
351385
errs = append(errs, fmt.Sprintf("invalid monitor staleness: %s can't be negative", c.Monitor.Staleness))
352386
}
353387
}
388+
{ // Kubernetes
389+
if c.Kube.Config != "" && !ptr.Deref(c.Kube.Enabled, false) {
390+
errs = append(errs, fmt.Sprintf("%s supplied but %s set to false", KubeConfigFlag, KubernetesFlag))
391+
}
392+
if c.Kube.Node != "" && !ptr.Deref(c.Kube.Enabled, false) {
393+
errs = append(errs, fmt.Sprintf("%s supplied but %s set to false", KubeNodeNameFlag, KubernetesFlag))
394+
}
395+
if ptr.Deref(c.Kube.Enabled, false) && c.Kube.Config != "" {
396+
if err := canReadFile(c.Kube.Config); err != nil {
397+
errs = append(errs, fmt.Sprintf("unreadable kubeconfig: %s", c.Kube.Config))
398+
}
399+
}
400+
}
354401

355402
if len(errs) > 0 {
356403
return fmt.Errorf("invalid configuration: %s", strings.Join(errs, ", "))
@@ -423,6 +470,7 @@ func (c *Config) manualString() string {
423470
{ExporterPrometheusEnabledFlag, fmt.Sprintf("%v", c.Exporter.Prometheus.Enabled)},
424471
{ExporterPrometheusDebugCollectors, strings.Join(c.Exporter.Prometheus.DebugCollectors, ", ")},
425472
{pprofEnabledFlag, fmt.Sprintf("%v", c.Debug.Pprof.Enabled)},
473+
{KubeConfigFlag, fmt.Sprintf("%v", c.Kube.Config)},
426474
}
427475
sb := strings.Builder{}
428476

config/config_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,31 @@ func TestInvalidConfigurationValues(t *testing.T) {
291291
},
292292
},
293293
error: "invalid web config file",
294+
}, {
295+
name: "unreadable kubeconfig",
296+
config: &Config{
297+
Kube: Kube{
298+
Config: "/non/existent/file",
299+
Enabled: ptr.To(true),
300+
},
301+
},
302+
error: "unreadable kubeconfig",
303+
}, {
304+
name: "kube not enabled, kubeconfig supplied",
305+
config: &Config{
306+
Kube: Kube{
307+
Config: "/some/existing/file",
308+
},
309+
},
310+
error: "kube.config supplied but kube.enable set to false",
311+
}, {
312+
name: "kube not enabled, nodeName supplied",
313+
config: &Config{
314+
Kube: Kube{
315+
Node: "dummyNode",
316+
},
317+
},
318+
error: "kube.node-name supplied but kube.enable set to false",
294319
}}
295320

296321
// test yaml marshall

go.mod

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,94 @@
11
module github.com/sustainable-computing-io/kepler
22

3-
go 1.23
3+
go 1.23.0
44

55
toolchain go1.23.3
66

77
require (
88
dario.cat/mergo v1.0.2
99
github.com/alecthomas/kingpin/v2 v2.4.0
10+
github.com/go-logr/logr v1.4.2
1011
github.com/oklog/run v1.1.0
1112
github.com/olekukonko/tablewriter v1.0.5
1213
github.com/prometheus/client_golang v1.22.0
1314
github.com/prometheus/client_model v0.6.1
1415
github.com/prometheus/exporter-toolkit v0.14.0
1516
github.com/prometheus/procfs v0.15.1
1617
github.com/stretchr/testify v1.10.0
17-
golang.org/x/sync v0.10.0
18+
go.uber.org/zap v1.26.0
19+
golang.org/x/sync v0.12.0
1820
gopkg.in/yaml.v3 v3.0.1
21+
k8s.io/api v0.31.0
22+
k8s.io/apimachinery v0.31.0
23+
k8s.io/client-go v0.31.0
1924
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e
25+
sigs.k8s.io/controller-runtime v0.19.0
2026
)
2127

2228
require (
2329
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
2430
github.com/beorn7/perks v1.0.1 // indirect
2531
github.com/cespare/xxhash/v2 v2.3.0 // indirect
2632
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
27-
github.com/davecgh/go-spew v1.1.1 // indirect
33+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
34+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
35+
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
2836
github.com/fatih/color v1.15.0 // indirect
37+
github.com/fsnotify/fsnotify v1.7.0 // indirect
38+
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
39+
github.com/go-logr/zapr v1.3.0 // indirect
40+
github.com/go-openapi/jsonpointer v0.19.6 // indirect
41+
github.com/go-openapi/jsonreference v0.20.2 // indirect
42+
github.com/go-openapi/swag v0.22.4 // indirect
43+
github.com/gogo/protobuf v1.3.2 // indirect
44+
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
45+
github.com/golang/protobuf v1.5.4 // indirect
46+
github.com/google/gnostic-models v0.6.8 // indirect
47+
github.com/google/go-cmp v0.7.0 // indirect
48+
github.com/google/gofuzz v1.2.0 // indirect
49+
github.com/google/uuid v1.6.0 // indirect
50+
github.com/imdario/mergo v0.3.6 // indirect
51+
github.com/josharian/intern v1.0.0 // indirect
2952
github.com/jpillora/backoff v1.0.0 // indirect
53+
github.com/json-iterator/go v1.1.12 // indirect
54+
github.com/mailru/easyjson v0.7.7 // indirect
3055
github.com/mattn/go-colorable v0.1.13 // indirect
3156
github.com/mattn/go-isatty v0.0.19 // indirect
3257
github.com/mattn/go-runewidth v0.0.16 // indirect
3358
github.com/mdlayher/socket v0.4.1 // indirect
3459
github.com/mdlayher/vsock v1.2.1 // indirect
60+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
61+
github.com/modern-go/reflect2 v1.0.2 // indirect
3562
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
3663
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
3764
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 // indirect
3865
github.com/olekukonko/ll v0.0.7 // indirect
39-
github.com/pmezard/go-difflib v1.0.0 // indirect
66+
github.com/pkg/errors v0.9.1 // indirect
67+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
4068
github.com/prometheus/common v0.62.0 // indirect
4169
github.com/rivo/uniseg v0.2.0 // indirect
70+
github.com/spf13/pflag v1.0.5 // indirect
4271
github.com/stretchr/objx v0.5.2 // indirect
72+
github.com/x448/float16 v0.8.4 // indirect
4373
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
74+
go.uber.org/multierr v1.11.0 // indirect
4475
golang.org/x/crypto v0.32.0 // indirect
76+
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect
4577
golang.org/x/net v0.33.0 // indirect
4678
golang.org/x/oauth2 v0.24.0 // indirect
4779
golang.org/x/sys v0.30.0 // indirect
80+
golang.org/x/term v0.28.0 // indirect
4881
golang.org/x/text v0.21.0 // indirect
82+
golang.org/x/time v0.3.0 // indirect
83+
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
4984
google.golang.org/protobuf v1.36.5 // indirect
85+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
86+
gopkg.in/inf.v0 v0.9.1 // indirect
5087
gopkg.in/yaml.v2 v2.4.0 // indirect
88+
k8s.io/apiextensions-apiserver v0.31.0 // indirect
89+
k8s.io/klog/v2 v2.130.1 // indirect
90+
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
91+
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
92+
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
93+
sigs.k8s.io/yaml v1.4.0 // indirect
5194
)

0 commit comments

Comments
 (0)