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  }