Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release v1.2.0 #4

Merged
merged 1 commit into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions client/clientset/versioned/fake/register.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions client/clientset/versioned/scheme/register.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion extension/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import corev1 "k8s.io/api/core/v1"

const (
DomainPrefix = "koordinator.sh/"
// use prefix "kubernetes.io/" for extend resource
// ResourceDomainPrefix is a prefix "kubernetes.io/" used by particular extend resources (e.g. batch resources)
ResourceDomainPrefix = corev1.ResourceDefaultNamespacePrefix
// SchedulingDomainPrefix represents the scheduling domain prefix
SchedulingDomainPrefix = "scheduling.koordinator.sh"
Expand Down
68 changes: 68 additions & 0 deletions extension/deprecated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright 2022 The Koordinator Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package extension

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

const (
// Deprecated: because of the limitation of extended resource naming
KoordBatchCPU corev1.ResourceName = DomainPrefix + "batch-cpu"
// Deprecated: because of the limitation of extended resource naming
KoordBatchMemory corev1.ResourceName = DomainPrefix + "batch-memory"

// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedKoordRDMA corev1.ResourceName = ResourceDomainPrefix + "rdma"
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedKoordFPGA corev1.ResourceName = ResourceDomainPrefix + "fpga"
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedKoordGPU corev1.ResourceName = ResourceDomainPrefix + "gpu"
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedGPUCore corev1.ResourceName = ResourceDomainPrefix + "gpu-core"
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedGPUMemory corev1.ResourceName = ResourceDomainPrefix + "gpu-memory"
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedGPUMemoryRatio corev1.ResourceName = ResourceDomainPrefix + "gpu-memory-ratio"
)

const (
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedGPUDriver string = ResourceDomainPrefix + "gpu-driver"
// Deprecated: Device extension resource names should use the prefix `koordinator.sh`
DeprecatedGPUModel string = ResourceDomainPrefix + "gpu-model"
)

var deprecatedDeviceResourceNameMapper = map[corev1.ResourceName]corev1.ResourceName{
DeprecatedKoordRDMA: ResourceRDMA,
DeprecatedKoordFPGA: ResourceFPGA,
DeprecatedKoordGPU: ResourceGPU,
DeprecatedGPUCore: ResourceGPUCore,
DeprecatedGPUMemory: ResourceGPUMemory,
DeprecatedGPUMemoryRatio: ResourceGPUMemoryRatio,
}

func TransformDeprecatedDeviceResources(resList corev1.ResourceList) corev1.ResourceList {
r := make(corev1.ResourceList, len(resList))
for k, v := range resList {
newResName := deprecatedDeviceResourceNameMapper[k]
if newResName != "" {
r[newResName] = v
} else {
r[k] = v
}
}
return r
}
91 changes: 91 additions & 0 deletions extension/descheduling.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
Copyright 2022 The Koordinator Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package extension

import (
"encoding/json"
"fmt"
"strconv"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
// AnnotationEvictionCost indicates the eviction cost. It can be used to set to an int32.
// Although the K8s community has [Pod Deletion Cost #2255](https://github.com/kubernetes/enhancements/issues/2255),
// it is not a general mechanism. To avoid conflicts with components that use `Pod Deletion Cost`,
// users can individually mark the eviction cost for Pods.
// The implicit eviction cost for pods that don't set the annotation is 0, negative values are permitted.
// If set the cost with `math.MaxInt32`, it means the Pod will not be evicted.
// Pods with lower eviction cost are preferred to be evicted before pods with higher eviction cost.
// If a batch of Pods to be evicted have the same priority, they will be sorted by cost,
// and the Pod with the smallest cost will be evicted.
AnnotationEvictionCost = SchedulingDomainPrefix + "/eviction-cost"
)

const (
// AnnotationSoftEviction indicates custom eviction. It can be used to set to an "true".
AnnotationSoftEviction = SchedulingDomainPrefix + "/soft-eviction"
)

type SoftEvictionSpec struct {
// Timestamp indicates time when custom eviction occurs . It can be used to set a second timestamp.
Timestamp *metav1.Time `json:"timestamp,omitempty"`
// DeleteOptions indicates the options to delete the pod.
DeleteOptions *metav1.DeleteOptions `json:"deleteOptions,omitempty"`
// Initiator indicates the initiator of the eviction.
Initiator string `json:"initiator,omitempty"`
// Reason indicates reason for eviction.
Reason string `json:"reason,omitempty"`
}

func GetSoftEvictionSpec(annotations map[string]string) (*SoftEvictionSpec, error) {
evictionSpec := &SoftEvictionSpec{}
data, ok := annotations[AnnotationSoftEviction]
if !ok {
return evictionSpec, nil
}
err := json.Unmarshal([]byte(data), evictionSpec)
if err != nil {
return evictionSpec, err
}
return evictionSpec, err
}

func GetEvictionCost(annotations map[string]string) (int32, error) {
if value, exist := annotations[AnnotationEvictionCost]; exist {
// values that start with plus sign (e.g, "+10") or leading zeros (e.g., "008") are not valid.
if !validFirstDigit(value) {
return 0, fmt.Errorf("invalid value %q", value)
}

i, err := strconv.ParseInt(value, 10, 32)
if err != nil {
// make sure we default to 0 on error.
return 0, err
}
return int32(i), nil
}
return 0, nil
}

func validFirstDigit(str string) bool {
if len(str) == 0 {
return false
}
return str[0] == '-' || (str[0] == '0' && str == "0") || (str[0] >= '1' && str[0] <= '9')
}
6 changes: 3 additions & 3 deletions extension/elastic_quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import (

// RootQuotaName means quotaTree's root\head.
const (
SystemQuotaName = "system"
RootQuotaName = "root"
DefaultQuotaName = "default"
SystemQuotaName = "koordinator-system-quota"
RootQuotaName = "koordinator-root-quota"
DefaultQuotaName = "koordinator-default-quota"
QuotaKoordinatorPrefix = "quota.scheduling.koordinator.sh"
LabelQuotaIsParent = QuotaKoordinatorPrefix + "/is-parent"
LabelQuotaParent = QuotaKoordinatorPrefix + "/parent"
Expand Down
73 changes: 73 additions & 0 deletions extension/node_reservation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
Copyright 2022 The Koordinator Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package extension

import (
"encoding/json"
"math"

corev1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
)

const (
AnnotationNodeReservation = NodeDomainPrefix + "/reservation"
)

// NodeReservation resource reserved by node.annotation,
// If node.annotation declares the resources to be reserved, like this:
// annotations:
// node.koordinator.sh/reservation: >-
// {"reservedCPUs":"0-5"}

// In the filter phase it needs to satisfy: node.alloc - node.req - reserved(6c) > pod.req
// if qos==LSE/LSR: the cores 0-5 are not used in the reserve phase
type NodeReservation struct {
// resources need to be reserved. like, {"cpu":"1C", "memory":"2Gi"}
Resources corev1.ResourceList `json:"resources,omitempty"`
// reserved cpus need to be reserved, such as 1-6, or 2,4,6,8
ReservedCPUs string `json:"reservedCPUs,omitempty"`
}

func GetReservedCPUs(anno map[string]string) (string, int) {
specificCPUsReservedStr := ""
numReservedCPUs := 0

val, ok := anno[AnnotationNodeReservation]
if !ok || val == "" {
return specificCPUsReservedStr, numReservedCPUs
}

reserved := NodeReservation{}
if err := json.Unmarshal([]byte(val), &reserved); err != nil {
klog.Errorf("failed to unmarshal reserved resources from node.annotation in nodenumaresource scheduler plugin.err:%v", err)
return specificCPUsReservedStr, numReservedCPUs
}

CPUsQuantityReserved, ok := reserved.Resources[corev1.ResourceCPU]
if ok && CPUsQuantityReserved.MilliValue() > 0 {
reservedCPUsFloat := float64(CPUsQuantityReserved.MilliValue()) / 1000
numReservedCPUs = int(math.Ceil(reservedCPUsFloat))
}

if reserved.ReservedCPUs != "" {
numReservedCPUs = 0
}
specificCPUsReservedStr = reserved.ReservedCPUs

return specificCPUsReservedStr, numReservedCPUs
}
1 change: 1 addition & 0 deletions extension/priority.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

type PriorityClass string

// https://koordinator.sh/docs/architecture/priority/
const (
PriorityProd PriorityClass = "koord-prod"
PriorityMid PriorityClass = "koord-mid"
Expand Down
18 changes: 1 addition & 17 deletions extension/qos.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ limitations under the License.

package extension

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

type QoSClass string

// https://koordinator.sh/docs/architecture/qos/
const (
QoSLSE QoSClass = "LSE"
QoSLSR QoSClass = "LSR"
Expand All @@ -29,21 +28,6 @@ const (
QoSNone QoSClass = ""
)

func GetPodQoSClass(pod *corev1.Pod) QoSClass {
if pod == nil || pod.Labels == nil {
return QoSNone
}
return GetQoSClassByAttrs(pod.Labels, pod.Annotations)
}

func GetQoSClassByAttrs(labels, annotations map[string]string) QoSClass {
// annotations are for old format adaption reason
if q, exist := labels[LabelPodQoS]; exist {
return GetPodQoSClassByName(q)
}
return QoSNone
}

func GetPodQoSClassByName(qos string) QoSClass {
q := QoSClass(qos)

Expand Down
36 changes: 36 additions & 0 deletions extension/qos_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright 2022 The Koordinator Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package extension

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

// NOTE: functions in this file can be overwritten for extension

func GetPodQoSClass(pod *corev1.Pod) QoSClass {
if pod == nil || pod.Labels == nil {
return QoSNone
}
return GetQoSClassByAttrs(pod.Labels, pod.Annotations)
}

func GetQoSClassByAttrs(labels, annotations map[string]string) QoSClass {
// annotations are for old format adaption reason
if q, exist := labels[LabelPodQoS]; exist {
return GetPodQoSClassByName(q)
}
return QoSNone
}
Loading