├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── OWNERS ├── README.md ├── RELEASE.md ├── SECURITY_CONTACTS ├── build ├── controller │ └── Dockerfile └── scheduler │ └── Dockerfile ├── cloudbuild.yaml ├── cmd ├── controller │ ├── app │ │ ├── import_known_versions.go │ │ ├── options.go │ │ └── server.go │ └── controller.go └── scheduler │ ├── main.go │ └── main_test.go ├── code-of-conduct.md ├── doc ├── adopters ├── develop.md ├── install.md └── release-guide.md ├── go.mod ├── go.sum ├── hack ├── boilerplate │ └── boilerplate.generatego.txt ├── install-etcd.sh ├── integration-test.sh ├── lib │ ├── etcd.sh │ ├── golang.sh │ ├── init.sh │ ├── logging.sh │ └── util.sh ├── openapi-violation.list ├── tools.go ├── unit-test.sh ├── update-codegen.sh ├── update-generated-openapi.sh ├── update-gofmt.sh ├── update-vendor.sh └── verify-gofmt.sh ├── kep ├── 119-node-resource-topology-aware-scheduling │ ├── README.md │ └── kep.yaml ├── 2-lightweight-coscheduling │ ├── README.md │ ├── design.png │ └── kep.yaml ├── 205-preemption-toleration │ ├── README.md │ └── kep.yaml ├── 217-resource-limit-aware-scorcing │ ├── README.md │ └── kep.yaml ├── 42-podgroup-coscheduling │ ├── README.md │ └── kep.yaml ├── 48-node-resources-allocatable-scoring │ ├── README.md │ └── kep.yaml ├── 61-Trimaran-real-load-aware-scheduling │ ├── README.md │ ├── images │ │ ├── design.png │ │ ├── image1.png │ │ ├── image2.png │ │ ├── image3.png │ │ ├── image4.png │ │ ├── image5.png │ │ ├── image6.png │ │ ├── image7.png │ │ ├── image8.png │ │ ├── image9.png │ │ ├── safe-sched-graph.png │ │ └── tlp-graph.png │ └── kep.yaml └── 9-capacity-scheduling │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ ├── 9.png │ ├── README.md │ └── kep.yaml ├── manifests ├── capacityscheduling │ ├── crd.yaml │ ├── elasticquota-example.yaml │ └── scheduler-config.yaml ├── coscheduling │ ├── crd.yaml │ └── scheduler-config.yaml ├── install │ ├── all-in-one.yaml │ └── charts │ │ └── as-a-second-scheduler │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates │ │ ├── _helpers.tpl │ │ ├── configmap.yaml │ │ ├── crds │ │ │ └── podgroup.yaml │ │ ├── deployment.yaml │ │ ├── rbac.yaml │ │ └── serviceaccount.yaml │ │ └── values.yaml ├── noderesources │ └── scheduler-config.yaml ├── noderesourcetopology │ ├── cluster-role.yaml │ ├── crd.yaml │ ├── deploy.yaml │ ├── ns.yaml │ ├── scheduler-config.yaml │ ├── scheduler-configmap.yaml │ ├── test-deployment.yaml │ ├── worker-node-A.yaml │ └── worker-node-B.yaml ├── podstate │ └── scheduler-config.yaml ├── qos │ └── scheduler-config.yaml └── trimaran │ └── scheduler-config.yaml ├── pkg ├── apis │ ├── config │ │ ├── doc.go │ │ ├── register.go │ │ ├── scheme │ │ │ └── scheme.go │ │ ├── types.go │ │ ├── v1beta1 │ │ │ ├── defaults.go │ │ │ ├── doc.go │ │ │ ├── register.go │ │ │ ├── types.go │ │ │ ├── zz_generated.conversion.go │ │ │ ├── zz_generated.deepcopy.go │ │ │ └── zz_generated.defaults.go │ │ └── zz_generated.deepcopy.go │ └── scheduling │ │ ├── register.go │ │ ├── scheme │ │ └── scheme.go │ │ └── v1alpha1 │ │ ├── doc.go │ │ ├── register.go │ │ ├── types.go │ │ └── zz_generated.deepcopy.go ├── capacityscheduling │ ├── README.md │ ├── candidate.go │ ├── capacity_scheduling.go │ ├── capacity_scheduling_test.go │ ├── elasticquota.go │ └── elasticquota_test.go ├── controller │ ├── elasticquota.go │ ├── elasticquota_test.go │ ├── podgroup.go │ └── podgroup_test.go ├── coscheduling │ ├── README.md │ ├── core │ │ ├── core.go │ │ └── core_test.go │ ├── coscheduling.go │ └── coscheduling_test.go ├── crossnodepreemption │ ├── README.md │ ├── candidate.go │ ├── cross_node_preemption.go │ └── cross_node_preemption_test.go ├── generated │ ├── clientset │ │ └── versioned │ │ │ ├── clientset.go │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── clientset_generated.go │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── typed │ │ │ └── scheduling │ │ │ └── v1alpha1 │ │ │ ├── doc.go │ │ │ ├── elasticquota.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── fake_elasticquota.go │ │ │ ├── fake_podgroup.go │ │ │ └── fake_scheduling_client.go │ │ │ ├── generated_expansion.go │ │ │ ├── podgroup.go │ │ │ └── scheduling_client.go │ ├── informers │ │ └── externalversions │ │ │ ├── factory.go │ │ │ ├── generic.go │ │ │ ├── internalinterfaces │ │ │ └── factory_interfaces.go │ │ │ └── scheduling │ │ │ ├── interface.go │ │ │ └── v1alpha1 │ │ │ ├── elasticquota.go │ │ │ ├── interface.go │ │ │ └── podgroup.go │ └── listers │ │ └── scheduling │ │ └── v1alpha1 │ │ ├── elasticquota.go │ │ ├── expansion_generated.go │ │ └── podgroup.go ├── noderesources │ ├── README.md │ ├── allocatable.go │ ├── allocatable_test.go │ └── resource_allocation.go ├── noderesourcetopology │ ├── README.md │ ├── filter.go │ ├── filter_test.go │ └── numa-topology.png ├── podstate │ ├── README.md │ ├── pod_state.go │ └── pod_state_test.go ├── qos │ ├── README.md │ ├── queue_sort.go │ └── queue_sort_test.go ├── trimaran │ ├── README.md │ ├── docs │ │ ├── load-watcher-library.png │ │ └── load-watcher-service.png │ ├── handler.go │ ├── handler_test.go │ ├── loadvariationriskbalancing │ │ ├── README.md │ │ ├── analysis.go │ │ ├── analysis_test.go │ │ ├── collector.go │ │ ├── collector_test.go │ │ ├── loadvariationriskbalancing.go │ │ └── loadvariationriskbalancing_test.go │ └── targetloadpacking │ │ ├── README.md │ │ ├── targetloadpacking.go │ │ └── targetloadpacking_test.go └── util │ ├── constants.go │ ├── podgroup.go │ └── podgroup_test.go └── test ├── integration ├── allocatable_test.go ├── base.go ├── capacity_scheduling_test.go ├── coscheduling_test.go ├── cross_node_preemption_test.go ├── elasticquota_controller_test.go ├── loadVariationRiskBalancing_test.go ├── main_test.go ├── noderesourcetopology_test.go ├── pod_state_test.go ├── qos_test.go └── targetloadpacking_test.go └── util ├── aggregator.go ├── apiserver.go ├── extension.go ├── fake.go ├── fixtures.go ├── framework.go ├── scheduler.go └── utils.go /.gitignore: -------------------------------------------------------------------------------- 1 | # build and test outputs 2 | /bin/ 3 | /_output/ 4 | /_artifacts/ 5 | /build/kube-scheduler 6 | 7 | # used for the code generators only 8 | /vendor/ 9 | 10 | # macOS 11 | .DS_Store 12 | 13 | # files generated by editors 14 | .idea/ 15 | *.iml 16 | .vscode/ 17 | *.swp 18 | *.sublime-project 19 | *.sublime-workspace 20 | *~ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://git.k8s.io/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: 4 | 5 | _As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ 6 | 7 | ## Getting Started 8 | 9 | We have full documentation on how to get started contributing here: 10 | 11 | 14 | 15 | - [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests 16 | - [Kubernetes Contributor Guide](https://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](https://git.k8s.io/community/contributors/guide#contributing) 17 | - [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md) - Common resources for existing developers 18 | 19 | ## Mentorship 20 | 21 | - [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! 22 | 23 | ## Contact Information 24 | 25 | - [Slack](https://kubernetes.slack.com/messages/sig-scheduling) 26 | - [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-scheduling) 27 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - ahg-g 5 | - Huang-Wei 6 | reviewers: 7 | - cwdsuzhou 8 | - denkensk 9 | - seanmalloy 10 | - yuanchen8911 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scheduler Plugins 2 | 3 | Repository for out-of-tree scheduler plugins based on the [scheduler framework](https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/). 4 | 5 | ## Install 6 | 7 | Container images are available in the official scheduler-plugins k8s container registry. There are two images one 8 | for the kube-scheduler and one for the controller. See the [Compatibility Matrix section](#compatibility-matrix) 9 | for the complete list of images. 10 | 11 | ```shell 12 | docker pull k8s.gcr.io/scheduler-plugins/kube-scheduler:$TAG 13 | docker pull k8s.gcr.io/scheduler-plugins/controller:$TAG 14 | ``` 15 | 16 | You can find [how to install release image](doc/install.md) here. 17 | 18 | ## Plugins 19 | 20 | The kube-scheduler binary includes the below list of plugins. They can be configured by creating one or more 21 | [scheduler profiles](https://kubernetes.io/docs/reference/scheduling/config/#multiple-profiles). 22 | 23 | * [Capacity Scheduling](pkg/capacityscheduling/README.md) 24 | * [Coscheduling](pkg/coscheduling/README.md) 25 | * [Node Resources](pkg/noderesources/README.md) 26 | * [Node Resource Topology](pkg/noderesourcetopology/README.md) 27 | * [Trimaran](pkg/trimaran/README.md) 28 | 29 | Additionally the kube-scheduler binary includes the below list of sample plugins. These plugins are not intended for use in production 30 | environments. 31 | 32 | * [Cross Node Preemption](pkg/crossnodepreemption/README.md) 33 | * [Pod State](pkg/podstate/README.md) 34 | * [Quality of Service](pkg/qos/README.md) 35 | 36 | ## Compatibility Matrix 37 | 38 | The below compatibility matrix shows the k8s client package (client-go, apimachinery, etc) versions 39 | that the scheduler-plugins are compiled with. 40 | 41 | The minor version of the scheduler-plugins matches the minor version of the k8s client packages that 42 | it is compiled with. For example scheduler-plugins `v0.18.x` releases are built with k8s `v1.18.x` 43 | dependencies. 44 | 45 | The scheduler-plugins patch versions come in two different varieties (single digit or three digits). 46 | The single digit patch versions (e.g., `v0.18.9`) exactly align with the the k8s client package 47 | versions that the scheduler plugins are built with. The three digit patch versions, which are built 48 | on demand, (e.g., `v0.18.800`) are used to indicated that the k8s client package versions have not 49 | changed since the previous release, and that only scheduler plugins code (features or bug fixes) was 50 | changed. 51 | 52 | Scheduler Plugins | Compiled With k8s Version | Container Image | Arch | 53 | -------------------|---------------------------|------------------------------------------------------|----------------| 54 | v0.20.10 | v1.20.10 | k8s.gcr.io/scheduler-plugins/kube-scheduler:v0.20.10 | AMD64
ARM64 | 55 | v0.19.9 | v1.19.9 | k8s.gcr.io/scheduler-plugins/kube-scheduler:v0.19.9 | AMD64
ARM64 | 56 | v0.19.8 | v1.19.8 | k8s.gcr.io/scheduler-plugins/kube-scheduler:v0.19.8 | AMD64
ARM64 | 57 | v0.18.9 | v1.18.9 | k8s.gcr.io/scheduler-plugins/kube-scheduler:v0.18.9 | AMD64 | 58 | 59 | Controller | Compiled With k8s Version | Container Image | Arch | 60 | -----------|---------------------------|--------------------------------------------------|----------------| 61 | v0.20.10 | v1.20.10 | k8s.gcr.io/scheduler-plugins/controller:v0.20.10 | AMD64
ARM64 | 62 | v0.19.9 | v1.19.9 | k8s.gcr.io/scheduler-plugins/controller:v0.19.9 | AMD64
ARM64 | 63 | v0.19.8 | v1.19.8 | k8s.gcr.io/scheduler-plugins/controller:v0.19.8 | AMD64
ARM64 | 64 | 65 | ## Community, discussion, contribution, and support 66 | 67 | Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). 68 | 69 | You can reach the maintainers of this project at: 70 | 71 | - [Slack](https://kubernetes.slack.com/messages/sig-scheduling) 72 | - [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-scheduling) 73 | 74 | You can find an [instruction how to build and run out-of-tree plugin here](doc/develop.md) . 75 | 76 | ### Code of conduct 77 | 78 | Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). 79 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Process 2 | 3 | The Kubernetes Template Project is released on an as-needed basis. The process is as follows: 4 | 5 | 1. An issue is proposing a new release with a changelog since the last release 6 | 1. All [OWNERS](OWNERS) must LGTM this release 7 | 1. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION` 8 | 1. The release issue is closed 9 | 1. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] kubernetes-template-project $VERSION is released` 10 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Committee to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | ahg-g 14 | Huang-Wei 15 | -------------------------------------------------------------------------------- /build/controller/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | ARG ARCH 15 | FROM golang:1.15.10 16 | 17 | WORKDIR /go/src/sigs.k8s.io/scheduler-plugins 18 | COPY . . 19 | ARG ARCH 20 | RUN make build-controller.$ARCH 21 | 22 | FROM $ARCH/alpine:3.12 23 | 24 | COPY --from=0 /go/src/sigs.k8s.io/scheduler-plugins/bin/controller /bin/controller 25 | 26 | WORKDIR /bin 27 | CMD ["controller"] 28 | -------------------------------------------------------------------------------- /build/scheduler/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | ARG ARCH 15 | FROM golang:1.15.10 16 | 17 | WORKDIR /go/src/sigs.k8s.io/scheduler-plugins 18 | COPY . . 19 | ARG ARCH 20 | ARG RELEASE_VERSION 21 | RUN RELEASE_VERSION=${RELEASE_VERSION} make build-scheduler.$ARCH 22 | 23 | FROM $ARCH/alpine:3.12 24 | 25 | COPY --from=0 /go/src/sigs.k8s.io/scheduler-plugins/bin/kube-scheduler /bin/kube-scheduler 26 | 27 | WORKDIR /bin 28 | CMD ["kube-scheduler"] 29 | -------------------------------------------------------------------------------- /cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # See https://cloud.google.com/cloud-build/docs/build-config 2 | 3 | # this must be specified in seconds. If omitted, defaults to 600s (10 mins) 4 | timeout: 2400s 5 | # this prevents errors if you don't use both _GIT_TAG and _PULL_BASE_REF, 6 | # or any new substitutions added in the future. 7 | options: 8 | substitution_option: ALLOW_LOOSE 9 | steps: 10 | - name: 'gcr.io/k8s-testimages/gcb-docker-gcloud:v20190906-745fed4' 11 | entrypoint: make 12 | env: 13 | - DOCKER_CLI_EXPERIMENTAL=enabled 14 | - RELEASE_VERSION=$_GIT_TAG 15 | - BASE_REF=$_PULL_BASE_REF 16 | args: 17 | - push-release-images 18 | substitutions: 19 | # _GIT_TAG will be filled with a git-based tag for the image, of the form vYYYYMMDD-hash, and 20 | # can be used as a substitution 21 | _GIT_TAG: '12345' 22 | # _PULL_BASE_REF will contain the ref that was pushed to to trigger this build - 23 | # a branch like 'master' or 'release-0.2', or a tag like 'v0.2'. 24 | _PULL_BASE_REF: 'master' 25 | -------------------------------------------------------------------------------- /cmd/controller/app/import_known_versions.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package app 18 | 19 | import ( 20 | _ "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/scheme" 21 | ) 22 | -------------------------------------------------------------------------------- /cmd/controller/app/options.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package app 18 | 19 | import ( 20 | "github.com/spf13/pflag" 21 | ) 22 | 23 | type ServerRunOptions struct { 24 | KubeConfig string 25 | MasterUrl string 26 | InCluster bool 27 | ApiServerQPS int 28 | ApiServerBurst int 29 | Workers int 30 | EnableLeaderElection bool 31 | } 32 | 33 | func NewServerRunOptions() *ServerRunOptions { 34 | options := &ServerRunOptions{} 35 | options.addAllFlags() 36 | return options 37 | } 38 | 39 | func (s *ServerRunOptions) addAllFlags() { 40 | pflag.BoolVar(&s.InCluster, "incluster", s.InCluster, "If controller run incluster.") 41 | pflag.StringVar(&s.KubeConfig, "kubeConfig", s.KubeConfig, "Kube Config path if not run in cluster.") 42 | pflag.StringVar(&s.MasterUrl, "masterUrl", s.MasterUrl, "Master Url if not run in cluster.") 43 | pflag.IntVar(&s.ApiServerQPS, "qps", 5, "qps of query apiserver.") 44 | pflag.IntVar(&s.ApiServerBurst, "burst", 10, "burst of query apiserver.") 45 | pflag.IntVar(&s.Workers, "workers", 1, "workers of scheduler-plugin-controllers.") 46 | pflag.BoolVar(&s.EnableLeaderElection, "enableLeaderElection", s.EnableLeaderElection, "If EnableLeaderElection for controller.") 47 | } 48 | -------------------------------------------------------------------------------- /cmd/controller/app/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package app 18 | 19 | import ( 20 | "context" 21 | "os" 22 | 23 | "k8s.io/apimachinery/pkg/util/uuid" 24 | "k8s.io/apiserver/pkg/server" 25 | "k8s.io/client-go/informers" 26 | "k8s.io/client-go/kubernetes" 27 | "k8s.io/client-go/rest" 28 | restclient "k8s.io/client-go/rest" 29 | "k8s.io/client-go/tools/clientcmd" 30 | "k8s.io/client-go/tools/leaderelection" 31 | "k8s.io/client-go/tools/leaderelection/resourcelock" 32 | "k8s.io/klog/v2" 33 | 34 | "sigs.k8s.io/scheduler-plugins/pkg/controller" 35 | schedclientset "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned" 36 | schedformers "sigs.k8s.io/scheduler-plugins/pkg/generated/informers/externalversions" 37 | ) 38 | 39 | func newConfig(kubeconfig, master string, inCluster bool) (*restclient.Config, error) { 40 | var ( 41 | config *rest.Config 42 | err error 43 | ) 44 | if inCluster { 45 | config, err = rest.InClusterConfig() 46 | } else { 47 | config, err = clientcmd.BuildConfigFromFlags(master, kubeconfig) 48 | } 49 | if err != nil { 50 | return nil, err 51 | } 52 | return config, nil 53 | } 54 | 55 | func Run(s *ServerRunOptions) error { 56 | ctx := context.Background() 57 | config, err := newConfig(s.KubeConfig, s.MasterUrl, s.InCluster) 58 | if err != nil { 59 | klog.Fatal(err) 60 | } 61 | config.QPS = float32(s.ApiServerQPS) 62 | config.Burst = s.ApiServerBurst 63 | stopCh := server.SetupSignalHandler() 64 | schedClient := schedclientset.NewForConfigOrDie(config) 65 | kubeClient := kubernetes.NewForConfigOrDie(config) 66 | 67 | schedInformerFactory := schedformers.NewSharedInformerFactory(schedClient, 0) 68 | pgInformer := schedInformerFactory.Scheduling().V1alpha1().PodGroups() 69 | eqInformer := schedInformerFactory.Scheduling().V1alpha1().ElasticQuotas() 70 | 71 | coreInformerFactory := informers.NewSharedInformerFactory(kubeClient, 0) 72 | podInformer := coreInformerFactory.Core().V1().Pods() 73 | pgCtrl := controller.NewPodGroupController(kubeClient, pgInformer, podInformer, schedClient) 74 | eqCtrl := controller.NewElasticQuotaController(kubeClient, eqInformer, podInformer, schedClient) 75 | 76 | run := func(ctx context.Context) { 77 | go pgCtrl.Run(s.Workers, ctx.Done()) 78 | go eqCtrl.Run(s.Workers, ctx.Done()) 79 | select {} 80 | } 81 | schedInformerFactory.Start(stopCh) 82 | coreInformerFactory.Start(stopCh) 83 | if !s.EnableLeaderElection { 84 | run(ctx) 85 | } else { 86 | id, err := os.Hostname() 87 | if err != nil { 88 | return err 89 | } 90 | // add a uniquifier so that two processes on the same host don't accidentally both become active 91 | id = id + "_" + string(uuid.NewUUID()) 92 | 93 | rl, err := resourcelock.New("endpoints", 94 | "kube-system", 95 | "sched-plugins-controller", 96 | kubeClient.CoreV1(), 97 | kubeClient.CoordinationV1(), 98 | resourcelock.ResourceLockConfig{ 99 | Identity: id, 100 | }) 101 | if err != nil { 102 | klog.Fatalf("error creating lock: %v", err) 103 | } 104 | 105 | leaderelection.RunOrDie(context.TODO(), leaderelection.LeaderElectionConfig{ 106 | Lock: rl, 107 | Callbacks: leaderelection.LeaderCallbacks{ 108 | OnStartedLeading: run, 109 | OnStoppedLeading: func() { 110 | klog.Fatalf("leaderelection lost") 111 | }, 112 | }, 113 | Name: "scheduler-plugins controller", 114 | }) 115 | } 116 | 117 | <-stopCh 118 | return nil 119 | } 120 | -------------------------------------------------------------------------------- /cmd/controller/controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "fmt" 22 | "os" 23 | 24 | "github.com/spf13/pflag" 25 | "sigs.k8s.io/scheduler-plugins/cmd/controller/app" 26 | ) 27 | 28 | func main() { 29 | options := app.NewServerRunOptions() 30 | 31 | pflag.CommandLine.AddGoFlagSet(flag.CommandLine) 32 | pflag.Parse() 33 | 34 | if err := app.Run(options); err != nil { 35 | fmt.Fprintf(os.Stderr, "%v\n", err) 36 | os.Exit(1) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmd/scheduler/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "math/rand" 21 | "os" 22 | "time" 23 | 24 | "k8s.io/component-base/logs" 25 | "k8s.io/kubernetes/cmd/kube-scheduler/app" 26 | 27 | "sigs.k8s.io/scheduler-plugins/pkg/capacityscheduling" 28 | "sigs.k8s.io/scheduler-plugins/pkg/coscheduling" 29 | "sigs.k8s.io/scheduler-plugins/pkg/crossnodepreemption" 30 | "sigs.k8s.io/scheduler-plugins/pkg/noderesources" 31 | "sigs.k8s.io/scheduler-plugins/pkg/noderesourcetopology" 32 | "sigs.k8s.io/scheduler-plugins/pkg/podstate" 33 | "sigs.k8s.io/scheduler-plugins/pkg/qos" 34 | "sigs.k8s.io/scheduler-plugins/pkg/trimaran/loadvariationriskbalancing" 35 | "sigs.k8s.io/scheduler-plugins/pkg/trimaran/targetloadpacking" 36 | // Ensure scheme package is initialized. 37 | _ "sigs.k8s.io/scheduler-plugins/pkg/apis/config/scheme" 38 | ) 39 | 40 | func main() { 41 | rand.Seed(time.Now().UnixNano()) 42 | 43 | // Register custom plugins to the scheduler framework. 44 | // Later they can consist of scheduler profile(s) and hence 45 | // used by various kinds of workloads. 46 | command := app.NewSchedulerCommand( 47 | app.WithPlugin(capacityscheduling.Name, capacityscheduling.New), 48 | app.WithPlugin(coscheduling.Name, coscheduling.New), 49 | app.WithPlugin(loadvariationriskbalancing.Name, loadvariationriskbalancing.New), 50 | app.WithPlugin(noderesources.AllocatableName, noderesources.NewAllocatable), 51 | app.WithPlugin(noderesourcetopology.Name, noderesourcetopology.New), 52 | app.WithPlugin(targetloadpacking.Name, targetloadpacking.New), 53 | // Sample plugins below. 54 | app.WithPlugin(crossnodepreemption.Name, crossnodepreemption.New), 55 | app.WithPlugin(podstate.Name, podstate.New), 56 | app.WithPlugin(qos.Name, qos.New), 57 | ) 58 | 59 | // TODO: once we switch everything over to Cobra commands, we can go back to calling 60 | // utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the 61 | // normalize func and add the go flag set by hand. 62 | // utilflag.InitFlags() 63 | logs.InitLogs() 64 | defer logs.FlushLogs() 65 | 66 | if err := command.Execute(); err != nil { 67 | os.Exit(1) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /doc/adopters: -------------------------------------------------------------------------------- 1 | # Adopters of Scheduling Framework plugins 2 | 3 | TBD -------------------------------------------------------------------------------- /doc/develop.md: -------------------------------------------------------------------------------- 1 | # Developer guide 2 | 3 | ## How to build 4 | 5 | This section is about building on the local host, e.g. for debug purpose. 6 | Your `GOPATH` environment variable should be set. 7 | After cloning it into the `$GOPATH/src/sigs.k8s.io` directory 8 | you can build an image by the following command: 9 | ```shell 10 | make local-image 11 | ``` 12 | After that you'll take localhost:5000/scheduler-plugins/kube-scheduler:latest and 13 | localhost:5000/scheduler-plugins/controller:latest images. 14 | 15 | Your source code has to be located at `$GOPATH/src/sigs.k8s.io`, if you would like to change some type definition of the interfaces 16 | and regenerate their implementation by running the command: 17 | ```shell 18 | hack/update-codegen.sh 19 | ``` 20 | 21 | Also, if you are adding a new plugin args struct, to have it properly decoded, its name needs to follow the convention `Args`. 22 | 23 | If you would like to build just the binaries you can do it by 24 | ```shell 25 | make 26 | ``` 27 | command. 28 | If you changed the branch or added new dependency you might need to regenerate vendor directory, for this you can use 29 | ```shell 30 | make autogen 31 | ``` 32 | command. 33 | 34 | ## How to debug 35 | By default debug information is stripped, to keep it in the binary you need to remove -w command line option from 36 | ldflags in the Makefile. 37 | You can run all unit tests by **make unit-test** command or if you would like to run exact unit test 38 | ```shell 39 | GOFLAGS="-v" go test ./pkg/util/podgroup.go ./pkg/util/constants.go ./pkg/util/podgroup_test.go 40 | ``` 41 | -v in GOFLAGS was used for verbosity 42 | You can also run integration test locally, but etcd port 2379 on your system should be free. 43 | ```shell 44 | make integration-test 45 | ``` 46 | 47 | ## How to start 48 | If you would like to start produced kube-scheduler image you can use it in your static kube-scheduler manifests or any kind of 49 | deployment spec as following: 50 | ```yaml 51 | apiVersion: apps/v1 52 | kind: Deployment 53 | metadata: 54 | name: schedulingplugin 55 | namespace: kube-system 56 | spec: 57 | replicas: 1 58 | selector: 59 | matchLabels: 60 | component: scheduler 61 | tier: control-plane 62 | template: 63 | metadata: 64 | labels: 65 | component: scheduler 66 | tier: control-plane 67 | spec: 68 | nodeSelector: 69 | node-role.kubernetes.io/master: "" 70 | containers: 71 | - image: localhost:5000/scheduler-plugins/kube-scheduler:latest 72 | imagePullPolicy: Never 73 | command: 74 | - /bin/kube-scheduler 75 | - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf 76 | - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf 77 | - --config=/etc/kubernetes/configs/scheduler-config.yaml 78 | - -v=9 79 | name: schedulingplugin 80 | securityContext: 81 | privileged: true 82 | volumeMounts: 83 | - mountPath: /etc/kubernetes 84 | name: etckubernetes 85 | hostNetwork: false 86 | hostPID: false 87 | volumes: 88 | - hostPath: 89 | path: /etc/kubernetes/ 90 | type: Directory 91 | name: etckubernetes 92 | ``` 93 | Where example for scheduler-config.yaml, could be taken from manifests/*/scheduler-config.yaml. 94 | 95 | 96 | ## Before submitting 97 | In addition to starting integration and unit tests, check formatting 98 | ```shell 99 | make verify-gofmt 100 | ``` 101 | -------------------------------------------------------------------------------- /doc/release-guide.md: -------------------------------------------------------------------------------- 1 | # Release Guide 2 | 3 | ## Semi-automatic 4 | 5 | 1. Make sure your repo is clean by git's standards 6 | 2. Create a release branch `git checkout -b release-1.19` (not required for patch releases) 7 | 3. Push the release branch to the scheduler-plugins repo and ensure branch protection is enabled (not required for patch releases) 8 | 4. Tag the repository from the `master` branch (from the `release-1.19` branch for a patch release) and push the tag `VERSION=v0.19.0 git tag -m $VERSION $VERSION; git push origin $VERSION` 9 | 5. Publish a draft release using the tag you just created 10 | 6. Perform the [image promotion process](https://github.com/kubernetes/k8s.io/tree/main/k8s.gcr.io#image-promoter) 11 | 7. Publish release 12 | 8. Email `kubernetes-sig-scheduling@googlegroups.com` to announce the release 13 | 14 | ## Manual 15 | 16 | 1. Make sure your repo is clean by git's standards 17 | 2. Create a release branch `git checkout -b release-1.19` (not required for patch releases) 18 | 3. Push the release branch to the scheduler-plugins repo and ensure branch protection is enabled (not required for patch releases) 19 | 4. Tag the repository from the `master` branch (from the `release-1.19` branch for a patch release) and push the tag `VERSION=v0.19.0 git tag -m $VERSION $VERSION; git push origin $VERSION` 20 | 5. Checkout the tag you just created and make sure your repo is clean by git's standards `git checkout $VERSION` 21 | 6. Build and push the container image to the staging registry `RELEASE_VERSION=$VERSION make push-release-image` 22 | 7. Publish a draft release using the tag you just created 23 | 8. Perform the [image promotion process](https://github.com/kubernetes/k8s.io/tree/main/k8s.gcr.io#image-promoter) 24 | 9. Publish release 25 | 10. Email `kubernetes-sig-scheduling@googlegroups.com` to announce the release 26 | 27 | ## Notes 28 | See [post-scheduler-plugins-push-images dashboard](https://testgrid.k8s.io/sig-scheduling#post-scheduler-plugins-push-images) for staging registry image build job status. 29 | 30 | View the scheduler-plugins staging registry using [this URL](https://console.cloud.google.com/gcr/images/k8s-staging-scheduler-plugins/GLOBAL) in a web browser 31 | or use the below `gcloud` commands. 32 | 33 | List images in staging registry. 34 | ``` 35 | gcloud container images list --repository gcr.io/k8s-staging-scheduler-plugins 36 | ``` 37 | 38 | List kube-scheduler image tags in the staging registry. 39 | ``` 40 | gcloud container images list-tags gcr.io/k8s-staging-scheduler-plugins/kube-scheduler 41 | ``` 42 | 43 | Get SHA256 hash for a specific image in the staging registry. 44 | ``` 45 | gcloud container images describe gcr.io/k8s-staging-scheduler-plugins/kube-scheduler:v20200206-0.9.0-94-ge2a23f284 46 | ``` 47 | 48 | Pull image from the staging registry. 49 | ``` 50 | docker pull gcr.io/k8s-staging-scheduler-plugins/kube-scheduler:v20200206-0.9.0-94-ge2a23f284 51 | ``` 52 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/scheduler-plugins 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/google/go-cmp v0.5.4 7 | github.com/google/uuid v1.1.2 8 | github.com/k8stopologyawareschedwg/noderesourcetopology-api v0.0.8 9 | github.com/patrickmn/go-cache v2.1.0+incompatible 10 | github.com/paypal/load-watcher v0.1.1 11 | github.com/spf13/pflag v1.0.5 12 | github.com/stretchr/testify v1.6.1 13 | k8s.io/api v0.21.4 14 | k8s.io/apiextensions-apiserver v0.0.0 15 | k8s.io/apimachinery v0.21.4 16 | k8s.io/apiserver v0.21.4 17 | k8s.io/client-go v0.21.4 18 | k8s.io/code-generator v0.21.4 19 | k8s.io/component-base v0.21.4 20 | k8s.io/component-helpers v0.21.4 21 | k8s.io/klog/v2 v2.8.0 22 | k8s.io/kube-aggregator v0.0.0 23 | k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 24 | k8s.io/kube-scheduler v0.21.4 25 | k8s.io/kubernetes v1.21.4 26 | ) 27 | 28 | replace ( 29 | k8s.io/api => k8s.io/api v0.21.4 30 | k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.4 31 | k8s.io/apimachinery => k8s.io/apimachinery v0.21.4 32 | k8s.io/apiserver => k8s.io/apiserver v0.21.4 33 | k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.4 34 | k8s.io/client-go => k8s.io/client-go v0.21.4 35 | k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.4 36 | k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.4 37 | k8s.io/code-generator => k8s.io/code-generator v0.21.4 38 | k8s.io/component-base => k8s.io/component-base v0.21.4 39 | k8s.io/component-helpers => k8s.io/component-helpers v0.21.4 40 | k8s.io/controller-manager => k8s.io/controller-manager v0.21.4 41 | k8s.io/cri-api => k8s.io/cri-api v0.21.4 42 | k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.4 43 | k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.4 44 | k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.4 45 | k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.4 46 | k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.4 47 | k8s.io/kubectl => k8s.io/kubectl v0.21.4 48 | k8s.io/kubelet => k8s.io/kubelet v0.21.4 49 | k8s.io/kubernetes => k8s.io/kubernetes v1.21.4 50 | k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.4 51 | k8s.io/metrics => k8s.io/metrics v0.21.4 52 | k8s.io/mount-utils => k8s.io/mount-utils v0.21.4 53 | k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.4 54 | ) 55 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.generatego.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /hack/install-etcd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2014 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This script is convenience to download and install etcd in third_party. 18 | # Mostly just used by CI. 19 | # Usage: `hack/install-etcd.sh`. 20 | 21 | set -o errexit 22 | set -o nounset 23 | set -o pipefail 24 | 25 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 26 | source "${SCRIPT_ROOT}/hack/lib/init.sh" 27 | 28 | kube::etcd::install 29 | -------------------------------------------------------------------------------- /hack/integration-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. 22 | source "${SCRIPT_ROOT}/hack/lib/init.sh" 23 | 24 | checkEtcdOnPath() { 25 | # If it's in a prow CI env, add etcd to path. 26 | [[ ${CI:-} == "true" ]] && export PATH="$(pwd)/etcd:${PATH}" 27 | kube::log::status "Checking etcd is on PATH" 28 | command -v etcd >/dev/null && return 29 | kube::log::status "Cannot find etcd, cannot run integration tests." 30 | kube::log::status "Please see https://git.k8s.io/community/contributors/devel/sig-testing/integration-tests.md#install-etcd-dependency for instructions." 31 | # kube::log::usage "You can use 'hack/install-etcd.sh' to install a copy in third_party/." 32 | return 1 33 | } 34 | 35 | CLEANUP_REQUIRED= 36 | cleanup() { 37 | [[ -z "${CLEANUP_REQUIRED}" ]] && return 38 | kube::log::status "Cleaning up etcd" 39 | kube::etcd::cleanup 40 | CLEANUP_REQUIRED= 41 | kube::log::status "Integration test cleanup complete" 42 | } 43 | 44 | runTests() { 45 | kube::log::status "Starting etcd instance" 46 | CLEANUP_REQUIRED=1 47 | kube::etcd::start 48 | kube::log::status "Running integration test cases" 49 | 50 | # TODO: make args customizable. 51 | go test -timeout=40m -mod=vendor sigs.k8s.io/scheduler-plugins/test/integration/... 52 | 53 | cleanup 54 | } 55 | 56 | checkEtcdOnPath 57 | 58 | # Run cleanup to stop etcd on interrupt or other kill signal. 59 | trap cleanup EXIT 60 | 61 | runTests 62 | -------------------------------------------------------------------------------- /hack/lib/golang.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Ensure the go tool exists and is a viable version. 18 | kube::golang::verify_go_version() { 19 | if [[ -z "$(command -v go)" ]]; then 20 | kube::log::usage_from_stdin <&2 36 | shift 37 | for message; do 38 | echo " ${message}" >&2 39 | done 40 | } 41 | 42 | # Print an usage message to stderr. The arguments are printed directly. 43 | kube::log::usage() { 44 | echo >&2 45 | local message 46 | for message; do 47 | echo "${message}" >&2 48 | done 49 | echo >&2 50 | } 51 | 52 | kube::log::usage_from_stdin() { 53 | local messages=() 54 | while read -r line; do 55 | messages+=("${line}") 56 | done 57 | 58 | kube::log::usage "${messages[@]}" 59 | } -------------------------------------------------------------------------------- /hack/lib/util.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | kube::util::host_os() { 18 | local host_os 19 | case "$(uname -s)" in 20 | Darwin) 21 | host_os=darwin 22 | ;; 23 | Linux) 24 | host_os=linux 25 | ;; 26 | *) 27 | kube::log::error "Unsupported host OS. Must be Linux or Mac OS X." 28 | exit 1 29 | ;; 30 | esac 31 | echo "${host_os}" 32 | } 33 | 34 | kube::util::host_arch() { 35 | local host_arch 36 | case "$(uname -m)" in 37 | x86_64*) 38 | host_arch=amd64 39 | ;; 40 | i?86_64*) 41 | host_arch=amd64 42 | ;; 43 | amd64*) 44 | host_arch=amd64 45 | ;; 46 | aarch64*) 47 | host_arch=arm64 48 | ;; 49 | arm64*) 50 | host_arch=arm64 51 | ;; 52 | arm*) 53 | host_arch=arm 54 | ;; 55 | i?86*) 56 | host_arch=x86 57 | ;; 58 | s390x*) 59 | host_arch=s390x 60 | ;; 61 | ppc64le*) 62 | host_arch=ppc64le 63 | ;; 64 | *) 65 | kube::log::error "Unsupported host arch. Must be x86_64, 386, arm, arm64, s390x or ppc64le." 66 | exit 1 67 | ;; 68 | esac 69 | echo "${host_arch}" 70 | } 71 | 72 | kube::util::wait_for_url() { 73 | local url=$1 74 | local prefix=${2:-} 75 | local wait=${3:-1} 76 | local times=${4:-30} 77 | local maxtime=${5:-1} 78 | 79 | command -v curl >/dev/null || { 80 | kube::log::usage "curl must be installed" 81 | exit 1 82 | } 83 | 84 | local i 85 | for i in $(seq 1 "${times}"); do 86 | local out 87 | if out=$(curl --max-time "${maxtime}" -gkfs "${url}" 2>/dev/null); then 88 | kube::log::status "On try ${i}, ${prefix}: ${out}" 89 | return 0 90 | fi 91 | sleep "${wait}" 92 | done 93 | kube::log::error "Timed out waiting for ${prefix} to answer at ${url}; tried ${times} waiting ${wait} between each" 94 | return 1 95 | } 96 | 97 | kube::util::download_file() { 98 | local -r url=$1 99 | local -r destination_file=$2 100 | 101 | rm "${destination_file}" 2&> /dev/null || true 102 | 103 | for i in $(seq 5) 104 | do 105 | if ! curl -fsSL --retry 3 --keepalive-time 2 "${url}" -o "${destination_file}"; then 106 | echo "Downloading ${url} failed. $((5-i)) retries left." 107 | sleep 1 108 | else 109 | echo "Downloading ${url} succeed" 110 | return 0 111 | fi 112 | done 113 | return 1 114 | } 115 | -------------------------------------------------------------------------------- /hack/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | /* 4 | Copyright 2019 The Kubernetes Authors. 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | // Copied from https://github.com/kubernetes/sample-controller/blob/master/hack/tools.go 17 | 18 | // This package imports things required by build scripts, to force `go mod` to see them as dependencies 19 | package tools 20 | 21 | import ( 22 | _ "k8s.io/code-generator" 23 | _ "k8s.io/kube-openapi/cmd/openapi-gen" 24 | ) 25 | -------------------------------------------------------------------------------- /hack/unit-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. 22 | source "${SCRIPT_ROOT}/hack/lib/init.sh" 23 | 24 | # TODO: make args customizable. 25 | go test -mod=vendor \ 26 | sigs.k8s.io/scheduler-plugins/cmd/... \ 27 | sigs.k8s.io/scheduler-plugins/pkg/... 28 | -------------------------------------------------------------------------------- /hack/update-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} 23 | 24 | bash "${CODEGEN_PKG}"/generate-internal-groups.sh \ 25 | "deepcopy,defaulter,conversion" \ 26 | sigs.k8s.io/scheduler-plugins/pkg/generated \ 27 | sigs.k8s.io/scheduler-plugins/pkg/apis \ 28 | sigs.k8s.io/scheduler-plugins/pkg/apis \ 29 | "config:v1beta1" \ 30 | --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate/boilerplate.generatego.txt 31 | 32 | bash "${CODEGEN_PKG}"/generate-groups.sh \ 33 | all \ 34 | sigs.k8s.io/scheduler-plugins/pkg/generated \ 35 | sigs.k8s.io/scheduler-plugins/pkg/apis \ 36 | "scheduling:v1alpha1" \ 37 | --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate/boilerplate.generatego.txt 38 | -------------------------------------------------------------------------------- /hack/update-generated-openapi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # TODO: make this script run faster. 22 | 23 | SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. 24 | 25 | go install k8s.io/kube-openapi/cmd/openapi-gen 26 | 27 | KUBE_INPUT_DIRS=( 28 | $( 29 | grep --color=never -rl '+k8s:openapi-gen=' vendor/k8s.io | \ 30 | xargs -n1 dirname | \ 31 | sed "s,^vendor/,," | \ 32 | sort -u | \ 33 | sed '/^k8s\.io\/kubernetes\/build\/root$/d' | \ 34 | sed '/^k8s\.io\/kubernetes$/d' | \ 35 | sed '/^k8s\.io\/kubernetes\/staging$/d' | \ 36 | sed 's,k8s\.io/kubernetes/staging/src/,,' | \ 37 | grep -v 'k8s.io/code-generator' | \ 38 | grep -v 'k8s.io/sample-apiserver' 39 | ) 40 | ) 41 | 42 | KUBE_INPUT_DIRS=$(IFS=,; echo "${KUBE_INPUT_DIRS[*]}") 43 | 44 | function join { local IFS="$1"; shift; echo "$*"; } 45 | 46 | echo "Generating Kubernetes OpenAPI" 47 | 48 | $GOPATH/bin/openapi-gen \ 49 | --output-file-base zz_generated.openapi \ 50 | --output-base="${GOPATH}/src" \ 51 | --go-header-file ${SCRIPT_ROOT}/hack/boilerplate/boilerplate.generatego.txt \ 52 | --output-base="./" \ 53 | --input-dirs $(join , "${KUBE_INPUT_DIRS[@]}") \ 54 | --output-package "vendor/k8s.io/kubernetes/pkg/generated/openapi" \ 55 | --report-filename "${SCRIPT_ROOT}/hack/openapi-violation.list" \ 56 | "$@" 57 | 58 | # TODO: verify hack/openapi-violation.list -------------------------------------------------------------------------------- /hack/update-gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCIPRT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | source "${SCIPRT_ROOT}/hack/lib/init.sh" 23 | 24 | kube::golang::verify_go_version 25 | 26 | cd "${SCIPRT_ROOT}" 27 | 28 | find_files() { 29 | find . -not \( \ 30 | \( \ 31 | -wholename './output' \ 32 | -o -wholename './.git' \ 33 | -o -wholename './_output' \ 34 | -o -wholename './release' \ 35 | -o -wholename './target' \ 36 | -o -wholename '*/third_party/*' \ 37 | -o -wholename '*/vendor/*' \ 38 | -o -wholename './staging/src/k8s.io/client-go/*vendor/*' \ 39 | \) -prune \ 40 | \) -name '*.go' 41 | } 42 | 43 | find_files | xargs gofmt -s -w 44 | -------------------------------------------------------------------------------- /hack/update-vendor.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCIPRT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | source "${SCIPRT_ROOT}/hack/lib/init.sh" 23 | 24 | kube::golang::verify_go_version 25 | 26 | go mod tidy 27 | go mod vendor -------------------------------------------------------------------------------- /hack/verify-gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This script checks whether the source codes need to be formatted or not by 18 | # `gofmt`. We should run `hack/update-gofmt.sh` if actually formats them. 19 | # Usage: `hack/verify-gofmt.sh`. 20 | # Note: GoFmt apparently is changing @ head... 21 | 22 | set -o errexit 23 | set -o nounset 24 | set -o pipefail 25 | 26 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 27 | source "${SCRIPT_ROOT}/hack/lib/init.sh" 28 | 29 | kube::golang::verify_go_version 30 | 31 | cd "${SCRIPT_ROOT}" 32 | 33 | find_files() { 34 | find . -not \( \ 35 | \( \ 36 | -wholename './output' \ 37 | -o -wholename './.git' \ 38 | -o -wholename './_output' \ 39 | -o -wholename './release' \ 40 | -o -wholename './target' \ 41 | -o -wholename '*/third_party/*' \ 42 | -o -wholename '*/vendor/*' \ 43 | -o -wholename './staging/src/k8s.io/client-go/*vendor/*' \ 44 | -o -wholename '*/bindata.go' \ 45 | \) -prune \ 46 | \) -name '*.go' 47 | } 48 | 49 | 50 | # gofmt exits with non-zero exit code if it finds a problem unrelated to 51 | # formatting (e.g., a file does not parse correctly). Without "|| true" this 52 | # would have led to no useful error message from gofmt, because the script would 53 | # have failed before getting to the "echo" in the block below. 54 | diff=$(find_files | xargs gofmt -d -s 2>&1) || true 55 | if [[ -n "${diff}" ]]; then 56 | echo "${diff}" >&2 57 | echo >&2 58 | echo "Run ./hack/update-gofmt.sh" >&2 59 | exit 1 60 | fi 61 | -------------------------------------------------------------------------------- /kep/119-node-resource-topology-aware-scheduling/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Simplified version of Topology Manager in kube-scheduler 2 | kep-number: 119 3 | authors: 4 | - "@AlexeyPerevalov" 5 | - "@swatisehgal" 6 | owning-sig: sig-scheduling 7 | reviewers: 8 | - "@Huang-Wei" 9 | - "@ahg-g" 10 | - "@alculquicondor" 11 | approvers: 12 | - "@Huang-Wei" 13 | creation-date: 2020-11-24 14 | last-updated: 2020-11-24 15 | status: implementable 16 | -------------------------------------------------------------------------------- /kep/2-lightweight-coscheduling/design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/2-lightweight-coscheduling/design.png -------------------------------------------------------------------------------- /kep/2-lightweight-coscheduling/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Lightweight coscheduling based on back-to-back queue sorting 2 | kep-number: 2 3 | authors: 4 | - "@denkensk" 5 | owning-sig: sig-scheduling 6 | reviewers: 7 | - "@Huang-Wei" 8 | - "@ahg-g" 9 | - "@alculquicondor" 10 | - "k82cn" 11 | - "@resouer" 12 | - "@hex108" 13 | - "@everpeace" 14 | approvers: 15 | - "@Huang-Wei" 16 | creation-date: 2020-01-16 17 | last-updated: 2020-01-16 18 | status: implementable 19 | -------------------------------------------------------------------------------- /kep/205-preemption-toleration/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Preemption Toleration 2 | kep-number: 205 3 | authors: 4 | - "@everpeace" 5 | - "@ordovicia" 6 | - "@shioshiota" 7 | owning-sig: sig-scheduling 8 | reviewers: 9 | - "@Huang-Wei" 10 | approvers: 11 | - "@Huang-Wei" 12 | creation-date: 2021-08-04 13 | last-updated: 2021-08-04 14 | status: implementable 15 | -------------------------------------------------------------------------------- /kep/217-resource-limit-aware-scorcing/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Resource limit-aware Scoring 2 | kep-number: 217 3 | authors: 4 | - "@yuanchen8911" 5 | owning-sig: sig-scheduling 6 | reviewers: 7 | - "@Huang-Wei" 8 | - "@denkensk" 9 | approvers: 10 | - "@Huang-Wei" 11 | creation-date: 2021-07-20 12 | last-updated: 2021-07-20 13 | status: implementable 14 | -------------------------------------------------------------------------------- /kep/42-podgroup-coscheduling/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Coscheduling based on PodGroup CRD 2 | kep-number: 42 3 | authors: 4 | - "@cwdsuzhou" 5 | owning-sig: sig-scheduling 6 | reviewers: 7 | - "@Huang-Wei" 8 | - "@denkensk" 9 | approvers: 10 | - "@Huang-Wei" 11 | creation-date: 2020-08-24 12 | last-updated: 2020-08-24 13 | status: implementable -------------------------------------------------------------------------------- /kep/48-node-resources-allocatable-scoring/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Node resources allocatable scoring 2 | authors: 3 | - "@patricklundquist" 4 | owning-sig: sig-scheduling 5 | reviewers: 6 | - "@Huang-Wei" 7 | - "@ahg-g" 8 | approvers: 9 | - "@Huang-Wei" 10 | creation-date: 2020-09-03 11 | last-updated: 2020-09-15 12 | status: implementable 13 | -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/design.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image1.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image2.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image3.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image4.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image5.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image6.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image7.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image8.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/image9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/image9.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/safe-sched-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/safe-sched-graph.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/images/tlp-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/61-Trimaran-real-load-aware-scheduling/images/tlp-graph.png -------------------------------------------------------------------------------- /kep/61-Trimaran-real-load-aware-scheduling/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Trimaran - Real Load Aware Scheduling 2 | kep-number: 61 3 | authors: 4 | - "@zorro786" 5 | - "@wangchen615" 6 | owning-sig: sig-scheduling 7 | reviewers: 8 | - "@Huang-Wei" 9 | - "@ahg-g" 10 | - "@alculquicondor" 11 | approvers: 12 | - "@Huang-Wei" 13 | creation-date: 2020-09-22 14 | last-updated: 2020-09-22 15 | status: implementable -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/1.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/2.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/3.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/4.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/5.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/6.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/7.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/8.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/kep/9-capacity-scheduling/9.png -------------------------------------------------------------------------------- /kep/9-capacity-scheduling/kep.yaml: -------------------------------------------------------------------------------- 1 | title: Capacity scheduling 2 | kep-number: 3 | authors: 4 | - "@denkensk" 5 | - "@Fei-Guo" 6 | owning-sig: sig-scheduling 7 | participating-sigs: 8 | - sig-scheduling 9 | status: implementable 10 | creation-date: 2020-06-22 11 | reviewers: 12 | - "@ahg-g" 13 | - "@Huang-Wei" 14 | - "@alculquicondor" 15 | - "@yuanchen8911" 16 | approvers: 17 | - "Huang-Wei" 18 | stage: alpha 19 | latest-milestone: "v1.19" 20 | milestone: 21 | alpha: "v1.19" 22 | disable-supported: true 23 | metrics: 24 | - pod_preemption_victims 25 | - total_preemption_attempts 26 | - scheduling_algorithm_preemption_evaluation_seconds -------------------------------------------------------------------------------- /manifests/capacityscheduling/crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: elasticquotas.scheduling.sigs.k8s.io 5 | annotations: 6 | "api-approved.kubernetes.io": "https://github.com/kubernetes-sigs/scheduler-plugins/pull/52" 7 | spec: 8 | group: scheduling.sigs.k8s.io 9 | names: 10 | plural: elasticquotas 11 | singular: elasticquota 12 | kind: ElasticQuota 13 | shortNames: 14 | - eq 15 | - eqs 16 | scope: Namespaced 17 | versions: 18 | - name: v1alpha1 19 | served: true 20 | storage: true 21 | schema: 22 | openAPIV3Schema: 23 | type: object 24 | properties: 25 | spec: 26 | type: object 27 | properties: 28 | min: 29 | type: object 30 | additionalProperties: 31 | anyOf: 32 | - type: integer 33 | - type: string 34 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 35 | x-kubernetes-int-or-string: true 36 | max: 37 | type: object 38 | additionalProperties: 39 | anyOf: 40 | - type: integer 41 | - type: string 42 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 43 | x-kubernetes-int-or-string: true 44 | status: 45 | type: object 46 | properties: 47 | used: 48 | type: object 49 | additionalProperties: 50 | anyOf: 51 | - type: integer 52 | - type: string 53 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 54 | x-kubernetes-int-or-string: true -------------------------------------------------------------------------------- /manifests/capacityscheduling/elasticquota-example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scheduling.sigs.k8s.io/v1alpha1 2 | kind: ElasticQuota 3 | metadata: 4 | name: test 5 | namespace: test 6 | spec: 7 | max: 8 | cpu: 20 9 | memory: 40Gi 10 | nvidia.com/gpu: 2 11 | min: 12 | cpu: 10 13 | memory: 20Gi 14 | nvidia.com/gpu: 1 -------------------------------------------------------------------------------- /manifests/capacityscheduling/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | profiles: 8 | - schedulerName: default-scheduler 9 | plugins: 10 | preFilter: 11 | enabled: 12 | - name: CapacityScheduling 13 | postFilter: 14 | enabled: 15 | - name: CapacityScheduling 16 | disabled: 17 | - name: "*" 18 | reserve: 19 | enabled: 20 | - name: CapacityScheduling 21 | pluginConfig: 22 | - name: CapacityScheduling 23 | args: 24 | kubeConfigPath: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 25 | -------------------------------------------------------------------------------- /manifests/coscheduling/crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: podgroups.scheduling.sigs.k8s.io 5 | annotations: 6 | "api-approved.kubernetes.io": "https://github.com/kubernetes-sigs/scheduler-plugins/pull/50" 7 | spec: 8 | group: scheduling.sigs.k8s.io 9 | names: 10 | kind: PodGroup 11 | plural: podgroups 12 | singular: podgroup 13 | shortNames: 14 | - pg 15 | - pgs 16 | scope: Namespaced 17 | versions: 18 | - name: "v1alpha1" 19 | served: true 20 | storage: true 21 | schema: 22 | openAPIV3Schema: 23 | type: object 24 | properties: 25 | spec: 26 | type: object 27 | properties: 28 | minMember: 29 | type: integer 30 | minimum: 1 31 | scheduleTimeoutSeconds: 32 | type: integer 33 | minResources: 34 | type: object 35 | additionalProperties: 36 | type: string 37 | status: 38 | type: object 39 | properties: 40 | phase: 41 | type: string 42 | occupiedBy: 43 | type: string 44 | scheduled: 45 | type: integer 46 | default: 0 47 | running: 48 | type: integer 49 | default: 0 50 | succeeded: 51 | type: integer 52 | default: 0 53 | failed: 54 | type: integer 55 | default: 0 56 | scheduleStartTime: 57 | type: string 58 | format: date-time 59 | 60 | -------------------------------------------------------------------------------- /manifests/coscheduling/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | profiles: 8 | - schedulerName: default-scheduler 9 | plugins: 10 | queueSort: 11 | enabled: 12 | - name: Coscheduling 13 | disabled: 14 | - name: "*" 15 | preFilter: 16 | enabled: 17 | - name: Coscheduling 18 | permit: 19 | enabled: 20 | - name: Coscheduling 21 | reserve: 22 | enabled: 23 | - name: Coscheduling 24 | postBind: 25 | enabled: 26 | - name: Coscheduling 27 | pluginConfig: 28 | - name: Coscheduling 29 | args: 30 | permitWaitingTimeSeconds: 10 31 | deniedPGExpirationTimeSeconds: 3 32 | kubeConfigPath: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 33 | -------------------------------------------------------------------------------- /manifests/install/all-in-one.yaml: -------------------------------------------------------------------------------- 1 | # First part 2 | # Apply extra privileges to system:kube-scheduler. 3 | kind: ClusterRole 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | metadata: 6 | name: system:kube-scheduler:plugins 7 | rules: 8 | - apiGroups: ["scheduling.sigs.k8s.io"] 9 | resources: ["podgroups", "elasticquotas"] 10 | verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] 11 | --- 12 | kind: ClusterRoleBinding 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | metadata: 15 | name: system:kube-scheduler:plugins 16 | roleRef: 17 | apiGroup: rbac.authorization.k8s.io 18 | kind: ClusterRole 19 | name: system:kube-scheduler:plugins 20 | subjects: 21 | - apiGroup: rbac.authorization.k8s.io 22 | kind: User 23 | name: system:kube-scheduler 24 | --- 25 | # Second part 26 | # Install the controller image. 27 | apiVersion: v1 28 | kind: Namespace 29 | metadata: 30 | name: scheduler-plugins 31 | --- 32 | apiVersion: v1 33 | kind: ServiceAccount 34 | metadata: 35 | name: scheduler-plugins-controller 36 | namespace: scheduler-plugins 37 | --- 38 | kind: ClusterRole 39 | apiVersion: rbac.authorization.k8s.io/v1 40 | metadata: 41 | name: scheduler-plugins-controller 42 | rules: 43 | - apiGroups: [""] 44 | resources: ["pods"] 45 | verbs: ["get", "list", "watch"] 46 | - apiGroups: ["scheduling.sigs.k8s.io"] 47 | resources: ["podgroups", "elasticquotas"] 48 | verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] 49 | --- 50 | kind: ClusterRoleBinding 51 | apiVersion: rbac.authorization.k8s.io/v1 52 | metadata: 53 | name: scheduler-plugins-controller 54 | subjects: 55 | - kind: ServiceAccount 56 | name: scheduler-plugins-controller 57 | namespace: scheduler-plugins 58 | roleRef: 59 | kind: ClusterRole 60 | name: scheduler-plugins-controller 61 | apiGroup: rbac.authorization.k8s.io 62 | --- 63 | kind: Deployment 64 | apiVersion: apps/v1 65 | metadata: 66 | name: scheduler-plugins-controller 67 | namespace: scheduler-plugins 68 | labels: 69 | app: scheduler-plugins-controller 70 | spec: 71 | replicas: 1 72 | selector: 73 | matchLabels: 74 | app: scheduler-plugins-controller 75 | template: 76 | metadata: 77 | labels: 78 | app: scheduler-plugins-controller 79 | spec: 80 | serviceAccount: scheduler-plugins-controller 81 | containers: 82 | - name: scheduler-plugins-controller 83 | image: k8s.gcr.io/scheduler-plugins/controller:v0.20.10 84 | imagePullPolicy: IfNotPresent 85 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: scheduler-plugins 3 | description: deploy scheduler plugin as a second scheduler in cluster 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.19.9 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | appVersion: 0.19.9 24 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/README.md: -------------------------------------------------------------------------------- 1 | # Chart to run scheduler plugin as a second scheduler in cluster. 2 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "scheduler-plugins-as-a-second-scheduler.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "scheduler-plugins-as-a-second-scheduler.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "scheduler-plugins-as-a-second-scheduler.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "scheduler-plugins-as-a-second-scheduler.labels" -}} 37 | helm.sh/chart: {{ include "scheduler-plugins-as-a-second-scheduler.chart" . }} 38 | {{ include "scheduler-plugins-as-a-second-scheduler.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "scheduler-plugins-as-a-second-scheduler.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "scheduler-plugins-as-a-second-scheduler.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: scheduler-config 5 | namespace: {{ .Values.scheduler.namespace }} 6 | data: 7 | scheduler-config.yaml: | 8 | apiVersion: kubescheduler.config.k8s.io/v1beta1 9 | kind: KubeSchedulerConfiguration 10 | leaderElection: 11 | leaderElect: false 12 | profiles: 13 | - schedulerName: scheduler-plugins-scheduler 14 | plugins: 15 | queueSort: 16 | enabled: 17 | - name: Coscheduling 18 | disabled: 19 | - name: "*" 20 | preFilter: 21 | enabled: 22 | - name: Coscheduling 23 | permit: 24 | enabled: 25 | - name: Coscheduling 26 | reserve: 27 | enabled: 28 | - name: Coscheduling 29 | postBind: 30 | enabled: 31 | - name: Coscheduling 32 | pluginConfig: 33 | - name: Coscheduling 34 | args: 35 | permitWaitingTimeSeconds: 10 36 | deniedPGExpirationTimeSeconds: 3 37 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/templates/crds/podgroup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: podgroups.scheduling.sigs.k8s.io 5 | annotations: 6 | "api-approved.kubernetes.io": "https://github.com/kubernetes-sigs/scheduler-plugins/pull/50" 7 | spec: 8 | group: scheduling.sigs.k8s.io 9 | names: 10 | kind: PodGroup 11 | plural: podgroups 12 | singular: podgroup 13 | shortNames: 14 | - pg 15 | - pgs 16 | scope: Namespaced 17 | versions: 18 | - name: "v1alpha1" 19 | served: true 20 | storage: true 21 | schema: 22 | openAPIV3Schema: 23 | type: object 24 | properties: 25 | spec: 26 | type: object 27 | properties: 28 | minMember: 29 | type: integer 30 | minimum: 1 31 | scheduleTimeoutSeconds: 32 | type: integer 33 | minResources: 34 | type: object 35 | additionalProperties: 36 | type: string 37 | status: 38 | type: object 39 | properties: 40 | phase: 41 | type: string 42 | occupiedBy: 43 | type: string 44 | scheduled: 45 | type: integer 46 | default: 0 47 | running: 48 | type: integer 49 | default: 0 50 | succeeded: 51 | type: integer 52 | default: 0 53 | failed: 54 | type: integer 55 | default: 0 56 | scheduleStartTime: 57 | type: string 58 | format: date-time 59 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | kind: Deployment 2 | apiVersion: apps/v1 3 | metadata: 4 | name: {{ .Values.controller.name }} 5 | namespace: {{ .Values.controller.namespace }} 6 | labels: 7 | app: scheduler-plugins-controller 8 | spec: 9 | replicas: {{ .Values.controller.replicaCount }} 10 | selector: 11 | matchLabels: 12 | app: scheduler-plugins-controller 13 | template: 14 | metadata: 15 | labels: 16 | app: scheduler-plugins-controller 17 | spec: 18 | serviceAccount: scheduler-plugins-controller 19 | containers: 20 | - name: scheduler-plugins-controller 21 | image: {{ .Values.controller.image }} 22 | imagePullPolicy: IfNotPresent 23 | --- 24 | apiVersion: apps/v1 25 | kind: Deployment 26 | metadata: 27 | labels: 28 | component: scheduler 29 | name: {{ .Values.scheduler.name }} 30 | namespace: {{ .Values.scheduler.namespace }} 31 | spec: 32 | selector: 33 | matchLabels: 34 | component: scheduler 35 | replicas: {{ .Values.scheduler.replicaCount }} 36 | template: 37 | metadata: 38 | labels: 39 | component: scheduler 40 | spec: 41 | serviceAccountName: scheduler-plugins-scheduler 42 | containers: 43 | - command: 44 | - /bin/kube-scheduler 45 | - --address=0.0.0.0 46 | - --leader-elect=false 47 | - --config=/etc/kubernetes/scheduler-config.yaml 48 | - --scheduler-name=scheduler-plugins-scheduler 49 | image: {{ .Values.scheduler.image }} 50 | livenessProbe: 51 | httpGet: 52 | path: /healthz 53 | port: 10251 54 | initialDelaySeconds: 15 55 | name: scheduler-plugins-scheduler 56 | readinessProbe: 57 | httpGet: 58 | path: /healthz 59 | port: 10251 60 | resources: 61 | requests: 62 | cpu: '0.1' 63 | securityContext: 64 | privileged: false 65 | volumeMounts: 66 | - name: scheduler-config 67 | mountPath: /etc/kubernetes 68 | readOnly: true 69 | hostNetwork: false 70 | hostPID: false 71 | volumes: 72 | - name: scheduler-config 73 | configMap: 74 | name: scheduler-config 75 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/templates/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: scheduler-plugins-scheduler 5 | rules: 6 | - apiGroups: ["", "events.k8s.io"] 7 | resources: ["events"] 8 | verbs: ["create", "patch", "update"] 9 | - apiGroups: ["coordination.k8s.io"] 10 | resources: ["leases"] 11 | verbs: ["create"] 12 | - apiGroups: ["coordination.k8s.io"] 13 | resourceNames: ["kube-scheduler"] 14 | resources: ["leases"] 15 | verbs: ["get", "update"] 16 | - apiGroups: [""] 17 | resources: ["endpoints"] 18 | verbs: ["create"] 19 | - apiGroups: [""] 20 | resourceNames: ["kube-scheduler"] 21 | resources: ["endpoints"] 22 | verbs: ["get", "update"] 23 | - apiGroups: [""] 24 | resources: ["nodes"] 25 | verbs: ["get", "list", "watch"] 26 | - apiGroups: [""] 27 | resources: ["pods"] 28 | verbs: ["delete", "get", "list", "watch"] 29 | - apiGroups: [""] 30 | resources: ["bindings", "pods/binding"] 31 | verbs: ["create"] 32 | - apiGroups: [""] 33 | resources: ["pods/status"] 34 | verbs: ["patch", "update"] 35 | - apiGroups: [""] 36 | resources: ["replicationcontrollers", "services"] 37 | verbs: ["get", "list", "watch"] 38 | - apiGroups: ["apps", "extensions"] 39 | resources: ["replicasets"] 40 | verbs: ["get", "list", "watch"] 41 | - apiGroups: ["apps"] 42 | resources: ["statefulsets"] 43 | verbs: ["get", "list", "watch"] 44 | - apiGroups: ["policy"] 45 | resources: ["poddisruptionbudgets"] 46 | verbs: ["get", "list", "watch"] 47 | - apiGroups: [""] 48 | resources: ["persistentvolumeclaims", "persistentvolumes"] 49 | verbs: ["get", "list", "watch", "patch", "update"] 50 | - apiGroups: ["authentication.k8s.io"] 51 | resources: ["tokenreviews"] 52 | verbs: ["create"] 53 | - apiGroups: ["authorization.k8s.io"] 54 | resources: ["subjectaccessreviews"] 55 | verbs: ["create"] 56 | - apiGroups: ["storage.k8s.io"] 57 | resources: ["csinodes", "storageclasses"] 58 | verbs: ["get", "list", "watch"] 59 | - apiGroups: ["scheduling.sigs.k8s.io"] 60 | resources: ["podgroups", "elasticquotas"] 61 | verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] 62 | --- 63 | kind: ClusterRoleBinding 64 | apiVersion: rbac.authorization.k8s.io/v1 65 | metadata: 66 | name: scheduler-plugins-scheduler 67 | roleRef: 68 | apiGroup: rbac.authorization.k8s.io 69 | kind: ClusterRole 70 | name: scheduler-plugins-scheduler 71 | subjects: 72 | - kind: ServiceAccount 73 | name: {{ .Values.scheduler.name }} 74 | namespace: {{ .Values.scheduler.namespace }} 75 | --- 76 | kind: ClusterRole 77 | apiVersion: rbac.authorization.k8s.io/v1 78 | metadata: 79 | name: scheduler-plugins-controller 80 | rules: 81 | - apiGroups: [""] 82 | resources: ["pods"] 83 | verbs: ["get", "list", "watch"] 84 | - apiGroups: ["scheduling.sigs.k8s.io"] 85 | resources: ["podgroups", "elasticquotas"] 86 | verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] 87 | --- 88 | kind: ClusterRoleBinding 89 | apiVersion: rbac.authorization.k8s.io/v1 90 | metadata: 91 | name: scheduler-plugins-controller 92 | subjects: 93 | - kind: ServiceAccount 94 | name: {{ .Values.controller.name }} 95 | namespace: {{ .Values.controller.namespace }} 96 | roleRef: 97 | kind: ClusterRole 98 | name: scheduler-plugins-controller 99 | apiGroup: rbac.authorization.k8s.io 100 | 101 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: {{ .Values.controller.namespace }} 5 | --- 6 | apiVersion: v1 7 | kind: ServiceAccount 8 | metadata: 9 | name: {{ .Values.scheduler.name }} 10 | namespace: {{ .Values.scheduler.namespace }} 11 | --- 12 | apiVersion: v1 13 | kind: ServiceAccount 14 | metadata: 15 | name: {{ .Values.controller.name }} 16 | namespace: {{ .Values.controller.namespace }} 17 | -------------------------------------------------------------------------------- /manifests/install/charts/as-a-second-scheduler/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for scheduler-plugins-as-a-second-scheduler. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | scheduler: 6 | name: scheduler-plugins-scheduler 7 | image: k8s.gcr.io/scheduler-plugins/kube-scheduler:v0.20.10 8 | namespace: scheduler-plugins 9 | replicaCount: 1 10 | 11 | controller: 12 | name: scheduler-plugins-controller 13 | image: k8s.gcr.io/scheduler-plugins/controller:v0.20.10 14 | namespace: scheduler-plugins 15 | replicaCount: 1 16 | -------------------------------------------------------------------------------- /manifests/noderesources/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | profiles: 8 | - schedulerName: default-scheduler 9 | plugins: 10 | score: 11 | enabled: 12 | - name: NodeResourcesAllocatable 13 | disabled: 14 | - name: "*" 15 | pluginConfig: 16 | - name: NodeResourcesAllocatable 17 | args: 18 | mode: Least 19 | resources: 20 | - name: cpu 21 | weight: 1000000 22 | - name: memory 23 | weight: 1 24 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/cluster-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: topo-aware-scheduler 5 | namespace: kube-system 6 | --- 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | kind: ClusterRole 9 | metadata: 10 | name: noderesourcetoplogy-handler 11 | rules: 12 | - apiGroups: ["topology.node.k8s.io"] 13 | resources: ["noderesourcetopologies"] 14 | verbs: ["*"] 15 | - apiGroups: [""] 16 | resources: ["nodes"] 17 | verbs: ["get", "list", "patch"] 18 | - apiGroups: [""] 19 | resources: ["pods"] 20 | verbs: ["get","list","watch","update"] 21 | - apiGroups: ["rbac.authorization.k8s.io"] 22 | resources: ["*"] 23 | verbs: ["*"] 24 | --- 25 | apiVersion: rbac.authorization.k8s.io/v1 26 | kind: ClusterRoleBinding 27 | metadata: 28 | name: topo-aware-scheduler-as-kube-scheduler 29 | subjects: 30 | - kind: ServiceAccount 31 | name: topo-aware-scheduler 32 | namespace: kube-system 33 | roleRef: 34 | kind: ClusterRole 35 | name: noderesourcetoplogy-handler 36 | apiGroup: rbac.authorization.k8s.io 37 | --- 38 | apiVersion: rbac.authorization.k8s.io/v1 39 | kind: ClusterRoleBinding 40 | metadata: 41 | name: my-scheduler-as-volume-scheduler 42 | subjects: 43 | - kind: ServiceAccount 44 | name: my-scheduler 45 | namespace: kube-system 46 | roleRef: 47 | kind: ClusterRole 48 | name: system:volume-scheduler 49 | apiGroup: rbac.authorization.k8s.io 50 | --- 51 | apiVersion: rbac.authorization.k8s.io/v1 52 | kind: RoleBinding 53 | metadata: 54 | name: topo-aware-scheduler-as-kube-scheduler 55 | namespace: kube-system 56 | subjects: 57 | - kind: ServiceAccount 58 | name: topo-aware-scheduler 59 | namespace: kube-system 60 | roleRef: 61 | kind: Role 62 | name: extension-apiserver-authentication-reader 63 | apiGroup: rbac.authorization.k8s.io 64 | --- 65 | apiVersion: rbac.authorization.k8s.io/v1 66 | kind: ClusterRoleBinding 67 | metadata: 68 | name: noderesourcetoplogy 69 | namespace: kube-system 70 | subjects: 71 | - kind: User 72 | name: system:kube-scheduler 73 | namespace: kube-system 74 | apiGroup: rbac.authorization.k8s.io 75 | roleRef: 76 | kind: ClusterRole 77 | name: noderesourcetoplogy-handler 78 | apiGroup: rbac.authorization.k8s.io 79 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/crd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | "api-approved.kubernetes.io": "https://github.com/kubernetes/enhancements/pull/1870" 7 | name: noderesourcetopologies.topology.node.k8s.io 8 | spec: 9 | group: topology.node.k8s.io 10 | versions: 11 | - name: v1alpha1 12 | served: true 13 | storage: true 14 | schema: 15 | openAPIV3Schema: 16 | type: object 17 | properties: 18 | topologyPolicies: 19 | type: array 20 | items: 21 | type: string 22 | zones: 23 | type: array 24 | items: 25 | type: object 26 | properties: 27 | name: 28 | type: string 29 | type: 30 | type: string 31 | parent: 32 | type: string 33 | resources: 34 | type: array 35 | items: 36 | type: object 37 | properties: 38 | name: 39 | type: string 40 | capacity: 41 | x-kubernetes-int-or-string: true 42 | allocatable: 43 | x-kubernetes-int-or-string: true 44 | costs: 45 | type: array 46 | items: 47 | type: object 48 | properties: 49 | name: 50 | type: string 51 | type: 52 | type: integer 53 | attributes: 54 | type: array 55 | items: 56 | type: object 57 | properties: 58 | name: 59 | type: string 60 | type: 61 | type: string 62 | scope: Namespaced 63 | names: 64 | plural: noderesourcetopologies 65 | singular: noderesourcetopology 66 | kind: NodeResourceTopology 67 | shortNames: 68 | - node-res-topo 69 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | component: scheduler 6 | tier: control-plane 7 | name: topo-aware-scheduler 8 | namespace: kube-system 9 | spec: 10 | selector: 11 | matchLabels: 12 | component: scheduler 13 | tier: control-plane 14 | replicas: 1 15 | template: 16 | metadata: 17 | labels: 18 | component: scheduler 19 | tier: control-plane 20 | version: second 21 | spec: 22 | nodeSelector: 23 | node-role.kubernetes.io/master: "" 24 | serviceAccountName: topo-aware-scheduler 25 | containers: 26 | - image: localhost:5000/scheduler-plugins/kube-scheduler:latest 27 | imagePullPolicy: Never 28 | command: 29 | - /bin/kube-scheduler 30 | - --scheduler-name=topo-aware-scheduler 31 | - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf 32 | - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf 33 | - --config=/etc/kubernetes/scheduler-config/scheduler-config.yaml 34 | name: scheduler 35 | securityContext: 36 | privileged: false 37 | volumeMounts: 38 | - mountPath: /etc/kubernetes/scheduler.conf 39 | name: kubeconfig 40 | - mountPath: /etc/kubernetes/scheduler-config 41 | name: topo-aware-scheduler-config-vol 42 | hostNetwork: false 43 | hostPID: false 44 | volumes: 45 | - hostPath: 46 | path: /etc/kubernetes/scheduler.conf 47 | type: File 48 | name: kubeconfig 49 | - configMap: 50 | name: topo-aware-scheduler-config 51 | name: topo-aware-scheduler-config-vol 52 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: test-namespace # Test namespace -------------------------------------------------------------------------------- /manifests/noderesourcetopology/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | # kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | kubeconfig: "/etc/kubernetes/scheduler.conf" 8 | profiles: 9 | - schedulerName: topo-aware-scheduler 10 | plugins: 11 | filter: 12 | enabled: 13 | - name: NodeResourceTopologyMatch 14 | # optional plugin configs 15 | pluginConfig: 16 | - name: NodeResourceTopologyMatch 17 | args: 18 | # kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 19 | kubeconfigpath: "/etc/kubernetes/scheduler.conf" 20 | namespaces: 21 | - "test-namespace" 22 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/scheduler-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: topo-aware-scheduler-config 5 | namespace: kube-system 6 | data: 7 | scheduler-config.yaml: | 8 | apiVersion: kubescheduler.config.k8s.io/v1beta1 9 | kind: KubeSchedulerConfiguration 10 | leaderElection: 11 | leaderElect: false 12 | clientConnection: 13 | kubeconfig: "/etc/kubernetes/scheduler.conf" 14 | profiles: 15 | - schedulerName: topo-aware-scheduler 16 | plugins: 17 | filter: 18 | enabled: 19 | - name: NodeResourceTopologyMatch 20 | # optional plugin configs 21 | pluginConfig: 22 | - name: NodeResourceTopologyMatch 23 | args: 24 | kubeconfigpath: "/etc/kubernetes/scheduler.conf" 25 | namespaces: 26 | - "test-namespace" 27 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/test-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: test-deployment 5 | spec: 6 | selector: 7 | matchLabels: 8 | name: test 9 | template: 10 | metadata: 11 | labels: 12 | name: test 13 | spec: 14 | schedulerName: topo-aware-scheduler 15 | containers: 16 | - name: test-deployment-1-container-1 17 | image: quay.io/fromani/numalign 18 | imagePullPolicy: IfNotPresent 19 | command: ["/bin/sh", "-c"] 20 | args: [ "while true; do numalign; sleep 100000; done;" ] 21 | resources: 22 | limits: 23 | cpu: 1 24 | memory: 0 25 | example.com/deviceA: 1 26 | example.com/deviceB: 1 27 | requests: 28 | cpu: 1 29 | memory: 0 30 | example.com/deviceA: 1 31 | example.com/deviceB: 1 32 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/worker-node-A.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: topology.node.k8s.io/v1alpha1 3 | kind: NodeResourceTopology 4 | metadata: 5 | name: worker-node-a 6 | namespace: test-namespace 7 | topologyPolicies: ["SingleNUMANodeContainerLevel"] 8 | zones: 9 | - name: node-0 10 | type: Node 11 | resources: 12 | - name: cpu 13 | capacity: 4 14 | allocatable: 3 15 | - name: example.com/deviceA 16 | capacity: 1 17 | allocatable: 1 18 | - name: example.com/deviceB 19 | capacity: 2 20 | allocatable: 2 21 | - name: node-1 22 | type: Node 23 | resources: 24 | - name: cpu 25 | capacity: 4 26 | allocatable: 3 27 | - name: example.com/deviceA 28 | capacity: 2 29 | allocatable: 2 30 | - name: example.com/deviceB 31 | capacity: 1 32 | allocatable: 1 33 | -------------------------------------------------------------------------------- /manifests/noderesourcetopology/worker-node-B.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: topology.node.k8s.io/v1alpha1 3 | kind: NodeResourceTopology 4 | metadata: 5 | name: worker-node-b 6 | namespace: test-namespace 7 | topologyPolicies: ["SingleNUMANodeContainerLevel"] 8 | zones: 9 | - name: node-0 10 | type: Node 11 | resources: 12 | - name: cpu 13 | capacity: 4 14 | allocatable: 3 15 | - name: example.com/deviceA 16 | capacity: 3 17 | allocatable: 3 18 | - name: node-1 19 | type: Node 20 | resources: 21 | - name: cpu 22 | capacity: 4 23 | allocatable: 3 24 | - name: example.com/deviceB 25 | capacity: 3 26 | allocatable: 3 27 | -------------------------------------------------------------------------------- /manifests/podstate/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | profiles: 8 | - schedulerName: default-scheduler 9 | plugins: 10 | score: 11 | enabled: 12 | - name: PodState 13 | -------------------------------------------------------------------------------- /manifests/qos/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | profiles: 8 | - schedulerName: default-scheduler 9 | plugins: 10 | queueSort: 11 | enabled: 12 | - name: QOSSort 13 | disabled: 14 | - name: "*" 15 | -------------------------------------------------------------------------------- /manifests/trimaran/scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kubescheduler.config.k8s.io/v1beta1 2 | kind: KubeSchedulerConfiguration 3 | leaderElection: 4 | leaderElect: false 5 | clientConnection: 6 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 7 | profiles: 8 | - schedulerName: trimaran 9 | plugins: 10 | score: 11 | disabled: 12 | - name: NodeResourcesBalancedAllocation 13 | - name: NodeResourcesLeastAllocated 14 | enabled: 15 | - name: TargetLoadPacking -------------------------------------------------------------------------------- /pkg/apis/config/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=kubescheduler.config.k8s.io 19 | 20 | package config // import "sigs.k8s.io/scheduler-plugins/pkg/apis/config" 21 | -------------------------------------------------------------------------------- /pkg/apis/config/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package config 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | "k8s.io/apimachinery/pkg/runtime/schema" 22 | schedscheme "k8s.io/kubernetes/pkg/scheduler/apis/config" 23 | ) 24 | 25 | // GroupName is the group name used in this package 26 | const GroupName = "kubescheduler.config.k8s.io" 27 | 28 | // SchemeGroupVersion is group version used to register these objects 29 | var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} 30 | 31 | var ( 32 | localSchemeBuilder = &schedscheme.SchemeBuilder 33 | // AddToScheme is a global function that registers this API group & version to a scheme 34 | AddToScheme = localSchemeBuilder.AddToScheme 35 | ) 36 | 37 | // addKnownTypes registers known types to the given scheme 38 | func addKnownTypes(scheme *runtime.Scheme) error { 39 | scheme.AddKnownTypes(SchemeGroupVersion, 40 | &CoschedulingArgs{}, 41 | &NodeResourcesAllocatableArgs{}, 42 | &CapacitySchedulingArgs{}, 43 | &TargetLoadPackingArgs{}, 44 | &LoadVariationRiskBalancingArgs{}, 45 | &NodeResourceTopologyMatchArgs{}, 46 | ) 47 | return nil 48 | } 49 | 50 | func init() { 51 | // We only register manually written functions here. The registration of the 52 | // generated functions takes place in the generated files. The separation 53 | // makes the code compile even when the generated files are missing. 54 | localSchemeBuilder.Register(addKnownTypes) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/apis/config/scheme/scheme.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheme 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | "k8s.io/apimachinery/pkg/runtime/serializer" 22 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 23 | kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" 24 | 25 | "sigs.k8s.io/scheduler-plugins/pkg/apis/config" 26 | configv1beta1 "sigs.k8s.io/scheduler-plugins/pkg/apis/config/v1beta1" 27 | ) 28 | 29 | var ( 30 | // Re-use the in-tree Scheme. 31 | Scheme = kubeschedulerscheme.Scheme 32 | 33 | // Codecs provides access to encoding and decoding for the scheme. 34 | Codecs = serializer.NewCodecFactory(Scheme, serializer.EnableStrict) 35 | ) 36 | 37 | func init() { 38 | AddToScheme(Scheme) 39 | } 40 | 41 | // AddToScheme builds the kubescheduler scheme using all known versions of the kubescheduler api. 42 | func AddToScheme(scheme *runtime.Scheme) { 43 | utilruntime.Must(config.AddToScheme(scheme)) 44 | utilruntime.Must(configv1beta1.AddToScheme(scheme)) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/apis/config/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +k8s:conversion-gen=sigs.k8s.io/scheduler-plugins/pkg/apis/config 19 | // +k8s:defaulter-gen=TypeMeta 20 | // +groupName=kubescheduler.config.k8s.io 21 | 22 | // Package v1beta1 is the v1beta1 version of the API. 23 | package v1beta1 // import "sigs.k8s.io/scheduler-plugins/pkg/apis/config/v1beta1" 24 | -------------------------------------------------------------------------------- /pkg/apis/config/v1beta1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | "k8s.io/apimachinery/pkg/runtime/schema" 22 | schedschemev1beta1 "k8s.io/kube-scheduler/config/v1beta1" 23 | ) 24 | 25 | // GroupName is the group name used in this package 26 | const GroupName = "kubescheduler.config.k8s.io" 27 | 28 | // SchemeGroupVersion is group version used to register these objects 29 | var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} 30 | 31 | var ( 32 | localSchemeBuilder = &schedschemev1beta1.SchemeBuilder 33 | // AddToScheme is a global function that registers this API group & version to a scheme 34 | AddToScheme = localSchemeBuilder.AddToScheme 35 | ) 36 | 37 | // addKnownTypes registers known types to the given scheme 38 | func addKnownTypes(scheme *runtime.Scheme) error { 39 | scheme.AddKnownTypes(SchemeGroupVersion, 40 | &CoschedulingArgs{}, 41 | &NodeResourcesAllocatableArgs{}, 42 | &CapacitySchedulingArgs{}, 43 | &TargetLoadPackingArgs{}, 44 | &LoadVariationRiskBalancingArgs{}, 45 | &NodeResourceTopologyMatchArgs{}, 46 | ) 47 | return nil 48 | } 49 | 50 | func init() { 51 | // We only register manually written functions here. The registration of the 52 | // generated functions takes place in the generated files. The separation 53 | // makes the code compile even when the generated files are missing. 54 | localSchemeBuilder.Register(addKnownTypes) 55 | localSchemeBuilder.Register(RegisterDefaults) 56 | localSchemeBuilder.Register(RegisterConversions) 57 | } 58 | -------------------------------------------------------------------------------- /pkg/apis/config/v1beta1/zz_generated.defaults.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | Copyright The Kubernetes Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | // Code generated by defaulter-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | ) 26 | 27 | // RegisterDefaults adds defaulters functions to the given scheme. 28 | // Public to allow building arbitrary schemes. 29 | // All generated defaulters are covering - they call all nested defaulters. 30 | func RegisterDefaults(scheme *runtime.Scheme) error { 31 | scheme.AddTypeDefaultingFunc(&CapacitySchedulingArgs{}, func(obj interface{}) { SetObjectDefaultsCapacitySchedulingArgs(obj.(*CapacitySchedulingArgs)) }) 32 | scheme.AddTypeDefaultingFunc(&CoschedulingArgs{}, func(obj interface{}) { SetObjectDefaultsCoschedulingArgs(obj.(*CoschedulingArgs)) }) 33 | scheme.AddTypeDefaultingFunc(&NodeResourcesAllocatableArgs{}, func(obj interface{}) { 34 | SetObjectDefaultsNodeResourcesAllocatableArgs(obj.(*NodeResourcesAllocatableArgs)) 35 | }) 36 | scheme.AddTypeDefaultingFunc(&TargetLoadPackingArgs{}, func(obj interface{}) { 37 | SetObjectDefaultsTargetLoadPackingArgs(obj.(*TargetLoadPackingArgs)) 38 | }) 39 | scheme.AddTypeDefaultingFunc(&LoadVariationRiskBalancingArgs{}, func(obj interface{}) { 40 | SetObjectDefaultsLoadVariationRiskBalancingArgs(obj.(*LoadVariationRiskBalancingArgs)) 41 | }) 42 | scheme.AddTypeDefaultingFunc(&NodeResourceTopologyMatchArgs{}, func(obj interface{}) { 43 | SetDefaultsNodeResourceTopologyMatchArgs(obj.(*NodeResourceTopologyMatchArgs)) 44 | }) 45 | return nil 46 | } 47 | 48 | func SetObjectDefaultsCapacitySchedulingArgs(in *CapacitySchedulingArgs) { 49 | SetDefaultsCapacitySchedulingArgs(in) 50 | } 51 | 52 | func SetObjectDefaultsCoschedulingArgs(in *CoschedulingArgs) { 53 | SetDefaultsCoschedulingArgs(in) 54 | } 55 | 56 | func SetObjectDefaultsNodeResourcesAllocatableArgs(in *NodeResourcesAllocatableArgs) { 57 | SetDefaultsNodeResourcesAllocatableArgs(in) 58 | } 59 | 60 | func SetObjectDefaultsTargetLoadPackingArgs(in *TargetLoadPackingArgs) { 61 | SetDefaultTargetLoadPackingArgs(in) 62 | } 63 | 64 | func SetObjectDefaultsLoadVariationRiskBalancingArgs(in *LoadVariationRiskBalancingArgs) { 65 | SetDefaultLoadVariationRiskBalancingArgs(in) 66 | } 67 | -------------------------------------------------------------------------------- /pkg/apis/scheduling/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheduling 18 | 19 | // GroupName is the group name used in this package 20 | const ( 21 | GroupName = "scheduling.sigs.k8s.io" 22 | ) 23 | -------------------------------------------------------------------------------- /pkg/apis/scheduling/scheme/scheme.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheme 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 22 | "k8s.io/client-go/kubernetes/scheme" 23 | schedv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 24 | ) 25 | 26 | func init() { 27 | AddToScheme(scheme.Scheme) 28 | } 29 | 30 | // AddToScheme builds the kubescheduler scheme using all known versions of the kubescheduler api. 31 | func AddToScheme(scheme *runtime.Scheme) { 32 | utilruntime.Must(schedv1alpha1.AddToScheme(scheme)) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/apis/scheduling/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=scheduling.sigs.k8s.io 19 | 20 | // Package v1alpha1 is the v1alpha1 version of the API. 21 | package v1alpha1 22 | -------------------------------------------------------------------------------- /pkg/apis/scheduling/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | 24 | "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling" 25 | ) 26 | 27 | // SchemeGroupVersion is group version used to register these objects 28 | var SchemeGroupVersion = schema.GroupVersion{Group: scheduling.GroupName, Version: "v1alpha1"} 29 | 30 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 31 | func Kind(kind string) schema.GroupKind { 32 | return SchemeGroupVersion.WithKind(kind).GroupKind() 33 | } 34 | 35 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 36 | func Resource(resource string) schema.GroupResource { 37 | return SchemeGroupVersion.WithResource(resource).GroupResource() 38 | } 39 | 40 | var ( 41 | // SchemeBuilder initializes a scheme builder 42 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 43 | // AddToScheme is a global function that registers this API group & version to a scheme 44 | AddToScheme = SchemeBuilder.AddToScheme 45 | ) 46 | 47 | // Adds the list of known types to Scheme. 48 | func addKnownTypes(scheme *runtime.Scheme) error { 49 | scheme.AddKnownTypes(SchemeGroupVersion, 50 | &ElasticQuota{}, 51 | &ElasticQuotaList{}, 52 | &PodGroup{}, 53 | &PodGroupList{}, 54 | ) 55 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/capacityscheduling/candidate.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package capacityscheduling 18 | 19 | import extenderv1 "k8s.io/kube-scheduler/extender/v1" 20 | 21 | type candidate struct { 22 | victims *extenderv1.Victims 23 | name string 24 | } 25 | 26 | // Victims returns s.victims. 27 | func (c *candidate) Victims() *extenderv1.Victims { 28 | return c.victims 29 | } 30 | 31 | // Name returns s.name. 32 | func (c *candidate) Name() string { 33 | return c.name 34 | } 35 | -------------------------------------------------------------------------------- /pkg/capacityscheduling/elasticquota_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package capacityscheduling 18 | 19 | import ( 20 | "reflect" 21 | "testing" 22 | 23 | "k8s.io/api/core/v1" 24 | "k8s.io/kubernetes/pkg/scheduler/framework" 25 | ) 26 | 27 | func TestReserveResource(t *testing.T) { 28 | tests := []struct { 29 | before *ElasticQuotaInfo 30 | name string 31 | pods []*v1.Pod 32 | expected *ElasticQuotaInfo 33 | }{ 34 | { 35 | before: &ElasticQuotaInfo{ 36 | Namespace: "ns1", 37 | Used: &framework.Resource{ 38 | MilliCPU: 1000, 39 | Memory: 200, 40 | ScalarResources: map[v1.ResourceName]int64{ 41 | ResourceGPU: 2, 42 | }, 43 | }, 44 | }, 45 | name: "ElasticQuotaInfo ReserveResource", 46 | pods: []*v1.Pod{ 47 | makePod("t1-p1", "ns1", 50, 1000, 1, midPriority, "t1-p1", "node-a"), 48 | makePod("t1-p2", "ns2", 100, 2000, 0, midPriority, "t1-p2", "node-a"), 49 | makePod("t1-p3", "ns2", 0, 0, 2, midPriority, "t1-p3", "node-a"), 50 | }, 51 | expected: &ElasticQuotaInfo{ 52 | Namespace: "ns1", 53 | Used: &framework.Resource{ 54 | MilliCPU: 4000, 55 | Memory: 350, 56 | ScalarResources: map[v1.ResourceName]int64{ 57 | ResourceGPU: 5, 58 | }, 59 | }, 60 | }, 61 | }, 62 | } 63 | 64 | for _, tt := range tests { 65 | t.Run(tt.name, func(t *testing.T) { 66 | elasticQuotaInfo := tt.before 67 | for _, pod := range tt.pods { 68 | request := computePodResourceRequest(pod) 69 | elasticQuotaInfo.reserveResource(request.Resource) 70 | } 71 | 72 | if !reflect.DeepEqual(elasticQuotaInfo, tt.expected) { 73 | t.Errorf("expected %v, got %v", tt.expected.Used, elasticQuotaInfo.Used) 74 | } 75 | }) 76 | } 77 | } 78 | 79 | func TestUnReserveResource(t *testing.T) { 80 | tests := []struct { 81 | before *ElasticQuotaInfo 82 | name string 83 | pods []*v1.Pod 84 | expected *ElasticQuotaInfo 85 | }{ 86 | { 87 | before: &ElasticQuotaInfo{ 88 | Namespace: "ns1", 89 | Used: &framework.Resource{ 90 | MilliCPU: 4000, 91 | Memory: 200, 92 | ScalarResources: map[v1.ResourceName]int64{ 93 | ResourceGPU: 5, 94 | }, 95 | }, 96 | }, 97 | name: "ElasticQuotaInfo UnReserveResource", 98 | pods: []*v1.Pod{ 99 | makePod("t1-p1", "ns1", 50, 1000, 1, midPriority, "t1-p1", "node-a"), 100 | makePod("t1-p2", "ns2", 100, 2000, 0, midPriority, "t1-p2", "node-a"), 101 | makePod("t1-p3", "ns2", 0, 0, 2, midPriority, "t1-p3", "node-a"), 102 | }, 103 | expected: &ElasticQuotaInfo{ 104 | Namespace: "ns1", 105 | Used: &framework.Resource{ 106 | MilliCPU: 1000, 107 | Memory: 50, 108 | ScalarResources: map[v1.ResourceName]int64{ 109 | ResourceGPU: 2, 110 | }, 111 | }, 112 | }, 113 | }, 114 | } 115 | 116 | for _, tt := range tests { 117 | t.Run(tt.name, func(t *testing.T) { 118 | elasticQuotaInfo := tt.before 119 | for _, pod := range tt.pods { 120 | request := computePodResourceRequest(pod) 121 | elasticQuotaInfo.unreserveResource(request.Resource) 122 | } 123 | 124 | if !reflect.DeepEqual(elasticQuotaInfo, tt.expected) { 125 | t.Errorf("expected %v, got %v", tt.expected.Used, elasticQuotaInfo.Used) 126 | } 127 | }) 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /pkg/crossnodepreemption/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | The PostFilter extension point was introduced in Kubernetes Scheduler since 1.19, 4 | and the default implementation in upstream is to preempt Pods **on the same node** 5 | to make room for the unschedulable Pod. 6 | 7 | In contrast to the "same-node-preemption" strategy, we can come up with a "cross-node-preemption" 8 | strategy to preempt Pods across multiple nodes, which is useful when a Pod cannot be 9 | scheduled due to "cross node" constraints such as PodTopologySpread and PodAntiAffinity. 10 | This was also mentioned in the original design document of [Preemption]. 11 | 12 | [Preemption]: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/pod-preemption.md#supporting-cross-node-preemption 13 | 14 | This plugin is built as a sample to demonstrate how to use PostFilter extension point, 15 | as well as inspiring users to built their own innovative strategies, such as preepmpting 16 | a group of Pods. 17 | 18 | > ⚠️ CAVEAT: Current implementation doesn't do any branch cutting, but uses a DFS algorithm 19 | > to iterate all possible preemption strategies. DO NOT use it in your production env. 20 | 21 | ## Maturity Level 22 | 23 | 24 | 25 | - [x] 💡 Sample (for demonstrating and inspiring purpose) 26 | - [ ] 👶 Alpha (used in companies for pilot projects) 27 | - [ ] 👦 Beta (used in companies and developed actively) 28 | - [ ] 👨 Stable (used in companies for production workloads) 29 | 30 | ## Example config: 31 | 32 | ```yaml 33 | apiVersion: kubescheduler.config.k8s.io/v1beta1 34 | kind: KubeSchedulerConfiguration 35 | leaderElection: 36 | leaderElect: false 37 | clientConnection: 38 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 39 | profiles: 40 | - schedulerName: default-scheduler 41 | plugins: 42 | postFilter: 43 | enabled: 44 | - name: CrossNodePreemption 45 | ``` 46 | -------------------------------------------------------------------------------- /pkg/crossnodepreemption/candidate.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package crossnodepreemption 18 | 19 | import ( 20 | v1 "k8s.io/api/core/v1" 21 | extenderv1 "k8s.io/kube-scheduler/extender/v1" 22 | ) 23 | 24 | type candidate struct { 25 | victims []*v1.Pod 26 | name string 27 | } 28 | 29 | // Victims returns s.victims. 30 | func (s *candidate) Victims() *extenderv1.Victims { 31 | return &extenderv1.Victims{ 32 | Pods: s.victims, 33 | NumPDBViolations: 0, 34 | } 35 | } 36 | 37 | // Name returns s.name. 38 | func (s *candidate) Name() string { 39 | return s.name 40 | } 41 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package versioned 20 | 21 | import ( 22 | "fmt" 23 | 24 | discovery "k8s.io/client-go/discovery" 25 | rest "k8s.io/client-go/rest" 26 | flowcontrol "k8s.io/client-go/util/flowcontrol" 27 | schedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned/typed/scheduling/v1alpha1" 28 | ) 29 | 30 | type Interface interface { 31 | Discovery() discovery.DiscoveryInterface 32 | SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface 33 | } 34 | 35 | // Clientset contains the clients for groups. Each group has exactly one 36 | // version included in a Clientset. 37 | type Clientset struct { 38 | *discovery.DiscoveryClient 39 | schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client 40 | } 41 | 42 | // SchedulingV1alpha1 retrieves the SchedulingV1alpha1Client 43 | func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface { 44 | return c.schedulingV1alpha1 45 | } 46 | 47 | // Discovery retrieves the DiscoveryClient 48 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 49 | if c == nil { 50 | return nil 51 | } 52 | return c.DiscoveryClient 53 | } 54 | 55 | // NewForConfig creates a new Clientset for the given config. 56 | // If config's RateLimiter is not set and QPS and Burst are acceptable, 57 | // NewForConfig will generate a rate-limiter in configShallowCopy. 58 | func NewForConfig(c *rest.Config) (*Clientset, error) { 59 | configShallowCopy := *c 60 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 61 | if configShallowCopy.Burst <= 0 { 62 | return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") 63 | } 64 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 65 | } 66 | var cs Clientset 67 | var err error 68 | cs.schedulingV1alpha1, err = schedulingv1alpha1.NewForConfig(&configShallowCopy) 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) 74 | if err != nil { 75 | return nil, err 76 | } 77 | return &cs, nil 78 | } 79 | 80 | // NewForConfigOrDie creates a new Clientset for the given config and 81 | // panics if there is an error in the config. 82 | func NewForConfigOrDie(c *rest.Config) *Clientset { 83 | var cs Clientset 84 | cs.schedulingV1alpha1 = schedulingv1alpha1.NewForConfigOrDie(c) 85 | 86 | cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) 87 | return &cs 88 | } 89 | 90 | // New creates a new Clientset for the given RESTClient. 91 | func New(c rest.Interface) *Clientset { 92 | var cs Clientset 93 | cs.schedulingV1alpha1 = schedulingv1alpha1.New(c) 94 | 95 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 96 | return &cs 97 | } 98 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated clientset. 20 | package versioned 21 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "k8s.io/apimachinery/pkg/watch" 24 | "k8s.io/client-go/discovery" 25 | fakediscovery "k8s.io/client-go/discovery/fake" 26 | "k8s.io/client-go/testing" 27 | clientset "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned" 28 | schedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned/typed/scheduling/v1alpha1" 29 | fakeschedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned/typed/scheduling/v1alpha1/fake" 30 | ) 31 | 32 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 33 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 34 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 35 | // for a real clientset and is mostly useful in simple unit tests. 36 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 37 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 38 | for _, obj := range objects { 39 | if err := o.Add(obj); err != nil { 40 | panic(err) 41 | } 42 | } 43 | 44 | cs := &Clientset{tracker: o} 45 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 46 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 47 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 48 | gvr := action.GetResource() 49 | ns := action.GetNamespace() 50 | watch, err := o.Watch(gvr, ns) 51 | if err != nil { 52 | return false, nil, err 53 | } 54 | return true, watch, nil 55 | }) 56 | 57 | return cs 58 | } 59 | 60 | // Clientset implements clientset.Interface. Meant to be embedded into a 61 | // struct to get a default implementation. This makes faking out just the method 62 | // you want to test easier. 63 | type Clientset struct { 64 | testing.Fake 65 | discovery *fakediscovery.FakeDiscovery 66 | tracker testing.ObjectTracker 67 | } 68 | 69 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 70 | return c.discovery 71 | } 72 | 73 | func (c *Clientset) Tracker() testing.ObjectTracker { 74 | return c.tracker 75 | } 76 | 77 | var _ clientset.Interface = &Clientset{} 78 | 79 | // SchedulingV1alpha1 retrieves the SchedulingV1alpha1Client 80 | func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface { 81 | return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake} 82 | } 83 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated fake clientset. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | runtime "k8s.io/apimachinery/pkg/runtime" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | schedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 28 | ) 29 | 30 | var scheme = runtime.NewScheme() 31 | var codecs = serializer.NewCodecFactory(scheme) 32 | 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | schedulingv1alpha1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package contains the scheme of the automatically generated clientset. 20 | package scheme 21 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package scheme 20 | 21 | import ( 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | runtime "k8s.io/apimachinery/pkg/runtime" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | schedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 28 | ) 29 | 30 | var Scheme = runtime.NewScheme() 31 | var Codecs = serializer.NewCodecFactory(Scheme) 32 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | schedulingv1alpha1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(Scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/scheduling/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated typed clients. 20 | package v1alpha1 21 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/scheduling/v1alpha1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // Package fake has the automatically generated clients. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/scheduling/v1alpha1/fake/fake_scheduling_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | rest "k8s.io/client-go/rest" 23 | testing "k8s.io/client-go/testing" 24 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned/typed/scheduling/v1alpha1" 25 | ) 26 | 27 | type FakeSchedulingV1alpha1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeSchedulingV1alpha1) ElasticQuotas(namespace string) v1alpha1.ElasticQuotaInterface { 32 | return &FakeElasticQuotas{c, namespace} 33 | } 34 | 35 | func (c *FakeSchedulingV1alpha1) PodGroups(namespace string) v1alpha1.PodGroupInterface { 36 | return &FakePodGroups{c, namespace} 37 | } 38 | 39 | // RESTClient returns a RESTClient that is used to communicate 40 | // with API server by this client implementation. 41 | func (c *FakeSchedulingV1alpha1) RESTClient() rest.Interface { 42 | var ret *rest.RESTClient 43 | return ret 44 | } 45 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/scheduling/v1alpha1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | type ElasticQuotaExpansion interface{} 22 | 23 | type PodGroupExpansion interface{} 24 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/scheduling/v1alpha1/scheduling_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import ( 22 | rest "k8s.io/client-go/rest" 23 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 24 | "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned/scheme" 25 | ) 26 | 27 | type SchedulingV1alpha1Interface interface { 28 | RESTClient() rest.Interface 29 | ElasticQuotasGetter 30 | PodGroupsGetter 31 | } 32 | 33 | // SchedulingV1alpha1Client is used to interact with features provided by the scheduling.sigs.k8s.io group. 34 | type SchedulingV1alpha1Client struct { 35 | restClient rest.Interface 36 | } 37 | 38 | func (c *SchedulingV1alpha1Client) ElasticQuotas(namespace string) ElasticQuotaInterface { 39 | return newElasticQuotas(c, namespace) 40 | } 41 | 42 | func (c *SchedulingV1alpha1Client) PodGroups(namespace string) PodGroupInterface { 43 | return newPodGroups(c, namespace) 44 | } 45 | 46 | // NewForConfig creates a new SchedulingV1alpha1Client for the given config. 47 | func NewForConfig(c *rest.Config) (*SchedulingV1alpha1Client, error) { 48 | config := *c 49 | if err := setConfigDefaults(&config); err != nil { 50 | return nil, err 51 | } 52 | client, err := rest.RESTClientFor(&config) 53 | if err != nil { 54 | return nil, err 55 | } 56 | return &SchedulingV1alpha1Client{client}, nil 57 | } 58 | 59 | // NewForConfigOrDie creates a new SchedulingV1alpha1Client for the given config and 60 | // panics if there is an error in the config. 61 | func NewForConfigOrDie(c *rest.Config) *SchedulingV1alpha1Client { 62 | client, err := NewForConfig(c) 63 | if err != nil { 64 | panic(err) 65 | } 66 | return client 67 | } 68 | 69 | // New creates a new SchedulingV1alpha1Client for the given RESTClient. 70 | func New(c rest.Interface) *SchedulingV1alpha1Client { 71 | return &SchedulingV1alpha1Client{c} 72 | } 73 | 74 | func setConfigDefaults(config *rest.Config) error { 75 | gv := v1alpha1.SchemeGroupVersion 76 | config.GroupVersion = &gv 77 | config.APIPath = "/apis" 78 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 79 | 80 | if config.UserAgent == "" { 81 | config.UserAgent = rest.DefaultKubernetesUserAgent() 82 | } 83 | 84 | return nil 85 | } 86 | 87 | // RESTClient returns a RESTClient that is used to communicate 88 | // with API server by this client implementation. 89 | func (c *SchedulingV1alpha1Client) RESTClient() rest.Interface { 90 | if c == nil { 91 | return nil 92 | } 93 | return c.restClient 94 | } 95 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package externalversions 20 | 21 | import ( 22 | "fmt" 23 | 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | cache "k8s.io/client-go/tools/cache" 26 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 27 | ) 28 | 29 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 30 | // sharedInformers based on type 31 | type GenericInformer interface { 32 | Informer() cache.SharedIndexInformer 33 | Lister() cache.GenericLister 34 | } 35 | 36 | type genericInformer struct { 37 | informer cache.SharedIndexInformer 38 | resource schema.GroupResource 39 | } 40 | 41 | // Informer returns the SharedIndexInformer. 42 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 43 | return f.informer 44 | } 45 | 46 | // Lister returns the GenericLister. 47 | func (f *genericInformer) Lister() cache.GenericLister { 48 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 49 | } 50 | 51 | // ForResource gives generic access to a shared informer of the matching type 52 | // TODO extend this to unknown resources with a client pool 53 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 54 | switch resource { 55 | // Group=scheduling.sigs.k8s.io, Version=v1alpha1 56 | case v1alpha1.SchemeGroupVersion.WithResource("elasticquotas"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1alpha1().ElasticQuotas().Informer()}, nil 58 | case v1alpha1.SchemeGroupVersion.WithResource("podgroups"): 59 | return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1alpha1().PodGroups().Informer()}, nil 60 | 61 | } 62 | 63 | return nil, fmt.Errorf("no informer found for %v", resource) 64 | } 65 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package internalinterfaces 20 | 21 | import ( 22 | time "time" 23 | 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | runtime "k8s.io/apimachinery/pkg/runtime" 26 | cache "k8s.io/client-go/tools/cache" 27 | versioned "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned" 28 | ) 29 | 30 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 31 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 32 | 33 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 34 | type SharedInformerFactory interface { 35 | Start(stopCh <-chan struct{}) 36 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 37 | } 38 | 39 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 40 | type TweakListOptionsFunc func(*v1.ListOptions) 41 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/scheduling/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package scheduling 20 | 21 | import ( 22 | internalinterfaces "sigs.k8s.io/scheduler-plugins/pkg/generated/informers/externalversions/internalinterfaces" 23 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/informers/externalversions/scheduling/v1alpha1" 24 | ) 25 | 26 | // Interface provides access to each of this group's versions. 27 | type Interface interface { 28 | // V1alpha1 provides access to shared informers for resources in V1alpha1. 29 | V1alpha1() v1alpha1.Interface 30 | } 31 | 32 | type group struct { 33 | factory internalinterfaces.SharedInformerFactory 34 | namespace string 35 | tweakListOptions internalinterfaces.TweakListOptionsFunc 36 | } 37 | 38 | // New returns a new Interface. 39 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 40 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 41 | } 42 | 43 | // V1alpha1 returns a new v1alpha1.Interface. 44 | func (g *group) V1alpha1() v1alpha1.Interface { 45 | return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/scheduling/v1alpha1/elasticquota.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import ( 22 | "context" 23 | time "time" 24 | 25 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | watch "k8s.io/apimachinery/pkg/watch" 28 | cache "k8s.io/client-go/tools/cache" 29 | schedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 30 | versioned "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned" 31 | internalinterfaces "sigs.k8s.io/scheduler-plugins/pkg/generated/informers/externalversions/internalinterfaces" 32 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/listers/scheduling/v1alpha1" 33 | ) 34 | 35 | // ElasticQuotaInformer provides access to a shared informer and lister for 36 | // ElasticQuotas. 37 | type ElasticQuotaInformer interface { 38 | Informer() cache.SharedIndexInformer 39 | Lister() v1alpha1.ElasticQuotaLister 40 | } 41 | 42 | type elasticQuotaInformer struct { 43 | factory internalinterfaces.SharedInformerFactory 44 | tweakListOptions internalinterfaces.TweakListOptionsFunc 45 | namespace string 46 | } 47 | 48 | // NewElasticQuotaInformer constructs a new informer for ElasticQuota type. 49 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 50 | // one. This reduces memory footprint and number of connections to the server. 51 | func NewElasticQuotaInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 52 | return NewFilteredElasticQuotaInformer(client, namespace, resyncPeriod, indexers, nil) 53 | } 54 | 55 | // NewFilteredElasticQuotaInformer constructs a new informer for ElasticQuota type. 56 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 57 | // one. This reduces memory footprint and number of connections to the server. 58 | func NewFilteredElasticQuotaInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 59 | return cache.NewSharedIndexInformer( 60 | &cache.ListWatch{ 61 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 62 | if tweakListOptions != nil { 63 | tweakListOptions(&options) 64 | } 65 | return client.SchedulingV1alpha1().ElasticQuotas(namespace).List(context.TODO(), options) 66 | }, 67 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 68 | if tweakListOptions != nil { 69 | tweakListOptions(&options) 70 | } 71 | return client.SchedulingV1alpha1().ElasticQuotas(namespace).Watch(context.TODO(), options) 72 | }, 73 | }, 74 | &schedulingv1alpha1.ElasticQuota{}, 75 | resyncPeriod, 76 | indexers, 77 | ) 78 | } 79 | 80 | func (f *elasticQuotaInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 81 | return NewFilteredElasticQuotaInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 82 | } 83 | 84 | func (f *elasticQuotaInformer) Informer() cache.SharedIndexInformer { 85 | return f.factory.InformerFor(&schedulingv1alpha1.ElasticQuota{}, f.defaultInformer) 86 | } 87 | 88 | func (f *elasticQuotaInformer) Lister() v1alpha1.ElasticQuotaLister { 89 | return v1alpha1.NewElasticQuotaLister(f.Informer().GetIndexer()) 90 | } 91 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/scheduling/v1alpha1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import ( 22 | internalinterfaces "sigs.k8s.io/scheduler-plugins/pkg/generated/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to all the informers in this group version. 26 | type Interface interface { 27 | // ElasticQuotas returns a ElasticQuotaInformer. 28 | ElasticQuotas() ElasticQuotaInformer 29 | // PodGroups returns a PodGroupInformer. 30 | PodGroups() PodGroupInformer 31 | } 32 | 33 | type version struct { 34 | factory internalinterfaces.SharedInformerFactory 35 | namespace string 36 | tweakListOptions internalinterfaces.TweakListOptionsFunc 37 | } 38 | 39 | // New returns a new Interface. 40 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 41 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 42 | } 43 | 44 | // ElasticQuotas returns a ElasticQuotaInformer. 45 | func (v *version) ElasticQuotas() ElasticQuotaInformer { 46 | return &elasticQuotaInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 47 | } 48 | 49 | // PodGroups returns a PodGroupInformer. 50 | func (v *version) PodGroups() PodGroupInformer { 51 | return &podGroupInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 52 | } 53 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/scheduling/v1alpha1/podgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import ( 22 | "context" 23 | time "time" 24 | 25 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | watch "k8s.io/apimachinery/pkg/watch" 28 | cache "k8s.io/client-go/tools/cache" 29 | schedulingv1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 30 | versioned "sigs.k8s.io/scheduler-plugins/pkg/generated/clientset/versioned" 31 | internalinterfaces "sigs.k8s.io/scheduler-plugins/pkg/generated/informers/externalversions/internalinterfaces" 32 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/generated/listers/scheduling/v1alpha1" 33 | ) 34 | 35 | // PodGroupInformer provides access to a shared informer and lister for 36 | // PodGroups. 37 | type PodGroupInformer interface { 38 | Informer() cache.SharedIndexInformer 39 | Lister() v1alpha1.PodGroupLister 40 | } 41 | 42 | type podGroupInformer struct { 43 | factory internalinterfaces.SharedInformerFactory 44 | tweakListOptions internalinterfaces.TweakListOptionsFunc 45 | namespace string 46 | } 47 | 48 | // NewPodGroupInformer constructs a new informer for PodGroup type. 49 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 50 | // one. This reduces memory footprint and number of connections to the server. 51 | func NewPodGroupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 52 | return NewFilteredPodGroupInformer(client, namespace, resyncPeriod, indexers, nil) 53 | } 54 | 55 | // NewFilteredPodGroupInformer constructs a new informer for PodGroup type. 56 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 57 | // one. This reduces memory footprint and number of connections to the server. 58 | func NewFilteredPodGroupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 59 | return cache.NewSharedIndexInformer( 60 | &cache.ListWatch{ 61 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 62 | if tweakListOptions != nil { 63 | tweakListOptions(&options) 64 | } 65 | return client.SchedulingV1alpha1().PodGroups(namespace).List(context.TODO(), options) 66 | }, 67 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 68 | if tweakListOptions != nil { 69 | tweakListOptions(&options) 70 | } 71 | return client.SchedulingV1alpha1().PodGroups(namespace).Watch(context.TODO(), options) 72 | }, 73 | }, 74 | &schedulingv1alpha1.PodGroup{}, 75 | resyncPeriod, 76 | indexers, 77 | ) 78 | } 79 | 80 | func (f *podGroupInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 81 | return NewFilteredPodGroupInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 82 | } 83 | 84 | func (f *podGroupInformer) Informer() cache.SharedIndexInformer { 85 | return f.factory.InformerFor(&schedulingv1alpha1.PodGroup{}, f.defaultInformer) 86 | } 87 | 88 | func (f *podGroupInformer) Lister() v1alpha1.PodGroupLister { 89 | return v1alpha1.NewPodGroupLister(f.Informer().GetIndexer()) 90 | } 91 | -------------------------------------------------------------------------------- /pkg/generated/listers/scheduling/v1alpha1/elasticquota.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/api/errors" 23 | "k8s.io/apimachinery/pkg/labels" 24 | "k8s.io/client-go/tools/cache" 25 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 26 | ) 27 | 28 | // ElasticQuotaLister helps list ElasticQuotas. 29 | // All objects returned here must be treated as read-only. 30 | type ElasticQuotaLister interface { 31 | // List lists all ElasticQuotas in the indexer. 32 | // Objects returned here must be treated as read-only. 33 | List(selector labels.Selector) (ret []*v1alpha1.ElasticQuota, err error) 34 | // ElasticQuotas returns an object that can list and get ElasticQuotas. 35 | ElasticQuotas(namespace string) ElasticQuotaNamespaceLister 36 | ElasticQuotaListerExpansion 37 | } 38 | 39 | // elasticQuotaLister implements the ElasticQuotaLister interface. 40 | type elasticQuotaLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewElasticQuotaLister returns a new ElasticQuotaLister. 45 | func NewElasticQuotaLister(indexer cache.Indexer) ElasticQuotaLister { 46 | return &elasticQuotaLister{indexer: indexer} 47 | } 48 | 49 | // List lists all ElasticQuotas in the indexer. 50 | func (s *elasticQuotaLister) List(selector labels.Selector) (ret []*v1alpha1.ElasticQuota, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1alpha1.ElasticQuota)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // ElasticQuotas returns an object that can list and get ElasticQuotas. 58 | func (s *elasticQuotaLister) ElasticQuotas(namespace string) ElasticQuotaNamespaceLister { 59 | return elasticQuotaNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // ElasticQuotaNamespaceLister helps list and get ElasticQuotas. 63 | // All objects returned here must be treated as read-only. 64 | type ElasticQuotaNamespaceLister interface { 65 | // List lists all ElasticQuotas in the indexer for a given namespace. 66 | // Objects returned here must be treated as read-only. 67 | List(selector labels.Selector) (ret []*v1alpha1.ElasticQuota, err error) 68 | // Get retrieves the ElasticQuota from the indexer for a given namespace and name. 69 | // Objects returned here must be treated as read-only. 70 | Get(name string) (*v1alpha1.ElasticQuota, error) 71 | ElasticQuotaNamespaceListerExpansion 72 | } 73 | 74 | // elasticQuotaNamespaceLister implements the ElasticQuotaNamespaceLister 75 | // interface. 76 | type elasticQuotaNamespaceLister struct { 77 | indexer cache.Indexer 78 | namespace string 79 | } 80 | 81 | // List lists all ElasticQuotas in the indexer for a given namespace. 82 | func (s elasticQuotaNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ElasticQuota, err error) { 83 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 84 | ret = append(ret, m.(*v1alpha1.ElasticQuota)) 85 | }) 86 | return ret, err 87 | } 88 | 89 | // Get retrieves the ElasticQuota from the indexer for a given namespace and name. 90 | func (s elasticQuotaNamespaceLister) Get(name string) (*v1alpha1.ElasticQuota, error) { 91 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 92 | if err != nil { 93 | return nil, err 94 | } 95 | if !exists { 96 | return nil, errors.NewNotFound(v1alpha1.Resource("elasticquota"), name) 97 | } 98 | return obj.(*v1alpha1.ElasticQuota), nil 99 | } 100 | -------------------------------------------------------------------------------- /pkg/generated/listers/scheduling/v1alpha1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | // ElasticQuotaListerExpansion allows custom methods to be added to 22 | // ElasticQuotaLister. 23 | type ElasticQuotaListerExpansion interface{} 24 | 25 | // ElasticQuotaNamespaceListerExpansion allows custom methods to be added to 26 | // ElasticQuotaNamespaceLister. 27 | type ElasticQuotaNamespaceListerExpansion interface{} 28 | 29 | // PodGroupListerExpansion allows custom methods to be added to 30 | // PodGroupLister. 31 | type PodGroupListerExpansion interface{} 32 | 33 | // PodGroupNamespaceListerExpansion allows custom methods to be added to 34 | // PodGroupNamespaceLister. 35 | type PodGroupNamespaceListerExpansion interface{} 36 | -------------------------------------------------------------------------------- /pkg/generated/listers/scheduling/v1alpha1/podgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/api/errors" 23 | "k8s.io/apimachinery/pkg/labels" 24 | "k8s.io/client-go/tools/cache" 25 | v1alpha1 "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 26 | ) 27 | 28 | // PodGroupLister helps list PodGroups. 29 | // All objects returned here must be treated as read-only. 30 | type PodGroupLister interface { 31 | // List lists all PodGroups in the indexer. 32 | // Objects returned here must be treated as read-only. 33 | List(selector labels.Selector) (ret []*v1alpha1.PodGroup, err error) 34 | // PodGroups returns an object that can list and get PodGroups. 35 | PodGroups(namespace string) PodGroupNamespaceLister 36 | PodGroupListerExpansion 37 | } 38 | 39 | // podGroupLister implements the PodGroupLister interface. 40 | type podGroupLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewPodGroupLister returns a new PodGroupLister. 45 | func NewPodGroupLister(indexer cache.Indexer) PodGroupLister { 46 | return &podGroupLister{indexer: indexer} 47 | } 48 | 49 | // List lists all PodGroups in the indexer. 50 | func (s *podGroupLister) List(selector labels.Selector) (ret []*v1alpha1.PodGroup, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1alpha1.PodGroup)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // PodGroups returns an object that can list and get PodGroups. 58 | func (s *podGroupLister) PodGroups(namespace string) PodGroupNamespaceLister { 59 | return podGroupNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // PodGroupNamespaceLister helps list and get PodGroups. 63 | // All objects returned here must be treated as read-only. 64 | type PodGroupNamespaceLister interface { 65 | // List lists all PodGroups in the indexer for a given namespace. 66 | // Objects returned here must be treated as read-only. 67 | List(selector labels.Selector) (ret []*v1alpha1.PodGroup, err error) 68 | // Get retrieves the PodGroup from the indexer for a given namespace and name. 69 | // Objects returned here must be treated as read-only. 70 | Get(name string) (*v1alpha1.PodGroup, error) 71 | PodGroupNamespaceListerExpansion 72 | } 73 | 74 | // podGroupNamespaceLister implements the PodGroupNamespaceLister 75 | // interface. 76 | type podGroupNamespaceLister struct { 77 | indexer cache.Indexer 78 | namespace string 79 | } 80 | 81 | // List lists all PodGroups in the indexer for a given namespace. 82 | func (s podGroupNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.PodGroup, err error) { 83 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 84 | ret = append(ret, m.(*v1alpha1.PodGroup)) 85 | }) 86 | return ret, err 87 | } 88 | 89 | // Get retrieves the PodGroup from the indexer for a given namespace and name. 90 | func (s podGroupNamespaceLister) Get(name string) (*v1alpha1.PodGroup, error) { 91 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 92 | if err != nil { 93 | return nil, err 94 | } 95 | if !exists { 96 | return nil, errors.NewNotFound(v1alpha1.Resource("podgroup"), name) 97 | } 98 | return obj.(*v1alpha1.PodGroup), nil 99 | } 100 | -------------------------------------------------------------------------------- /pkg/noderesources/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This folder holds the node resources allocatable plugin implemented as discussed in [NodeResourcesLeastAllocatable as score plugin](https://github.com/kubernetes/kubernetes/issues/93547). 4 | 5 | ## Maturity Level 6 | 7 | 8 | 9 | - [ ] 💡 Sample (for demonstrating and inspiring purpose) 10 | - [ ] 👶 Alpha (used in companies for pilot projects) 11 | - [x] 👦 Beta (used in companies and developed actively) 12 | - [ ] 👨 Stable (used in companies for production workloads) 13 | 14 | ## Node Resources Allocatable Plugin 15 | ### Resource Weights 16 | Resources are assigned weights based on the plugin args resources param. The base units for CPU are millicores, while the base units for memory are bytes. 17 | 18 | Example config: 19 | 20 | ```yaml 21 | apiVersion: kubescheduler.config.k8s.io/v1beta1 22 | kind: KubeSchedulerConfiguration 23 | leaderElection: 24 | leaderElect: false 25 | clientConnection: 26 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 27 | profiles: 28 | - schedulerName: default-scheduler 29 | plugins: 30 | score: 31 | enabled: 32 | - name: NodeResourcesAllocatable 33 | pluginConfig: 34 | - name: NodeResourcesAllocatable 35 | args: 36 | mode: Least 37 | resources: 38 | - name: cpu 39 | weight: 1000000 40 | - name: memory 41 | weight: 1 42 | ``` 43 | 44 | ### Node Resources Least Allocatable 45 | If plugin args specify the priority param "Least", then nodes with the least allocatable resources are scored highest. 46 | 47 | ### Node Resources Most Allocatable 48 | If plugin args specify the priority param "Most", then nodes with the most allocatable resources are scored highest. 49 | -------------------------------------------------------------------------------- /pkg/noderesourcetopology/numa-topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/pkg/noderesourcetopology/numa-topology.png -------------------------------------------------------------------------------- /pkg/podstate/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This folder holds a sample plugin implementation based 4 | on the number of terminating and nominated Pods on a Node. 5 | 6 | ## Maturity Level 7 | 8 | 9 | 10 | - [x] 💡 Sample (for demonstrating and inspiring purpose) 11 | - [ ] 👶 Alpha (used in companies for pilot projects) 12 | - [ ] 👦 Beta (used in companies and developed actively) 13 | - [ ] 👨 Stable (used in companies for production workloads) 14 | 15 | ## Pod State Plugin 16 | 17 | This is a score plugin that takes terminating and nominated Pods into accounts in the following manner: 18 | - the nodes that have more terminating Pods will get a higher score as those terminating Pods would be physically removed eventually from nodes 19 | - the nodes that have more nominated Pods (which carry .status.nominatedNodeName) will get a lower score as the nominated nodes are supposed to accommodate some preemptor pod in a 20 | future scheduling cycle. 21 | 22 | ## Example config: 23 | 24 | ```yaml 25 | apiVersion: kubescheduler.config.k8s.io/v1beta1 26 | kind: KubeSchedulerConfiguration 27 | leaderElection: 28 | leaderElect: false 29 | clientConnection: 30 | kubeconfig: "REPLACE_ME_WITH_KUBE_CONFIG_PATH" 31 | profiles: 32 | - schedulerName: default-scheduler 33 | plugins: 34 | score: 35 | enabled: 36 | - name: PodState 37 | ``` -------------------------------------------------------------------------------- /pkg/podstate/pod_state.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package podstate 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "math" 23 | 24 | "k8s.io/api/core/v1" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/kubernetes/pkg/scheduler/framework" 27 | ) 28 | 29 | type PodState struct { 30 | handle framework.Handle 31 | } 32 | 33 | var _ = framework.ScorePlugin(&PodState{}) 34 | 35 | // Name is the name of the plugin used in the Registry and configurations. 36 | const Name = "PodState" 37 | 38 | func (ps *PodState) Name() string { 39 | return Name 40 | } 41 | 42 | // Score invoked at the score extension point. 43 | func (ps *PodState) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) { 44 | nodeInfo, err := ps.handle.SnapshotSharedLister().NodeInfos().Get(nodeName) 45 | if err != nil { 46 | return 0, framework.NewStatus(framework.Error, fmt.Sprintf("getting node %q from Snapshot: %v", nodeName, err)) 47 | } 48 | 49 | // pe.score favors nodes with terminating pods instead of nominated pods 50 | // It calculates the sum of the node's terminating pods and nominated pods 51 | return ps.score(nodeInfo) 52 | } 53 | 54 | // ScoreExtensions of the Score plugin. 55 | func (ps *PodState) ScoreExtensions() framework.ScoreExtensions { 56 | return ps 57 | } 58 | 59 | func (ps *PodState) score(nodeInfo *framework.NodeInfo) (int64, *framework.Status) { 60 | var terminatingPodNum, nominatedPodNum int64 61 | // get nominated Pods for node from nominatedPodMap 62 | nominatedPodNum = int64(len(ps.handle.NominatedPodsForNode(nodeInfo.Node().Name))) 63 | for _, p := range nodeInfo.Pods { 64 | // Pod is terminating if DeletionTimestamp has been set 65 | if p.Pod.DeletionTimestamp != nil { 66 | terminatingPodNum++ 67 | } 68 | } 69 | return terminatingPodNum - nominatedPodNum, nil 70 | } 71 | 72 | func (ps *PodState) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status { 73 | // Find highest and lowest scores. 74 | var highest int64 = -math.MaxInt64 75 | var lowest int64 = math.MaxInt64 76 | for _, nodeScore := range scores { 77 | if nodeScore.Score > highest { 78 | highest = nodeScore.Score 79 | } 80 | if nodeScore.Score < lowest { 81 | lowest = nodeScore.Score 82 | } 83 | } 84 | 85 | // Transform the highest to lowest score range to fit the framework's min to max node score range. 86 | oldRange := highest - lowest 87 | newRange := framework.MaxNodeScore - framework.MinNodeScore 88 | for i, nodeScore := range scores { 89 | if oldRange == 0 { 90 | scores[i].Score = framework.MinNodeScore 91 | } else { 92 | scores[i].Score = ((nodeScore.Score - lowest) * newRange / oldRange) + framework.MinNodeScore 93 | } 94 | } 95 | 96 | return nil 97 | } 98 | 99 | // New initializes a new plugin and returns it. 100 | func New(_ runtime.Object, h framework.Handle) (framework.Plugin, error) { 101 | return &PodState{handle: h}, nil 102 | } 103 | -------------------------------------------------------------------------------- /pkg/qos/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This folder holds some sample plugin implementations based on [QoS 4 | (Quality of Service) class](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/) 5 | of Pods. 6 | 7 | ## Maturity Level 8 | 9 | 10 | 11 | - [x] 💡 Sample (for demonstrating and inspiring purpose) 12 | - [ ] 👶 Alpha (used in companies for pilot projects) 13 | - [ ] 👦 Beta (used in companies and developed actively) 14 | - [ ] 👨 Stable (used in companies for production workloads) 15 | 16 | ## QOS QueueSort Plugin 17 | 18 | Sorts pods by .spec.priority and breaks ties by the [quality of service class](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes). 19 | Specifically, this plugin enqueue the Pods with the following order: 20 | 21 | - Guaranteed (requests == limits) 22 | - Burstable (requests < limits) 23 | - BestEffort (requests and limits not set) 24 | -------------------------------------------------------------------------------- /pkg/qos/queue_sort.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package qos 18 | 19 | import ( 20 | v1 "k8s.io/api/core/v1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | corev1helpers "k8s.io/component-helpers/scheduling/corev1" 23 | v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos" 24 | "k8s.io/kubernetes/pkg/scheduler/framework" 25 | ) 26 | 27 | // Name is the name of the plugin used in the plugin registry and configurations. 28 | const Name = "QOSSort" 29 | 30 | // Sort is a plugin that implements QoS class based sorting. 31 | type Sort struct{} 32 | 33 | var _ framework.QueueSortPlugin = &Sort{} 34 | 35 | // Name returns name of the plugin. 36 | func (pl *Sort) Name() string { 37 | return Name 38 | } 39 | 40 | // Less is the function used by the activeQ heap algorithm to sort pods. 41 | // It sorts pods based on their priorities. When the priorities are equal, it uses 42 | // the Pod QoS classes to break the tie. 43 | func (*Sort) Less(pInfo1, pInfo2 *framework.QueuedPodInfo) bool { 44 | p1 := corev1helpers.PodPriority(pInfo1.Pod) 45 | p2 := corev1helpers.PodPriority(pInfo2.Pod) 46 | return (p1 > p2) || (p1 == p2 && compQOS(pInfo1.Pod, pInfo2.Pod)) 47 | } 48 | 49 | func compQOS(p1, p2 *v1.Pod) bool { 50 | p1QOS, p2QOS := v1qos.GetPodQOS(p1), v1qos.GetPodQOS(p2) 51 | if p1QOS == v1.PodQOSGuaranteed { 52 | return true 53 | } 54 | if p1QOS == v1.PodQOSBurstable { 55 | return p2QOS != v1.PodQOSGuaranteed 56 | } 57 | return p2QOS == v1.PodQOSBestEffort 58 | } 59 | 60 | // New initializes a new plugin and returns it. 61 | func New(_ runtime.Object, _ framework.Handle) (framework.Plugin, error) { 62 | return &Sort{}, nil 63 | } 64 | -------------------------------------------------------------------------------- /pkg/trimaran/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Trimaran: Load-aware scheduling plugins 3 | 4 | Trimaran is a collection of load-aware scheduler plugins described in [Trimaran: Real Load Aware Scheduling](https://github.com/kubernetes-sigs/scheduler-plugins/blob/master/kep/61-Trimaran-real-load-aware-scheduling). 5 | 6 | Currently, the collection consists of the following plugins. 7 | 8 | - `TargetLoadPacking`: Implements a packing policy up to a configured CPU utilization, then switches to a spreading policy among the hot nodes. (Supports CPU resource.) 9 | - `LoadVariationRiskBalancing`: Equalizes the risk, defined as a combined measure of average utilization and variation in utilization, among nodes. (Supports CPU and memory resources.) 10 | 11 | The Trimaran plugins utilize a [load-watcher](https://github.com/paypal/load-watcher) to access resource utilization data via metrics providers. Currently, the `load-watcher` supports three metrics providers: [Kubernetes Metrics Server](https://github.com/kubernetes-sigs/metrics-server), [Prometheus Server](https://prometheus.io/), and [SignalFx](https://docs.signalfx.com/en/latest/integrations/agent/index.html). 12 | 13 | There are two modes for a Trimaran plugin to use the `load-watcher`: as a service or as a library. 14 | 15 | ## load-watcher as a service 16 | 17 | In this mode, the Trimaran plugin uses a deployed `load-watcher` service in the cluster as depicted in the figure below. A `watcherAddress` configuration parameter is required to define the `load-watcher` service endpoint. For example, 18 | 19 | ```yaml 20 | watcherAddress: http://xxxx.svc.cluster.local:2020 21 | ``` 22 | 23 | Instructions on how to build and deploy the `load-watcher` can be found [here](https://github.com/paypal/load-watcher/blob/master/README.md). The `load-watcher` service may also be deployed in the same scheduler pod, following the tutorial [here](https://medium.com/paypal-engineering/real-load-aware-scheduling-in-kubernetes-with-trimaran-a8efe14d51e2). 24 | 25 | ![load-watcher as a service](docs/load-watcher-service.png) 26 | 27 | ## load-watcher as a library 28 | 29 | In this mode, the Trimaran plugin embeds the `load-watcher` as a library, which in turn accesses the configured metrics provider. In this case, we have three configuration parameters: `metricProvider.type`, `metricProvider.address` and `metricProvider.token`. 30 | 31 | ![load-watcher as a library](docs/load-watcher-library.png) 32 | 33 | The configuration parameters should be set as follows. 34 | 35 | - `metricProvider.type`: the type of the metrics provider 36 | - `KubernetesMetricsServer` (default) 37 | - `Prometheus` 38 | - `SignalFx` 39 | - `metricProvider.address`: the address of the metrics provider endpoint, if needed. For the Kubernetes Metrics Server, this parameter may be ignored. For the Prometheus Server, an example setting is 40 | - `http://prometheus-k8s.monitoring.svc.cluster.local:9090` 41 | - `metricProvider.token`: set only if an authentication token is needed to access the metrics provider. 42 | 43 | The selection of the `load-watcher` mode is based on the existence of a `watcherAddress` parameter. If it is set, then the `load-watcher` is in the 'as a service' mode, otherwise it is in the 'as a library' mode. 44 | 45 | In addition to the above configuration parameters, the Trimaran plugin may have its own specific parameters. 46 | 47 | Following is an example scheduler configuration. 48 | 49 | ```yaml 50 | apiVersion: kubescheduler.config.k8s.io/v1beta1 51 | kind: KubeSchedulerConfiguration 52 | leaderElection: 53 | leaderElect: false 54 | profiles: 55 | - schedulerName: trimaran 56 | plugins: 57 | score: 58 | enabled: 59 | - name: LoadVariationRiskBalancing 60 | pluginConfig: 61 | - name: LoadVariationRiskBalancing 62 | args: 63 | metricProvider: 64 | type: Prometheus 65 | address: http://prometheus-k8s.monitoring.svc.cluster.local:9090 66 | safeVarianceMargin: 1 67 | safeVarianceSensitivity: 2 68 | ``` 69 | 70 | ## A note on multiple plugins 71 | 72 | The Trimaran plugins have different, potentially conflicting, objectives. Thus, it is recommended not to enable them concurrently. As such, they are designed to each have its own load-watcher. 73 | -------------------------------------------------------------------------------- /pkg/trimaran/docs/load-watcher-library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/pkg/trimaran/docs/load-watcher-library.png -------------------------------------------------------------------------------- /pkg/trimaran/docs/load-watcher-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openai/scheduler-plugins/c056c296f862af4459c8e0067eccfba383d6e104/pkg/trimaran/docs/load-watcher-service.png -------------------------------------------------------------------------------- /pkg/trimaran/handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package Trimaran provides common code for plugins developed for real load aware scheduling like TargetLoadPacking etc. 19 | */ 20 | 21 | package trimaran 22 | 23 | import ( 24 | "sort" 25 | "sync" 26 | "time" 27 | 28 | v1 "k8s.io/api/core/v1" 29 | clientcache "k8s.io/client-go/tools/cache" 30 | "k8s.io/klog/v2" 31 | ) 32 | 33 | const ( 34 | // This is the maximum staleness of metrics possible by load watcher 35 | cacheCleanupIntervalMinutes = 5 36 | // Time interval in seconds for each metrics agent ingestion. 37 | metricsAgentReportingIntervalSeconds = 60 38 | ) 39 | 40 | var _ clientcache.ResourceEventHandler = &PodAssignEventHandler{} 41 | 42 | // This event handler watches assigned Pod and caches them locally 43 | type PodAssignEventHandler struct { 44 | // Maintains the node-name to podInfo mapping for pods successfully bound to nodes 45 | ScheduledPodsCache map[string][]podInfo 46 | sync.RWMutex 47 | } 48 | 49 | // Stores Timestamp and Pod spec info object 50 | type podInfo struct { 51 | // This timestamp is initialised when adding it to ScheduledPodsCache after successful binding 52 | Timestamp time.Time 53 | Pod *v1.Pod 54 | } 55 | 56 | // Returns a new instance of PodAssignEventHandler, after starting a background go routine for cache cleanup 57 | func New() *PodAssignEventHandler { 58 | p := PodAssignEventHandler{ScheduledPodsCache: make(map[string][]podInfo)} 59 | go func() { 60 | cacheCleanerTicker := time.NewTicker(time.Minute * cacheCleanupIntervalMinutes) 61 | for range cacheCleanerTicker.C { 62 | p.cleanupCache() 63 | } 64 | }() 65 | return &p 66 | } 67 | 68 | func (p *PodAssignEventHandler) OnAdd(obj interface{}) { 69 | pod := obj.(*v1.Pod) 70 | p.updateCache(pod) 71 | } 72 | 73 | func (p *PodAssignEventHandler) OnUpdate(oldObj, newObj interface{}) { 74 | oldPod := oldObj.(*v1.Pod) 75 | newPod := newObj.(*v1.Pod) 76 | 77 | if oldPod.Spec.NodeName != newPod.Spec.NodeName { 78 | p.updateCache(newPod) 79 | } 80 | } 81 | 82 | func (p *PodAssignEventHandler) OnDelete(obj interface{}) { 83 | pod := obj.(*v1.Pod) 84 | nodeName := pod.Spec.NodeName 85 | p.Lock() 86 | defer p.Unlock() 87 | if _, ok := p.ScheduledPodsCache[nodeName]; !ok { 88 | return 89 | } 90 | for i, v := range p.ScheduledPodsCache[nodeName] { 91 | n := len(p.ScheduledPodsCache[nodeName]) 92 | if pod.ObjectMeta.UID == v.Pod.ObjectMeta.UID { 93 | klog.V(10).Infof("deleting pod %#v", v.Pod) 94 | copy(p.ScheduledPodsCache[nodeName][i:], p.ScheduledPodsCache[nodeName][i+1:]) 95 | p.ScheduledPodsCache[nodeName][n-1] = podInfo{} 96 | p.ScheduledPodsCache[nodeName] = p.ScheduledPodsCache[nodeName][:n-1] 97 | break 98 | } 99 | } 100 | 101 | } 102 | 103 | func (p *PodAssignEventHandler) updateCache(pod *v1.Pod) { 104 | if pod.Spec.NodeName == "" { 105 | return 106 | } 107 | p.Lock() 108 | p.ScheduledPodsCache[pod.Spec.NodeName] = append(p.ScheduledPodsCache[pod.Spec.NodeName], 109 | podInfo{Timestamp: time.Now(), Pod: pod}) 110 | p.Unlock() 111 | } 112 | 113 | // Deletes podInfo entries that are older than metricsAgentReportingIntervalSeconds. Also deletes node entry if empty 114 | func (p *PodAssignEventHandler) cleanupCache() { 115 | p.Lock() 116 | defer p.Unlock() 117 | for nodeName := range p.ScheduledPodsCache { 118 | cache := p.ScheduledPodsCache[nodeName] 119 | curTime := time.Now() 120 | idx := sort.Search(len(cache), func(i int) bool { 121 | return cache[i].Timestamp.Add(metricsAgentReportingIntervalSeconds * time.Second).After(curTime) 122 | }) 123 | if idx == len(cache) { 124 | continue 125 | } 126 | n := copy(cache, cache[idx:]) 127 | for j := n; j < len(cache); j++ { 128 | cache[j] = podInfo{} 129 | } 130 | cache = cache[:n] 131 | 132 | if len(cache) == 0 { 133 | delete(p.ScheduledPodsCache, nodeName) 134 | } else { 135 | p.ScheduledPodsCache[nodeName] = cache 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /pkg/trimaran/handler_test.go: -------------------------------------------------------------------------------- 1 | package trimaran 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | 9 | st "k8s.io/kubernetes/pkg/scheduler/testing" 10 | ) 11 | 12 | func TestHandlerCacheCleanup(t *testing.T) { 13 | testNode := "node-1" 14 | pod1 := st.MakePod().Name("Pod-1").Obj() 15 | pod2 := st.MakePod().Name("Pod-2").Obj() 16 | pod3 := st.MakePod().Name("Pod-3").Obj() 17 | pod4 := st.MakePod().Name("Pod-4").Obj() 18 | 19 | tests := []struct { 20 | name string 21 | podInfoList []podInfo 22 | podToUpdate string 23 | expectedCacheSize int 24 | expectedCachePods []string 25 | }{ 26 | { 27 | name: "OnUpdate doesn't add unassigned pods", 28 | podInfoList: []podInfo{ 29 | {Pod: pod1}, 30 | {Pod: pod2}, 31 | {Pod: pod3}}, 32 | podToUpdate: "Pod-4", 33 | expectedCacheSize: 1, 34 | expectedCachePods: []string{"Pod-4"}, 35 | }, 36 | { 37 | name: "cleanupCache doesn't delete newly added pods", 38 | podInfoList: []podInfo{ 39 | {Pod: pod1}, 40 | {Pod: pod2}, 41 | {Pod: pod3}, 42 | {Timestamp: time.Now(), Pod: pod4}}, 43 | podToUpdate: "Pod-5", 44 | expectedCacheSize: 2, 45 | expectedCachePods: []string{"Pod-4", "Pod-5"}, 46 | }, 47 | { 48 | name: "cleanupCache deletes old pods", 49 | podInfoList: []podInfo{ 50 | {Timestamp: time.Now().Add(-5 * time.Minute), Pod: pod1}, 51 | {Timestamp: time.Now().Add(-10 * time.Second), Pod: pod2}, 52 | {Timestamp: time.Now().Add(-5 * time.Second), Pod: pod3}, 53 | }, 54 | expectedCacheSize: 2, 55 | expectedCachePods: []string{pod2.Name, pod3.Name}, 56 | }, 57 | } 58 | 59 | for _, tt := range tests { 60 | t.Run(tt.name, func(t *testing.T) { 61 | p := New() 62 | for _, v := range tt.podInfoList { 63 | p.ScheduledPodsCache[testNode] = append(p.ScheduledPodsCache[testNode], v) 64 | } 65 | if tt.podToUpdate != "" { 66 | pod := st.MakePod().Name(tt.podToUpdate).Obj() 67 | pod.Spec.NodeName = testNode 68 | oldPod := st.MakePod().Name(tt.podToUpdate).Obj() 69 | p.OnUpdate(oldPod, pod) 70 | } 71 | p.cleanupCache() 72 | assert.NotNil(t, p.ScheduledPodsCache[testNode]) 73 | assert.Equal(t, tt.expectedCacheSize, len(p.ScheduledPodsCache[testNode])) 74 | for i, v := range p.ScheduledPodsCache[testNode] { 75 | assert.Equal(t, tt.expectedCachePods[i], v.Pod.Name) 76 | } 77 | }) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /pkg/trimaran/loadvariationriskbalancing/README.md: -------------------------------------------------------------------------------- 1 | # LoadVariationRiskBalancing Plugin 2 | 3 | The `LoadVariationRiskBalancing` plugin is one of the `Trimaran` scheduler plugins and is described in detail in [Trimaran: Real Load Aware Scheduling](https://github.com/kubernetes-sigs/scheduler-plugins/blob/master/kep/61-Trimaran-real-load-aware-scheduling). The `Trimaran` plugins employ the `load-watcher` in order to collect measurements from the nodes as described [here](../README.md). 4 | 5 | The (normalized) risk of a node is defined as a combined measure of the average and standard deviation of the node utilization. It is given by 6 | 7 | ```latex 8 | risk = [ average + margin * stDev^{1/sensitivity} ] / 2 9 | ``` 10 | 11 | where *average*​ and *stDev*​ are the fractional (between 0 and 1) measured average utilization and standard deviation of the utilization over a period of time, respectively. The two parameters: *margin*​ and *sensitivity*​, impact the amount of risk due to load variation. In order to magnify the impact of low variations, the *stDev*​ quantity is raised to a fractional power with the *sensitivity*​ parameter being the root power. And, the *margin*​ parameter scales the variation quantity. The recommended values for the *margin*​ and *sensitivity*​ parameters are 1 and 2, respectively. Each of the two added terms is bounded between 0 and 1. Then, the divisor 2 is used to normalize risk between 0 and 1. 12 | 13 | (Since the additional load due to the pod, that is the subject of scheduling, is not known in advance, we assume that its average and standard deviation load are the requested amount and zero, respectively.) 14 | 15 | Risk is calculated independently for the CPU and memory resources on the node. Let *worstRisk* be the maximum of the two calculated risks. The *score* of the node, assuming that *minScore* is 0, is then computed as 16 | 17 | ```latex 18 | score = maxScore * (1 - worstRisk) 19 | ``` 20 | 21 | Thus, the `LoadVariationRiskBalancing` plugin has the following configuration parameters: 22 | 23 | - `safeVarianceMargin` : Multiplier (non-negative floating point) of standard deviation. (Default 1) 24 | - `safeVarianceSensitivity` : Root power (non-negative floating point) of standard deviation. (Default 1) 25 | 26 | In addition, we have the `watcherAddress` or `metricProvider`configuration parameters, depending on whether the `load-watcher` is in service or library mode, respectively. 27 | 28 | Following is an example scheduler configuration with the `LoadVariationRiskBalancing` plugin enabled, and using the `load-watcher` in library mode, collecting measurements from the Prometheus server. 29 | 30 | ```yaml 31 | apiVersion: kubescheduler.config.k8s.io/v1beta1 32 | kind: KubeSchedulerConfiguration 33 | leaderElection: 34 | leaderElect: false 35 | profiles: 36 | - schedulerName: trimaran 37 | plugins: 38 | score: 39 | enabled: 40 | - name: LoadVariationRiskBalancing 41 | pluginConfig: 42 | - name: LoadVariationRiskBalancing 43 | args: 44 | safeVarianceMargin: 1 45 | safeVarianceSensitivity: 2 46 | metricProvider: 47 | type: Prometheus 48 | address: http://prometheus-k8s.monitoring.svc.cluster.local:9090 49 | ``` 50 | -------------------------------------------------------------------------------- /pkg/trimaran/loadvariationriskbalancing/collector_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package loadvariationriskbalancing 18 | 19 | import ( 20 | "encoding/json" 21 | "net/http" 22 | "net/http/httptest" 23 | "testing" 24 | 25 | "github.com/paypal/load-watcher/pkg/watcher" 26 | "github.com/stretchr/testify/assert" 27 | 28 | pluginConfig "sigs.k8s.io/scheduler-plugins/pkg/apis/config" 29 | "sigs.k8s.io/scheduler-plugins/pkg/apis/config/v1beta1" 30 | ) 31 | 32 | var ( 33 | args = pluginConfig.LoadVariationRiskBalancingArgs{ 34 | WatcherAddress: "http://deadbeef:2020", 35 | SafeVarianceMargin: 1, 36 | } 37 | 38 | watcherResponse = watcher.WatcherMetrics{ 39 | Window: watcher.Window{}, 40 | Data: watcher.Data{ 41 | NodeMetricsMap: map[string]watcher.NodeMetrics{ 42 | "node-1": { 43 | Metrics: []watcher.Metric{ 44 | { 45 | Type: watcher.CPU, 46 | Operator: watcher.Average, 47 | Value: 80, 48 | }, 49 | { 50 | Type: watcher.CPU, 51 | Operator: watcher.Std, 52 | Value: 16, 53 | }, 54 | { 55 | Type: watcher.Memory, 56 | Operator: watcher.Average, 57 | Value: 25, 58 | }, 59 | { 60 | Type: watcher.Memory, 61 | Operator: watcher.Std, 62 | Value: 6.25, 63 | }, 64 | }, 65 | }, 66 | }, 67 | }, 68 | } 69 | ) 70 | 71 | func TestNewCollector(t *testing.T) { 72 | col, err := newCollector(&args) 73 | assert.NotNil(t, col) 74 | assert.Nil(t, err) 75 | } 76 | 77 | func TestGetAllMetrics(t *testing.T) { 78 | server := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 79 | bytes, err := json.Marshal(watcherResponse) 80 | assert.Nil(t, err) 81 | resp.Write(bytes) 82 | })) 83 | defer server.Close() 84 | 85 | loadVariationRiskBalancingArgs := pluginConfig.LoadVariationRiskBalancingArgs{ 86 | WatcherAddress: server.URL, 87 | SafeVarianceMargin: v1beta1.DefaultSafeVarianceMargin, 88 | } 89 | collector, err := newCollector(&loadVariationRiskBalancingArgs) 90 | assert.NotNil(t, collector) 91 | assert.Nil(t, err) 92 | 93 | metrics := collector.getAllMetrics() 94 | metricsMap := metrics.Data.NodeMetricsMap 95 | expectedMap := watcherResponse.Data.NodeMetricsMap 96 | assert.EqualValues(t, expectedMap, metricsMap) 97 | } 98 | 99 | func TestUpdateMetrics(t *testing.T) { 100 | server := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 101 | bytes, err := json.Marshal(watcherResponse) 102 | assert.Nil(t, err) 103 | resp.Write(bytes) 104 | })) 105 | defer server.Close() 106 | 107 | loadVariationRiskBalancingArgs := pluginConfig.LoadVariationRiskBalancingArgs{ 108 | WatcherAddress: server.URL, 109 | SafeVarianceMargin: v1beta1.DefaultSafeVarianceMargin, 110 | } 111 | collector, err := newCollector(&loadVariationRiskBalancingArgs) 112 | assert.NotNil(t, collector) 113 | assert.Nil(t, err) 114 | 115 | err = collector.updateMetrics() 116 | assert.Nil(t, err) 117 | } 118 | 119 | func TestGetNodeMetrics(t *testing.T) { 120 | server := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 121 | bytes, err := json.Marshal(watcherResponse) 122 | assert.Nil(t, err) 123 | resp.Write(bytes) 124 | })) 125 | defer server.Close() 126 | 127 | loadVariationRiskBalancingArgs := pluginConfig.LoadVariationRiskBalancingArgs{ 128 | WatcherAddress: server.URL, 129 | SafeVarianceMargin: v1beta1.DefaultSafeVarianceMargin, 130 | } 131 | collector, err := newCollector(&loadVariationRiskBalancingArgs) 132 | assert.NotNil(t, collector) 133 | assert.Nil(t, err) 134 | nodeName := "node-1" 135 | metrics := collector.getNodeMetrics(nodeName) 136 | expectedMetrics := watcherResponse.Data.NodeMetricsMap[nodeName].Metrics 137 | assert.EqualValues(t, expectedMetrics, metrics) 138 | } 139 | -------------------------------------------------------------------------------- /pkg/util/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import "fmt" 20 | 21 | const ( 22 | // PodGroupLabel is the default label of coscheduling 23 | PodGroupLabel = "pod-group.scheduling.sigs.k8s.io" 24 | ) 25 | 26 | var ( 27 | // ErrorNotMatched means pod does not match coscheduling 28 | ErrorNotMatched = fmt.Errorf("not match coscheduling") 29 | // ErrorWaiting means pod number does not match the min pods required 30 | ErrorWaiting = fmt.Errorf("waiting") 31 | // ErrorResourceNotEnough means cluster resource is not enough, mainly used in Pre-Filter 32 | ErrorResourceNotEnough = fmt.Errorf("resource not enough") 33 | ) 34 | -------------------------------------------------------------------------------- /pkg/util/podgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "encoding/json" 21 | "fmt" 22 | "time" 23 | 24 | v1 "k8s.io/api/core/v1" 25 | "k8s.io/apimachinery/pkg/util/strategicpatch" 26 | 27 | "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 28 | ) 29 | 30 | // DefaultWaitTime is 60s if ScheduleTimeoutSeconds is not specified. 31 | const DefaultWaitTime = 60 * time.Second 32 | 33 | // CreateMergePatch return patch generated from original and new interfaces 34 | func CreateMergePatch(original, new interface{}) ([]byte, error) { 35 | pvByte, err := json.Marshal(original) 36 | if err != nil { 37 | return nil, err 38 | } 39 | cloneByte, err := json.Marshal(new) 40 | if err != nil { 41 | return nil, err 42 | } 43 | patch, err := strategicpatch.CreateTwoWayMergePatch(pvByte, cloneByte, original) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return patch, nil 48 | } 49 | 50 | // GetPodGroupLabel get pod group from pod annotations 51 | func GetPodGroupLabel(pod *v1.Pod) string { 52 | return pod.Labels[PodGroupLabel] 53 | } 54 | 55 | // GetPodGroupFullName get namespaced group name from pod annotations 56 | func GetPodGroupFullName(pod *v1.Pod) string { 57 | pgName := GetPodGroupLabel(pod) 58 | if len(pgName) == 0 { 59 | return "" 60 | } 61 | return fmt.Sprintf("%v/%v", pod.Namespace, pgName) 62 | } 63 | 64 | // GetWaitTimeDuration returns a wait timeout based on the following precedences: 65 | // 1. spec.scheduleTimeoutSeconds of the given pg, if specified 66 | // 2. given scheduleTimeout, if not nil 67 | // 3. fall back to DefaultWaitTime 68 | func GetWaitTimeDuration(pg *v1alpha1.PodGroup, scheduleTimeout *time.Duration) time.Duration { 69 | if pg != nil && pg.Spec.ScheduleTimeoutSeconds != nil { 70 | return time.Duration(*pg.Spec.ScheduleTimeoutSeconds) * time.Second 71 | } 72 | if scheduleTimeout != nil && *scheduleTimeout != 0 { 73 | return *scheduleTimeout 74 | } 75 | return DefaultWaitTime 76 | } 77 | -------------------------------------------------------------------------------- /pkg/util/podgroup_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "testing" 21 | 22 | "k8s.io/kubernetes/pkg/apis/core" 23 | ) 24 | 25 | type test struct { 26 | old interface{} 27 | new interface{} 28 | expectedError bool 29 | } 30 | 31 | func TestCreateMergePatch(t *testing.T) { 32 | tests := []struct { 33 | old interface{} 34 | new interface{} 35 | expected string 36 | }{ 37 | { 38 | old: &core.Pod{ 39 | Spec: core.PodSpec{ 40 | Hostname: "test", 41 | }, 42 | }, 43 | new: &core.Pod{ 44 | Status: core.PodStatus{ 45 | Reason: "test", 46 | }, 47 | }, 48 | expected: `{"Spec":{"Hostname":""},"Status":{"Reason":"test"}}`, 49 | }, 50 | 51 | { 52 | old: &core.Pod{ 53 | Spec: core.PodSpec{ 54 | Hostname: "test", 55 | }, 56 | Status: core.PodStatus{ 57 | Reason: "test1", 58 | }, 59 | }, 60 | new: &core.Pod{ 61 | Status: core.PodStatus{ 62 | Reason: "test", 63 | }, 64 | }, 65 | expected: `{"Spec":{"Hostname":""},"Status":{"Reason":"test"}}`, 66 | }, 67 | } 68 | 69 | for _, tcase := range tests { 70 | patch, err := CreateMergePatch(tcase.old, tcase.new) 71 | if err != nil { 72 | t.Error(err) 73 | } 74 | if string(patch) != tcase.expected { 75 | t.Errorf("expected %v get %v", tcase.expected, string(patch)) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /test/integration/base.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package integration 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | 23 | v1 "k8s.io/api/core/v1" 24 | "k8s.io/apimachinery/pkg/api/resource" 25 | st "k8s.io/kubernetes/pkg/scheduler/testing" 26 | "sigs.k8s.io/scheduler-plugins/pkg/apis/scheduling/v1alpha1" 27 | 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | clientset "k8s.io/client-go/kubernetes" 30 | "k8s.io/klog/v2" 31 | ) 32 | 33 | var lowPriority, midPriority, highPriority = int32(0), int32(100), int32(1000) 34 | 35 | // podScheduled returns true if a node is assigned to the given pod. 36 | func podScheduled(c clientset.Interface, podNamespace, podName string) bool { 37 | pod, err := c.CoreV1().Pods(podNamespace).Get(context.TODO(), podName, metav1.GetOptions{}) 38 | if err != nil { 39 | // This could be a connection error so we want to retry. 40 | klog.Errorf("klog error %v", err) 41 | return false 42 | } 43 | if pod.Spec.NodeName == "" { 44 | return false 45 | } 46 | return true 47 | } 48 | 49 | type resourceWrapper struct{ v1.ResourceList } 50 | 51 | func MakeResourceList() *resourceWrapper { 52 | return &resourceWrapper{v1.ResourceList{}} 53 | } 54 | 55 | func (r *resourceWrapper) CPU(val int64) *resourceWrapper { 56 | r.ResourceList[v1.ResourceCPU] = *resource.NewQuantity(val, resource.DecimalSI) 57 | return r 58 | } 59 | 60 | func (r *resourceWrapper) Mem(val int64) *resourceWrapper { 61 | r.ResourceList[v1.ResourceMemory] = *resource.NewQuantity(val, resource.DecimalSI) 62 | return r 63 | } 64 | 65 | func (r *resourceWrapper) GPU(val int64) *resourceWrapper { 66 | r.ResourceList["nvidia.com/gpu"] = *resource.NewQuantity(val, resource.DecimalSI) 67 | return r 68 | } 69 | 70 | func (r *resourceWrapper) Obj() v1.ResourceList { 71 | return r.ResourceList 72 | } 73 | 74 | type podWrapper struct{ *v1.Pod } 75 | 76 | func MakePod(namespace, name string) *podWrapper { 77 | pod := st.MakePod().Namespace(namespace).Name(name).Obj() 78 | 79 | return &podWrapper{pod} 80 | } 81 | 82 | func (p *podWrapper) Phase(phase v1.PodPhase) *podWrapper { 83 | p.Pod.Status.Phase = phase 84 | return p 85 | } 86 | 87 | func (p *podWrapper) Container(request v1.ResourceList) *podWrapper { 88 | p.Pod.Spec.Containers = append(p.Pod.Spec.Containers, v1.Container{ 89 | Name: fmt.Sprintf("con%d", len(p.Pod.Spec.Containers)), 90 | Image: "image", 91 | Resources: v1.ResourceRequirements{ 92 | Requests: request, 93 | }, 94 | }) 95 | return p 96 | } 97 | 98 | func (p *podWrapper) InitContainerRequest(request v1.ResourceList) *podWrapper { 99 | p.Pod.Spec.InitContainers = append(p.Pod.Spec.InitContainers, v1.Container{ 100 | Name: fmt.Sprintf("con%d", len(p.Pod.Spec.Containers)), 101 | Image: "image", 102 | Resources: v1.ResourceRequirements{ 103 | Requests: request, 104 | }, 105 | }) 106 | return p 107 | } 108 | 109 | func (p *podWrapper) Node(name string) *podWrapper { 110 | p.Pod.Spec.NodeName = name 111 | return p 112 | } 113 | 114 | func (p *podWrapper) Obj() *v1.Pod { 115 | return p.Pod 116 | } 117 | 118 | type eqWrapper struct{ *v1alpha1.ElasticQuota } 119 | 120 | func MakeEQ(namespace, name string) *eqWrapper { 121 | eq := &v1alpha1.ElasticQuota{ 122 | TypeMeta: metav1.TypeMeta{Kind: "ElasticQuota", APIVersion: "scheduling.sigs.k8s.io/v1alpha1"}, 123 | ObjectMeta: metav1.ObjectMeta{ 124 | Name: name, 125 | Namespace: namespace, 126 | }, 127 | } 128 | return &eqWrapper{eq} 129 | } 130 | 131 | func (e *eqWrapper) Min(min v1.ResourceList) *eqWrapper { 132 | e.ElasticQuota.Spec.Min = min 133 | return e 134 | } 135 | 136 | func (e *eqWrapper) Max(max v1.ResourceList) *eqWrapper { 137 | e.ElasticQuota.Spec.Max = max 138 | return e 139 | } 140 | 141 | func (e *eqWrapper) Used(used v1.ResourceList) *eqWrapper { 142 | e.ElasticQuota.Status.Used = used 143 | return e 144 | } 145 | 146 | func (e *eqWrapper) Obj() *v1alpha1.ElasticQuota { 147 | return e.ElasticQuota 148 | } 149 | -------------------------------------------------------------------------------- /test/integration/main_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package integration 18 | 19 | import ( 20 | "testing" 21 | 22 | "k8s.io/kubernetes/test/integration/framework" 23 | ) 24 | 25 | func TestMain(m *testing.M) { 26 | framework.EtcdMain(m.Run) 27 | } 28 | -------------------------------------------------------------------------------- /test/util/extension.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 21 | "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 22 | apiextensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver" 23 | apiextensionsoptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options" 24 | "k8s.io/apimachinery/pkg/runtime" 25 | "k8s.io/apimachinery/pkg/runtime/schema" 26 | "k8s.io/apiserver/pkg/admission" 27 | "k8s.io/apiserver/pkg/features" 28 | genericapiserver "k8s.io/apiserver/pkg/server" 29 | genericoptions "k8s.io/apiserver/pkg/server/options" 30 | "k8s.io/apiserver/pkg/util/feature" 31 | utilfeature "k8s.io/apiserver/pkg/util/feature" 32 | "k8s.io/apiserver/pkg/util/webhook" 33 | kubeexternalinformers "k8s.io/client-go/informers" 34 | "k8s.io/kubernetes/cmd/kube-apiserver/app/options" 35 | ) 36 | 37 | func createAPIExtensionsConfig( 38 | kubeAPIServerConfig genericapiserver.Config, 39 | externalInformers kubeexternalinformers.SharedInformerFactory, 40 | pluginInitializers []admission.PluginInitializer, 41 | commandOptions *options.ServerRunOptions, 42 | masterCount int, 43 | serviceResolver webhook.ServiceResolver, 44 | authResolverWrapper webhook.AuthenticationInfoResolverWrapper, 45 | ) (*apiextensionsapiserver.Config, error) { 46 | // make a shallow copy to let us twiddle a few things 47 | // most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the apiextensions 48 | genericConfig := kubeAPIServerConfig 49 | genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{} 50 | genericConfig.RESTOptionsGetter = nil 51 | 52 | // override genericConfig.AdmissionControl with apiextensions' scheme, 53 | // because apiextentions apiserver should use its own scheme to convert resources. 54 | err := commandOptions.Admission.ApplyTo( 55 | &genericConfig, 56 | externalInformers, 57 | genericConfig.LoopbackClientConfig, 58 | feature.DefaultFeatureGate, 59 | pluginInitializers...) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | // copy the etcd options so we don't mutate originals. 65 | etcdOptions := *commandOptions.Etcd 66 | etcdOptions.StorageConfig.Paging = utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking) 67 | etcdOptions.StorageConfig.Codec = apiextensionsapiserver.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion, v1.SchemeGroupVersion) 68 | etcdOptions.StorageConfig.EncodeVersioner = runtime.NewMultiGroupVersioner(v1beta1.SchemeGroupVersion, schema.GroupKind{Group: v1beta1.GroupName}) 69 | genericConfig.RESTOptionsGetter = &genericoptions.SimpleRestOptionsFactory{Options: etcdOptions} 70 | 71 | // override MergedResourceConfig with apiextensions defaults and registry 72 | if err := commandOptions.APIEnablement.ApplyTo( 73 | &genericConfig, 74 | apiextensionsapiserver.DefaultAPIResourceConfigSource(), 75 | apiextensionsapiserver.Scheme); err != nil { 76 | return nil, err 77 | } 78 | 79 | apiextensionsConfig := &apiextensionsapiserver.Config{ 80 | GenericConfig: &genericapiserver.RecommendedConfig{ 81 | Config: genericConfig, 82 | SharedInformerFactory: externalInformers, 83 | }, 84 | ExtraConfig: apiextensionsapiserver.ExtraConfig{ 85 | CRDRESTOptionsGetter: apiextensionsoptions.NewCRDRESTOptionsGetter(etcdOptions), 86 | MasterCount: masterCount, 87 | AuthResolverWrapper: authResolverWrapper, 88 | ServiceResolver: serviceResolver, 89 | }, 90 | } 91 | 92 | // we need to clear the poststarthooks so we don't add them multiple times to all the servers (that fails) 93 | apiextensionsConfig.GenericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{} 94 | 95 | return apiextensionsConfig, nil 96 | } 97 | 98 | func createAPIExtensionsServer(apiextensionsConfig *apiextensionsapiserver.Config, delegateAPIServer genericapiserver.DelegationTarget) (*apiextensionsapiserver.CustomResourceDefinitions, error) { 99 | return apiextensionsConfig.Complete().New(delegateAPIServer) 100 | } 101 | -------------------------------------------------------------------------------- /test/util/fixtures.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import "os" 20 | 21 | func IntegrationEtcdServers() []string { 22 | if etcdURL, ok := os.LookupEnv("KUBE_INTEGRATION_ETCD_URL"); ok { 23 | return []string{etcdURL} 24 | } 25 | return []string{"http://127.0.0.1:2379"} 26 | } 27 | -------------------------------------------------------------------------------- /test/util/framework.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "k8s.io/kubernetes/pkg/scheduler/apis/config" 21 | "k8s.io/kubernetes/pkg/scheduler/framework" 22 | "k8s.io/kubernetes/pkg/scheduler/framework/runtime" 23 | st "k8s.io/kubernetes/pkg/scheduler/testing" 24 | ) 25 | 26 | // NewFramework is a variant version of st.NewFramework - with extra PluginConfig slice as input. 27 | func NewFramework(fns []st.RegisterPluginFunc, cfgs []config.PluginConfig, profileName string, opts ...runtime.Option) (framework.Framework, error) { 28 | registry := runtime.Registry{} 29 | plugins := &config.Plugins{} 30 | for _, f := range fns { 31 | f(®istry, plugins) 32 | } 33 | profile := &config.KubeSchedulerProfile{ 34 | SchedulerName: profileName, 35 | Plugins: plugins, 36 | PluginConfig: cfgs, 37 | } 38 | return runtime.NewFramework(registry, profile, opts...) 39 | } 40 | -------------------------------------------------------------------------------- /test/util/scheduler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "testing" 21 | 22 | "k8s.io/client-go/informers" 23 | "k8s.io/client-go/tools/events" 24 | "k8s.io/kubernetes/pkg/scheduler" 25 | "k8s.io/kubernetes/pkg/scheduler/profile" 26 | testutils "k8s.io/kubernetes/test/integration/util" 27 | ) 28 | 29 | // InitTestSchedulerWithOptions initializes a test environment and creates a scheduler with default 30 | // configuration and other options. 31 | // TODO(Huang-Wei): refactor the same function in the upstream, and remove here. 32 | func InitTestSchedulerWithOptions( 33 | t *testing.T, 34 | testCtx *testutils.TestContext, 35 | startScheduler bool, 36 | opts ...scheduler.Option, 37 | ) *testutils.TestContext { 38 | testCtx.InformerFactory = informers.NewSharedInformerFactory(testCtx.ClientSet, 0) 39 | 40 | var err error 41 | eventBroadcaster := events.NewBroadcaster(&events.EventSinkImpl{ 42 | Interface: testCtx.ClientSet.EventsV1(), 43 | }) 44 | 45 | testCtx.Scheduler, err = scheduler.New( 46 | testCtx.ClientSet, 47 | testCtx.InformerFactory, 48 | profile.NewRecorderFactory(eventBroadcaster), 49 | testCtx.Ctx.Done(), 50 | opts..., 51 | ) 52 | 53 | if err != nil { 54 | t.Fatalf("Couldn't create scheduler: %v", err) 55 | } 56 | 57 | eventBroadcaster.StartRecordingToSink(testCtx.Ctx.Done()) 58 | 59 | testCtx.InformerFactory.Start(testCtx.Scheduler.StopEverything) 60 | testCtx.InformerFactory.WaitForCacheSync(testCtx.Scheduler.StopEverything) 61 | 62 | if startScheduler { 63 | go testCtx.Scheduler.Run(testCtx.Ctx) 64 | } 65 | 66 | return testCtx 67 | } 68 | --------------------------------------------------------------------------------