in pkg/trimaran/lowriskovercommitment/lowriskovercommitment.go [171:254]
func (pl *LowRiskOverCommitment) computeRisk(metrics []watcher.Metric, resourceName v1.ResourceName,
resourceType string, node *v1.Node, nodeRequestsAndLimits *trimaran.NodeRequestsAndLimits) float64 {
var riskLimit, riskLoad, totalRisk float64
defer func() {
klog.V(6).InfoS("Calculated risk", "node", klog.KObj(node), "resource", resourceName,
"riskLimit", riskLimit, "riskLoad", riskLoad, "totalRisk", totalRisk)
}()
nodeRequest := nodeRequestsAndLimits.NodeRequest
nodeLimit := nodeRequestsAndLimits.NodeLimit
nodeRequestMinusPod := nodeRequestsAndLimits.NodeRequestMinusPod
nodeLimitMinusPod := nodeRequestsAndLimits.NodeLimitMinusPod
nodeCapacity := nodeRequestsAndLimits.Nodecapacity
var request, limit, capacity, requestMinusPod, limitMinusPod int64
if resourceName == v1.ResourceCPU {
request = nodeRequest.MilliCPU
limit = nodeLimit.MilliCPU
requestMinusPod = nodeRequestMinusPod.MilliCPU
limitMinusPod = nodeLimitMinusPod.MilliCPU
capacity = nodeCapacity.MilliCPU
} else if resourceName == v1.ResourceMemory {
request = nodeRequest.Memory
limit = nodeLimit.Memory
requestMinusPod = nodeRequestMinusPod.Memory
limitMinusPod = nodeLimitMinusPod.Memory
capacity = nodeCapacity.Memory
} else {
// invalid resource
klog.V(6).InfoS("Unexpected resource", "resourceName", resourceName)
return 0
}
// (1) riskLimit : calculate overcommit potential load
if limit > capacity {
riskLimit = float64(limit-capacity) / float64(limit-request)
}
klog.V(6).InfoS("RiskLimit", "node", klog.KObj(node), "resource", resourceName, "riskLimit", riskLimit)
// (2) riskLoad : calculate measured overcommitment
zeroRequest := &framework.Resource{}
stats, ok := trimaran.CreateResourceStats(metrics, node, zeroRequest, resourceName, resourceType)
if ok {
// fit a beta distribution to the measured load stats
mu, sigma := trimaran.GetMuSigma(stats)
// adjust standard deviation due to data smoothing
sigma *= math.Pow(float64(pl.args.SmoothingWindowSize), 0.5)
// limit the standard deviation close to the allowed maximum for the beta distribution
sigma = math.Min(sigma, math.Sqrt(GetMaxVariance(mu)*MaxVarianceAllowance))
// calculate area under beta probability curve beyond total allocated, as overuse risk measure
allocThreshold := float64(requestMinusPod) / float64(capacity)
allocThreshold = math.Min(math.Max(allocThreshold, 0), 1)
allocProb, fitDistribution := ComputeProbability(mu, sigma, allocThreshold)
if fitDistribution != nil {
klog.V(6).InfoS("FitDistribution", "node", klog.KObj(node), "resource", resourceName, "dist", fitDistribution.Print())
}
// condition the probability in case total limit is less than capacity
if limitMinusPod < capacity && requestMinusPod <= limitMinusPod {
limitThreshold := float64(limitMinusPod) / float64(capacity)
if limitThreshold == 0 {
allocProb = 1 // zero over zero
} else if fitDistribution != nil {
limitProb := fitDistribution.DistributionFunction(limitThreshold)
if limitProb > 0 {
allocProb /= limitProb
allocProb = math.Min(math.Max(allocProb, 0), 1)
}
}
}
// calculate risk
riskLoad = 1 - allocProb
klog.V(6).InfoS("RiskLoad", "node", klog.KObj(node), "resource", resourceName,
"allocThreshold", allocThreshold, "allocProb", allocProb, "riskLoad", riskLoad)
}
// combine two components of risk into a total risk as a weighted sum
w := pl.riskLimitWeightsMap[resourceName]
totalRisk = w*riskLimit + (1-w)*riskLoad
totalRisk = math.Min(math.Max(totalRisk, 0), 1)
return totalRisk
}