<p>How does Kubernetes' scheduler work? What I mean is that Kubernetes' scheduler appears to be very simple?</p>

<p>My initial thought is that this scheduler is just a simple admission control system, not a real scheduler. Is it that correct?</p>

<p>I found a short description, but it is not terribly informative:</p>

<blockquote>
  <p>The kubernetes scheduler is a policy-rich, topology-aware,
  workload-specific function that significantly impacts availability,
  performance, and capacity. The scheduler needs to take into account
  individual and collective resource requirements, quality of service
  requirements, hardware/software/policy constraints, affinity and
  anti-affinity specifications, data locality, inter-workload
  interference, deadlines, and so on. Workload-specific requirements
  will be exposed through the API as necessary.</p>
</blockquote>

<p>The paragraph you quoted describes where we hope to be in the future (where the future is defined in units of months, not years). We're not there yet, but the scheduler does have a number of useful features already, enough for a simple deployment. In the rest of this reply, I'll explain how the scheduler works today.</p>

<p>The scheduler is not just an admission controller; for each pod that is created, it finds the "best" machine for that pod, and if no machine is suitable, the pod remains unscheduled until a machine becomes suitable.</p>

<p>The scheduler is configurable. It has two types of policies, <strong>FitPredicate</strong> (see <code>master/pkg/scheduler/predicates.go</code>) and <strong>PriorityFunction</strong> (see <code>master/pkg/scheduler/priorities.go</code>). I'll describe them.</p>

<p><strong>Fit predicates</strong> are required rules, for example the labels on the node must be compatible with the label selector on the pod (this rule is implemented in <code>PodSelectorMatches()</code> in <code>predicates.go</code>), and the sum of the requested resources of the container(s) already running on the machine plus the requested resources of the new container(s) you are considering scheduling onto the machine must not be greater than the capacity of the machine (this rule is implemented in <code>PodFitsResources()</code> in <code>predicates.go</code>; note that "requested resources" is defined as <em>pod.Spec.Containers[n].Resources.Limits</em>, and if you request zero resources then you always fit). If any of the required rules are not satisfied for a particular (new pod, machine) pair, then the new pod is not scheduled on that machine. If after checking all machines the scheduler decides that the new pod cannot be scheduled onto any machine, then the pod remains in Pending state until it can be satisfied by one of the machines.</p>

<p>After checking all of the machines with respect to the fit predicates, the scheduler may find that multiple machines "fit" the pod. But of course, the pod can only be scheduled onto one machine. That's where priority functions come in. Basically, the scheduler ranks the machines that meet all of the fit predicates, and then chooses the best one. For example, it prefers the machine whose already-running pods consume the least resources (this is implemented in <code>LeastRequestedPriority()</code> in <code>priorities.go</code>). This policy spreads pods (and thus containers) out instead of packing lots onto one machine while leaving others empty. </p>

<p>When I said that the scheduler is configurable, I mean that you can decide at compile time which fit predicates and priority functions you want Kubernetes to apply. Currently, it applies all of the ones you see in <code>predicates.go</code> and <code>priorities.go</code>.</p>
