Create Scheduler Logic
Here are a few CRDs that can affect scheduling:
Score
apiVersion: arbiter.k8s.com.cn/v1alpha1
kind: Score
metadata:
name: least-allocated
namespace: kube-system
spec:
weight: 100
logic: |
// Feel free to modify Score.spec.logic to suit your needs.
// Must include a function named `score`, this score function replaces the
// default score function in the scheduling framework. It inputs the pod and
// node to be scheduled, and outputs a number (0 to 100). The higher the
// number, the more the pod tends to be scheduled to this node.
// The following example shows the JS version of default parameter of the
// algorithm `LeastAllocated` in kubernetes scheduling.
function getPodCpuMemReq() {
const DefaultCPUReq = 100; // 0.1 core
const DefaultMemReq = 200 * 1024 * 1024; // 200MB
var podContainer = pod.raw.spec.containers;
if (podContainer == undefined) {
return [DefaultCPUReq, DefaultMemReq];
}
var cpuReq = 0;
var memReq = 0;
for (var i = 0; i < podContainer.length; i++) {
var resources = podContainer[i].resources;
if (resources.requests == undefined) {
cpuReq += DefaultCPUReq;
memReq += DefaultMemReq;
continue
}
cpuReq += cpuParser(resources.requests.cpu);
memReq += memParser(resources.requests.memory);
}
var podInitContainers = pod.raw.spec.initContainers;
if (podInitContainers == undefined) {
return [cpuReq, memReq];
}
var initCPUReq = 0;
var initMemReq = 0;
for (var i = 0; i < podInitContainers.length; i++) {
var resources = podInitContainers[i].resources;
if (resources.requests == undefined) {
initCPUReq = DefaultCPUReq;
initMemReq = DefaultMemReq;
} else {
initCPUReq = cpuParser(resources.requests.cpu);
}
if (initCPUReq > cpuReq) {
cpuReq = initCPUReq;
}
if (initMemReq > memReq) {
memReq = initMemReq;
}
}
return [cpuReq, memReq];
}
function cpuParser(input) {
const milliMatch = input.match(/^([0-9]+)m$/);
if (milliMatch) {
return parseInt(milliMatch[1]);
}
return parseFloat(input) * 1000;
}
function memParser(input) {
const memoryMultipliers = {
k: 1000, M: 1000 ** 2, G: 1000 ** 3, Ki: 1024, Mi: 1024 ** 2, Gi: 1024 ** 3,
};
const unitMatch = input.match(/^([0-9]+)([A-Za-z]{1,2})$/);
if (unitMatch) {
return parseInt(unitMatch[1], 10) * memoryMultipliers[unitMatch[2]];
}
return parseInt(input, 10);
}
function score() {
var podReq = getPodCpuMemReq();
var podName = pod.raw.metadata.name;
var podNS = pod.raw.metadata.namespace;
var podCPUReq = podReq[0];
var podMemReq = podReq[1];
var nodeName = node.raw.metadata.name;
var nodeCapacity = node.raw.status.allocatable;
var nodeCPUCap = cpuParser(nodeCapacity.cpu);
var nodeMemCap = memParser(nodeCapacity.memory);
var nodeCPUReq = parseInt(node.cpuReq);
var nodeMemReq = parseInt(node.memReq);
// LeastAllocated
var cpuScore = (nodeCPUCap - nodeCPUReq - podCPUReq) / nodeCPUCap;
console.log('[arbiter-js] podName:', podNS+'/'+podName, 'nodeName', nodeName, 'cpuScore:', cpuScore, 'nodeCPUCap', nodeCPUCap, 'nodeCPUReq', nodeCPUReq, 'podCPUReq', podCPUReq);
var memScore = (nodeMemCap - nodeMemReq - podMemReq) / nodeMemCap;
console.log('[arbiter-js] podName:', podNS+'/'+podName, 'nodeName', nodeName, 'memScore:', memScore, 'nodeMemCap', nodeMemCap, 'nodeMemReq', nodeMemReq, 'podMemReq', podMemReq);
return (cpuScore + memScore) / 2 * 100;
}
- Each
Score
CR represents a [Scoring step] in the kube-scheduler (kube-scheduler-implementation. - Multiple
Score
CRs can be created, and when scheduling, allScore
CRs in the namespace of the pod to be scheduled are used for calculation. The final weighted value is calculated based on thespec.weight
of eachScore
CR, and the pod is scheduled to the node with the highest weighted value.- If there are no
Score
CRs in the namespace of the pod to be scheduled, theScore
CRs in the namespace of the Arbiter-Scheduler are used for calculation - And if there are still no
Score
CRs in the Arbiter-Scheduler namespace, theScore
CRs in the kube-system namespace are used for calculation.
- If there are no
spec.weight
represents the weight of the currentScore
CR to the total result, it is an integer, if it is 0 or negative, it means the currentScore
CR is not valid.spec.logic
is actually a file that asks for a complete JS function with the namescore
.- Feel free to modify this
score
function to meet scheduling needs. - This scoring function replaces the default scoring function in the scheduling framework.
- It inputs the pod and node to be scheduled and outputs a number (0 to 100).
- The higher the number, the more the pod tends to be scheduled to that node.
pod
is actually an object in JS, with full manifest information. It is somewhat similar to the result ofkubectl get po -o json
, for example,pod.labels
will show the pod's labels.node
is the same.- Specifically,
node.obi.<OBI-Namespace>-<OBI-Name>
gets an instance of the OBI mentioned in the previous section and requires that theobi.Spec.TargetRef.Name
of this OBI is also written as the name of the current Name` is also the name of the current node.
- Feel free to modify this