~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
80 lines · 1.6 KB Raw History
package cloudprovider

import (
	corev1 "k8s.io/api/core/v1"

	"github.com/johnandersen777/socialweb-computer-kcp/internal/scale"
)

type Pressure struct {
	Pending int

	Running int

	Nodes int

	AllocatablePods int

	AllocatableCPUMilli int64

	AllocatableMemoryBytes int64
}

func Measure(pods []corev1.Pod, nodes []corev1.Node) Pressure {
	var p Pressure
	p.Nodes = len(nodes)
	for i := range nodes {
		n := &nodes[i]
		if !nodeReady(n) {
			continue
		}
		podCap := n.Status.Allocatable[corev1.ResourcePods]
		cpuCap := n.Status.Allocatable[corev1.ResourceCPU]
		memCap := n.Status.Allocatable[corev1.ResourceMemory]
		p.AllocatablePods += int(podCap.Value())
		p.AllocatableCPUMilli += cpuCap.MilliValue()
		p.AllocatableMemoryBytes += memCap.Value()
	}
	for i := range pods {
		pod := &pods[i]
		if scale.AppliedByTheControlPlane(pod.ObjectMeta) {
			continue
		}
		switch pod.Status.Phase {
		case corev1.PodSucceeded, corev1.PodFailed:
			continue
		case corev1.PodPending:
			if pod.Spec.NodeName == "" {
				p.Pending++
			}
		case corev1.PodRunning:
			p.Running++
		}
	}
	return p
}

func Target(p Pressure, current, maxNodes, podsPerNode int) int {
	work := p.Pending + p.Running
	if work == 0 {
		return 0
	}
	if podsPerNode <= 0 {
		return current
	}
	if maxNodes < 1 {
		return current
	}
	want := min(max((work+podsPerNode-1)/podsPerNode, 1), maxNodes)
	return want
}

func nodeReady(n *corev1.Node) bool {
	for i := range n.Status.Conditions {
		c := &n.Status.Conditions[i]
		if c.Type == corev1.NodeReady {
			return c.Status == corev1.ConditionTrue
		}
	}
	return false
}