func (s *Scheduler) scheduleOne() { pod := s.config.NextPod() glog.V(3).Infof("Attempting to schedule: %+v", pod) start := time.Now() dest, err := s.config.Algorithm.Schedule(pod, s.config.NodeLister) if err != nil { glog.V(1).Infof("Failed to schedule: %+v", pod) s.config.Error(pod, err) s.config.Recorder.Eventf(pod, api.EventTypeWarning, "FailedScheduling", "%v", err) return } metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) // Optimistically assume that the binding will succeed and send it to apiserver // in the background. // The only risk in this approach is that if the binding fails because of some // reason, scheduler will be assuming that it succeeded while scheduling next // pods, until the assumption in the internal cache expire (expiration is // defined as "didn't read the binding via watch within a given timeout", // timeout is currently set to 30s). However, after this timeout, the situation // will self-repair. assumed := *pod assumed.Spec.NodeName = dest s.config.SchedulerCache.AssumePodIfBindSucceed(&assumed, func() bool { return true }) go func() { defer metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) b := &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name}, Target: api.ObjectReference{ Kind: "Node", Name: dest, }, } bindingStart := time.Now() err := s.config.Binder.Bind(b) if err != nil { glog.V(1).Infof("Failed to bind pod: %+v", err) s.config.Error(pod, err) s.config.Recorder.Eventf(pod, api.EventTypeNormal, "FailedScheduling", "Binding rejected: %v", err) return } metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) s.config.Recorder.Eventf(pod, api.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest) }() }
func (s *Scheduler) scheduleOne() { fmt.Println("---------- now in scheduleOne() ----------") pod := s.config.NextPod() if s.config.BindPodsRateLimiter != nil { s.config.BindPodsRateLimiter.Accept() } glog.V(3).Infof("Attempting to schedule: %+v", pod) start := time.Now() defer func() { metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) }() dest, err := s.config.Algorithm.Schedule(pod, s.config.MinionLister) metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) if err != nil { glog.V(1).Infof("Failed to schedule: %+v", pod) s.config.Recorder.Eventf(pod, "FailedScheduling", "%v", err) s.config.Error(pod, err) return } b := &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name}, Target: api.ObjectReference{ Kind: "Node", Name: dest, }, } // We want to add the pod to the model iff the bind succeeds, but we don't want to race // with any deletions, which happen asynchronously. s.config.Modeler.LockedAction(func() { bindingStart := time.Now() err := s.config.Binder.Bind(b) metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) if err != nil { glog.V(1).Infof("Failed to bind pod: %+v", err) s.config.Recorder.Eventf(pod, "FailedScheduling", "Binding rejected: %v", err) s.config.Error(pod, err) return } s.config.Recorder.Eventf(pod, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest) // tell the model to assume that this binding took effect. assumed := *pod assumed.Spec.NodeName = dest s.config.Modeler.AssumePod(&assumed) }) }
func (s *Scheduler) scheduleOne() { pod := s.config.NextPod() glog.V(3).Infof("Attempting to schedule: %+v", pod) start := time.Now() dest, err := s.config.Algorithm.Schedule(pod, s.config.NodeLister) if err != nil { glog.V(1).Infof("Failed to schedule: %+v", pod) s.config.Recorder.Eventf(pod, api.EventTypeWarning, "FailedScheduling", "%v", err) s.config.Error(pod, err) return } metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) b := &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name}, Target: api.ObjectReference{ Kind: "Node", Name: dest, }, } bindAction := func() bool { bindingStart := time.Now() err := s.config.Binder.Bind(b) if err != nil { glog.V(1).Infof("Failed to bind pod: %+v", err) s.config.Recorder.Eventf(pod, api.EventTypeNormal, "FailedScheduling", "Binding rejected: %v", err) s.config.Error(pod, err) return false } metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) s.config.Recorder.Eventf(pod, api.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest) return true } assumed := *pod assumed.Spec.NodeName = dest // We want to assume the pod if and only if the bind succeeds, // but we don't want to race with any deletions, which happen asynchronously. s.config.SchedulerCache.AssumePodIfBindSucceed(&assumed, bindAction) metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) }
func (s *Scheduler) scheduleOne() { pod := s.config.NextPod() glog.V(3).Infof("Attempting to schedule pod: %v/%v", pod.Namespace, pod.Name) start := time.Now() dest, err := s.config.Algorithm.Schedule(pod, s.config.NodeLister) if err != nil { glog.V(1).Infof("Failed to schedule pod: %v/%v", pod.Namespace, pod.Name) s.config.Error(pod, err) s.config.Recorder.Eventf(pod, v1.EventTypeWarning, "FailedScheduling", "%v", err) s.config.PodConditionUpdater.Update(pod, &v1.PodCondition{ Type: v1.PodScheduled, Status: v1.ConditionFalse, Reason: v1.PodReasonUnschedulable, }) return } metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) // Optimistically assume that the binding will succeed and send it to apiserver // in the background. // If the binding fails, scheduler will release resources allocated to assumed pod // immediately. assumed := *pod assumed.Spec.NodeName = dest if err := s.config.SchedulerCache.AssumePod(&assumed); err != nil { glog.Errorf("scheduler cache AssumePod failed: %v", err) // TODO: This means that a given pod is already in cache (which means it // is either assumed or already added). This is most probably result of a // BUG in retrying logic. As a temporary workaround (which doesn't fully // fix the problem, but should reduce its impact), we simply return here, // as binding doesn't make sense anyway. // This should be fixed properly though. return } go func() { defer metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) b := &v1.Binding{ ObjectMeta: v1.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name}, Target: v1.ObjectReference{ Kind: "Node", Name: dest, }, } bindingStart := time.Now() // If binding succeeded then PodScheduled condition will be updated in apiserver so that // it's atomic with setting host. err := s.config.Binder.Bind(b) if err != nil { glog.V(1).Infof("Failed to bind pod: %v/%v", pod.Namespace, pod.Name) if err := s.config.SchedulerCache.ForgetPod(&assumed); err != nil { glog.Errorf("scheduler cache ForgetPod failed: %v", err) } s.config.Error(pod, err) s.config.Recorder.Eventf(pod, v1.EventTypeNormal, "FailedScheduling", "Binding rejected: %v", err) s.config.PodConditionUpdater.Update(pod, &v1.PodCondition{ Type: v1.PodScheduled, Status: v1.ConditionFalse, Reason: "BindingRejected", }) return } metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) s.config.Recorder.Eventf(pod, v1.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest) }() }
func (s *Scheduler) scheduleOne() { pod := s.config.NextPod() glog.V(3).Infof("Attempting to schedule pod: %v/%v", pod.Namespace, pod.Name) start := time.Now() dest, err := s.config.Algorithm.Schedule(pod, s.config.NodeLister) if err != nil { glog.V(1).Infof("Failed to schedule pod: %v/%v", pod.Namespace, pod.Name) s.config.Error(pod, err) s.config.Recorder.Eventf(pod, api.EventTypeWarning, "FailedScheduling", "%v", err) s.config.PodConditionUpdater.Update(pod, &api.PodCondition{ Type: api.PodScheduled, Status: api.ConditionFalse, Reason: "Unschedulable", }) return } metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) // Optimistically assume that the binding will succeed and send it to apiserver // in the background. // If the binding fails, scheduler will release resources allocated to assumed pod // immediately. assumed := *pod assumed.Spec.NodeName = dest if err := s.config.SchedulerCache.AssumePod(&assumed); err != nil { glog.Errorf("scheduler cache AssumePod failed: %v", err) } go func() { defer metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) b := &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name}, Target: api.ObjectReference{ Kind: "Node", Name: dest, }, } bindingStart := time.Now() // If binding succeeded then PodScheduled condition will be updated in apiserver so that // it's atomic with setting host. err := s.config.Binder.Bind(b) if err != nil { glog.V(1).Infof("Failed to bind pod: %v/%v", pod.Namespace, pod.Name) if err := s.config.SchedulerCache.ForgetPod(&assumed); err != nil { glog.Errorf("scheduler cache ForgetPod failed: %v", err) } s.config.Error(pod, err) s.config.Recorder.Eventf(pod, api.EventTypeNormal, "FailedScheduling", "Binding rejected: %v", err) s.config.PodConditionUpdater.Update(pod, &api.PodCondition{ Type: api.PodScheduled, Status: api.ConditionFalse, Reason: "BindingRejected", }) return } metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart)) s.config.Recorder.Eventf(pod, api.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest) }() }