Merge pull request #105125 from BinacsLee/binacs-fix-scheQ-caculate-overflow

Scheduler: fix calculateBackoffDuration overflow in extreme data cases
This commit is contained in:
Kubernetes Prow Robot 2021-09-20 21:26:23 -07:00 committed by GitHub
commit 6c45f6e32b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 4 deletions

View File

@ -742,10 +742,11 @@ func (p *PriorityQueue) getBackoffTime(podInfo *framework.QueuedPodInfo) time.Ti
func (p *PriorityQueue) calculateBackoffDuration(podInfo *framework.QueuedPodInfo) time.Duration { func (p *PriorityQueue) calculateBackoffDuration(podInfo *framework.QueuedPodInfo) time.Duration {
duration := p.podInitialBackoffDuration duration := p.podInitialBackoffDuration
for i := 1; i < podInfo.Attempts; i++ { for i := 1; i < podInfo.Attempts; i++ {
duration = duration * 2 // Use subtraction instead of addition or multiplication to avoid overflow.
if duration > p.podMaxBackoffDuration { if duration > p.podMaxBackoffDuration-duration {
return p.podMaxBackoffDuration return p.podMaxBackoffDuration
} }
duration += duration
} }
return duration return duration
} }

View File

@ -19,6 +19,7 @@ package queue
import ( import (
"context" "context"
"fmt" "fmt"
"math"
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
@ -27,10 +28,9 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"k8s.io/apimachinery/pkg/runtime"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
@ -1995,3 +1995,43 @@ func makeQueuedPodInfos(num int, timestamp time.Time) []*framework.QueuedPodInfo
} }
return pInfos return pInfos
} }
func TestPriorityQueue_calculateBackoffDuration(t *testing.T) {
tests := []struct {
name string
initialBackoffDuration time.Duration
maxBackoffDuration time.Duration
podInfo *framework.QueuedPodInfo
want time.Duration
}{
{
name: "normal",
initialBackoffDuration: 1 * time.Nanosecond,
maxBackoffDuration: 32 * time.Nanosecond,
podInfo: &framework.QueuedPodInfo{Attempts: 16},
want: 32 * time.Nanosecond,
},
{
name: "overflow_32bit",
initialBackoffDuration: 1 * time.Nanosecond,
maxBackoffDuration: math.MaxInt32 * time.Nanosecond,
podInfo: &framework.QueuedPodInfo{Attempts: 32},
want: math.MaxInt32 * time.Nanosecond,
},
{
name: "overflow_64bit",
initialBackoffDuration: 1 * time.Nanosecond,
maxBackoffDuration: math.MaxInt64 * time.Nanosecond,
podInfo: &framework.QueuedPodInfo{Attempts: 64},
want: math.MaxInt64 * time.Nanosecond,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
q := NewTestQueue(context.Background(), newDefaultQueueSort(), WithPodInitialBackoffDuration(tt.initialBackoffDuration), WithPodMaxBackoffDuration(tt.maxBackoffDuration))
if got := q.calculateBackoffDuration(tt.podInfo); got != tt.want {
t.Errorf("PriorityQueue.calculateBackoffDuration() = %v, want %v", got, tt.want)
}
})
}
}