github.com/deemoprobe/k8s-first-commit@v0.0.0-20230430165612-a541f1982be3/pkg/registry/scheduler.go (about) 1 /* 2 Copyright 2014 Google Inc. All rights reserved. 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 package registry 17 18 import ( 19 "fmt" 20 "math/rand" 21 22 . "github.com/GoogleCloudPlatform/kubernetes/pkg/api" 23 ) 24 25 // Scheduler is an interface implemented by things that know how to schedule tasks onto machines. 26 type Scheduler interface { 27 Schedule(Task) (string, error) 28 } 29 30 // RandomScheduler choses machines uniformly at random. 31 type RandomScheduler struct { 32 machines []string 33 random rand.Rand 34 } 35 36 func MakeRandomScheduler(machines []string, random rand.Rand) Scheduler { 37 return &RandomScheduler{ 38 machines: machines, 39 random: random, 40 } 41 } 42 43 func (s *RandomScheduler) Schedule(task Task) (string, error) { 44 return s.machines[s.random.Int()%len(s.machines)], nil 45 } 46 47 // RoundRobinScheduler chooses machines in order. 48 type RoundRobinScheduler struct { 49 machines []string 50 currentIndex int 51 } 52 53 func MakeRoundRobinScheduler(machines []string) Scheduler { 54 return &RoundRobinScheduler{ 55 machines: machines, 56 currentIndex: 0, 57 } 58 } 59 60 func (s *RoundRobinScheduler) Schedule(task Task) (string, error) { 61 result := s.machines[s.currentIndex] 62 s.currentIndex = (s.currentIndex + 1) % len(s.machines) 63 return result, nil 64 } 65 66 type FirstFitScheduler struct { 67 machines []string 68 registry TaskRegistry 69 } 70 71 func MakeFirstFitScheduler(machines []string, registry TaskRegistry) Scheduler { 72 return &FirstFitScheduler{ 73 machines: machines, 74 registry: registry, 75 } 76 } 77 78 func (s *FirstFitScheduler) containsPort(task Task, port Port) bool { 79 for _, container := range task.DesiredState.Manifest.Containers { 80 for _, taskPort := range container.Ports { 81 if taskPort.HostPort == port.HostPort { 82 return true 83 } 84 } 85 } 86 return false 87 } 88 89 func (s *FirstFitScheduler) Schedule(task Task) (string, error) { 90 machineToTasks := map[string][]Task{} 91 tasks, err := s.registry.ListTasks(nil) 92 if err != nil { 93 return "", err 94 } 95 for _, scheduledTask := range tasks { 96 host := scheduledTask.CurrentState.Host 97 machineToTasks[host] = append(machineToTasks[host], scheduledTask) 98 } 99 for _, machine := range s.machines { 100 taskFits := true 101 for _, scheduledTask := range machineToTasks[machine] { 102 for _, container := range task.DesiredState.Manifest.Containers { 103 for _, port := range container.Ports { 104 if s.containsPort(scheduledTask, port) { 105 taskFits = false 106 } 107 } 108 } 109 } 110 if taskFits { 111 return machine, nil 112 } 113 } 114 return "", fmt.Errorf("Failed to find fit for %#v", task) 115 }