Skip to content

Commit

Permalink
Merge pull request #4 from AndreZiviani/requests-metrics
Browse files Browse the repository at this point in the history
feat: Export pod resource requests cost as metric
  • Loading branch information
AndreZiviani authored Dec 31, 2022
2 parents d45de01 + e2f79fc commit 94a5820
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 29 deletions.
12 changes: 12 additions & 0 deletions exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ func (e *Exporter) initGauges() {
Name: "pod_cpu",
Help: "Cost of the pod cpu usage.",
}, []string{"pod", "namespace", "kind", "type"})

e.pricingMetrics["pod_memory_requests"] = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "pod_memory_requests",
Help: "Cost of the pod memory requests.",
}, []string{"pod", "namespace", "kind", "type"})

e.pricingMetrics["pod_cpu_requests"] = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "pod_cpu_requests",
Help: "Cost of the pod cpu requests.",
}, []string{"pod", "namespace", "kind", "type"})
}

// Describe outputs metric descriptions.
Expand Down
39 changes: 33 additions & 6 deletions exporter/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ func (m *Metrics) podUpdated(oldObj, newObj interface{}) {
}

if len(newPod.Spec.NodeName) > 0 {
m.Pods[newPod.ObjectMeta.Namespace+"/"+newPod.ObjectMeta.Name].Node = m.Nodes[newPod.Spec.NodeName]
pod := m.Pods[newPod.ObjectMeta.Namespace+"/"+newPod.ObjectMeta.Name]
pod.Node = m.Nodes[newPod.Spec.NodeName]
m.updatePodCost(pod)
return
}
}
Expand All @@ -96,8 +98,10 @@ func (m *Metrics) podCreated(obj interface{}) {
Memory: resource.NewQuantity(0, resource.BinarySI),
},
}

m.podsMtx.Lock()
m.Pods[pod.ObjectMeta.Namespace+"/"+pod.ObjectMeta.Name] = &tmp
m.updatePodCost(&tmp)
m.podsMtx.Unlock()
}

Expand Down Expand Up @@ -199,7 +203,7 @@ func (m Metrics) mergeResources(containers []corev1.Container) *PodResources {
return &resources
}

func (m *Metrics) GetUsage(ctx context.Context) {
func (m *Metrics) GetUsageCost(ctx context.Context) {
podMetricsList, err := m.metrics.MetricsV1beta1().PodMetricses("").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
Expand All @@ -209,12 +213,35 @@ func (m *Metrics) GetUsage(ctx context.Context) {
name := pod.GetName()
namespace := pod.GetNamespace()

m.Pods[namespace+"/"+name].Usage.Cpu.Reset()
m.Pods[namespace+"/"+name].Usage.Memory.Reset()
me := m.Pods[namespace+"/"+name]
me.Usage.Cpu.Reset()
me.Usage.Memory.Reset()

for _, container := range pod.Containers {
m.Pods[namespace+"/"+name].Usage.Cpu.Add(container.Usage["cpu"])
m.Pods[namespace+"/"+name].Usage.Memory.Add(container.Usage["memory"])
me.Usage.Cpu.Add(container.Usage["cpu"])
me.Usage.Memory.Add(container.Usage["memory"])
}

m.updatePodCost(me)
}
}

func (m *Metrics) updatePodCost(pod *Pod) {
if pod.Node == nil {
pod.MemoryCost = float64(0)
pod.VCpuCost = float64(0)
pod.MemoryRequestsCost = float64(0)
pod.VCpuRequestsCost = float64(0)

return
}
// convert bytes to GB
pod.MemoryCost = float64(pod.Usage.Memory.Value()) / 1024 / 1024 / 1024 * pod.Node.Instance.MemoryCost
pod.MemoryRequestsCost = float64(pod.Resources.Memory.Value()) / 1024 / 1024 / 1024 * pod.Node.Instance.MemoryCost

//convert millicore to core
pod.VCpuCost = float64(pod.Usage.Cpu.MilliValue()) / 1000 * pod.Node.Instance.VCpuCost
pod.VCpuRequestsCost = float64(pod.Resources.Cpu.MilliValue()) / 1000 * pod.Node.Instance.VCpuCost

pod.Cost = pod.MemoryCost + pod.VCpuCost
}
14 changes: 0 additions & 14 deletions exporter/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,3 @@ func (m *Metrics) init(ctx context.Context) {
m.GetNodes(ctx)
m.GetPods(ctx)
}

func (m *Metrics) GetCost(ctx context.Context) {
m.GetUsage(ctx)

for _, pod := range m.Pods {
// convert bytes to GB
pod.MemoryCost = float64(pod.Usage.Memory.Value()) / 1024 / 1024 / 1024 * pod.Node.Instance.MemoryCost

//convert millicore to core
pod.VCpuCost = float64(pod.Usage.Cpu.MilliValue()) / 1000 * pod.Node.Instance.VCpuCost

pod.Cost = pod.MemoryCost + pod.VCpuCost
}
}
18 changes: 17 additions & 1 deletion exporter/scrape.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (e *Exporter) scrape(scrapes chan<- scrapeResult) {

var errorCount uint64

e.metrics.GetCost(context.TODO())
e.metrics.GetUsageCost(context.TODO())

for _, pod := range e.metrics.Pods {
scrapes <- scrapeResult{
Expand All @@ -44,6 +44,22 @@ func (e *Exporter) scrape(scrapes chan<- scrapeResult) {
Kind: pod.Node.Instance.Kind,
Type: pod.Node.Instance.Type,
}
scrapes <- scrapeResult{
Name: "pod_cpu_requests",
Value: pod.VCpuRequestsCost,
Pod: pod.Name,
Namespace: pod.Namespace,
Kind: pod.Node.Instance.Kind,
Type: pod.Node.Instance.Type,
}
scrapes <- scrapeResult{
Name: "pod_memory_requests",
Value: pod.MemoryRequestsCost,
Pod: pod.Name,
Namespace: pod.Namespace,
Kind: pod.Node.Instance.Kind,
Type: pod.Node.Instance.Type,
}
}

e.scrapeErrors.Set(float64(atomic.LoadUint64(&errorCount)))
Expand Down
18 changes: 10 additions & 8 deletions exporter/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ type Instance struct {
}

type Pod struct {
Name string
Namespace string
Resources *PodResources
Node *Node
Usage *PodResources
Cost float64
VCpuCost float64
MemoryCost float64
Name string
Namespace string
Resources *PodResources
Node *Node
Usage *PodResources
Cost float64
VCpuCost float64
MemoryCost float64
VCpuRequestsCost float64
MemoryRequestsCost float64
}

type Node struct {
Expand Down

0 comments on commit 94a5820

Please sign in to comment.