plumb context from CRI calls through kubelet
This commit is contained in:
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package eviction
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -230,6 +231,7 @@ func (m *managerImpl) IsUnderPIDPressure() bool {
|
||||
// synchronize is the main control loop that enforces eviction thresholds.
|
||||
// Returns the pod that was killed, or nil if no pod was killed.
|
||||
func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc ActivePodsFunc) []*v1.Pod {
|
||||
ctx := context.Background()
|
||||
// if we have nothing to do, just return
|
||||
thresholds := m.config.Thresholds
|
||||
if len(thresholds) == 0 && !m.localStorageCapacityIsolation {
|
||||
@@ -240,7 +242,7 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act
|
||||
// build the ranking functions (if not yet known)
|
||||
// TODO: have a function in cadvisor that lets us know if global housekeeping has completed
|
||||
if m.dedicatedImageFs == nil {
|
||||
hasImageFs, ok := diskInfoProvider.HasDedicatedImageFs()
|
||||
hasImageFs, ok := diskInfoProvider.HasDedicatedImageFs(ctx)
|
||||
if ok != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -251,7 +253,7 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act
|
||||
|
||||
activePods := podFunc()
|
||||
updateStats := true
|
||||
summary, err := m.summaryProvider.Get(updateStats)
|
||||
summary, err := m.summaryProvider.Get(ctx, updateStats)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "Eviction manager: failed to get summary stats")
|
||||
return nil
|
||||
@@ -343,7 +345,7 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act
|
||||
m.recorder.Eventf(m.nodeRef, v1.EventTypeWarning, "EvictionThresholdMet", "Attempting to reclaim %s", resourceToReclaim)
|
||||
|
||||
// check if there are node-level resources we can reclaim to reduce pressure before evicting end-user pods.
|
||||
if m.reclaimNodeLevelResources(thresholdToReclaim.Signal, resourceToReclaim) {
|
||||
if m.reclaimNodeLevelResources(ctx, thresholdToReclaim.Signal, resourceToReclaim) {
|
||||
klog.InfoS("Eviction manager: able to reduce resource pressure without evicting pods.", "resourceName", resourceToReclaim)
|
||||
return nil
|
||||
}
|
||||
@@ -418,17 +420,17 @@ func (m *managerImpl) waitForPodsCleanup(podCleanedUpFunc PodCleanedUpFunc, pods
|
||||
}
|
||||
|
||||
// reclaimNodeLevelResources attempts to reclaim node level resources. returns true if thresholds were satisfied and no pod eviction is required.
|
||||
func (m *managerImpl) reclaimNodeLevelResources(signalToReclaim evictionapi.Signal, resourceToReclaim v1.ResourceName) bool {
|
||||
func (m *managerImpl) reclaimNodeLevelResources(ctx context.Context, signalToReclaim evictionapi.Signal, resourceToReclaim v1.ResourceName) bool {
|
||||
nodeReclaimFuncs := m.signalToNodeReclaimFuncs[signalToReclaim]
|
||||
for _, nodeReclaimFunc := range nodeReclaimFuncs {
|
||||
// attempt to reclaim the pressured resource.
|
||||
if err := nodeReclaimFunc(); err != nil {
|
||||
if err := nodeReclaimFunc(ctx); err != nil {
|
||||
klog.InfoS("Eviction manager: unexpected error when attempting to reduce resource pressure", "resourceName", resourceToReclaim, "err", err)
|
||||
}
|
||||
|
||||
}
|
||||
if len(nodeReclaimFuncs) > 0 {
|
||||
summary, err := m.summaryProvider.Get(true)
|
||||
summary, err := m.summaryProvider.Get(ctx, true)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "Eviction manager: failed to get summary stats after resource reclaim")
|
||||
return false
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package eviction
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -67,7 +68,7 @@ type mockDiskInfoProvider struct {
|
||||
}
|
||||
|
||||
// HasDedicatedImageFs returns the mocked value
|
||||
func (m *mockDiskInfoProvider) HasDedicatedImageFs() (bool, error) {
|
||||
func (m *mockDiskInfoProvider) HasDedicatedImageFs(_ context.Context) (bool, error) {
|
||||
return m.dedicatedImageFs, nil
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ type mockDiskGC struct {
|
||||
}
|
||||
|
||||
// DeleteUnusedImages returns the mocked values.
|
||||
func (m *mockDiskGC) DeleteUnusedImages() error {
|
||||
func (m *mockDiskGC) DeleteUnusedImages(_ context.Context) error {
|
||||
m.imageGCInvoked = true
|
||||
if m.summaryAfterGC != nil && m.fakeSummaryProvider != nil {
|
||||
m.fakeSummaryProvider.result = m.summaryAfterGC
|
||||
@@ -90,7 +91,7 @@ func (m *mockDiskGC) DeleteUnusedImages() error {
|
||||
}
|
||||
|
||||
// DeleteAllUnusedContainers returns the mocked value
|
||||
func (m *mockDiskGC) DeleteAllUnusedContainers() error {
|
||||
func (m *mockDiskGC) DeleteAllUnusedContainers(_ context.Context) error {
|
||||
m.containerGCInvoked = true
|
||||
if m.summaryAfterGC != nil && m.fakeSummaryProvider != nil {
|
||||
m.fakeSummaryProvider.result = m.summaryAfterGC
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package eviction
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
@@ -1185,11 +1186,11 @@ type fakeSummaryProvider struct {
|
||||
result *statsapi.Summary
|
||||
}
|
||||
|
||||
func (f *fakeSummaryProvider) Get(updateStats bool) (*statsapi.Summary, error) {
|
||||
func (f *fakeSummaryProvider) Get(ctx context.Context, updateStats bool) (*statsapi.Summary, error) {
|
||||
return f.result, nil
|
||||
}
|
||||
|
||||
func (f *fakeSummaryProvider) GetCPUAndMemoryStats() (*statsapi.Summary, error) {
|
||||
func (f *fakeSummaryProvider) GetCPUAndMemoryStats(ctx context.Context) (*statsapi.Summary, error) {
|
||||
return f.result, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ limitations under the License.
|
||||
package eviction
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
time "time"
|
||||
|
||||
@@ -129,18 +130,18 @@ func (m *MockDiskInfoProvider) EXPECT() *MockDiskInfoProviderMockRecorder {
|
||||
}
|
||||
|
||||
// HasDedicatedImageFs mocks base method.
|
||||
func (m *MockDiskInfoProvider) HasDedicatedImageFs() (bool, error) {
|
||||
func (m *MockDiskInfoProvider) HasDedicatedImageFs(ctx context.Context) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasDedicatedImageFs")
|
||||
ret := m.ctrl.Call(m, "HasDedicatedImageFs", ctx)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// HasDedicatedImageFs indicates an expected call of HasDedicatedImageFs.
|
||||
func (mr *MockDiskInfoProviderMockRecorder) HasDedicatedImageFs() *gomock.Call {
|
||||
func (mr *MockDiskInfoProviderMockRecorder) HasDedicatedImageFs(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDedicatedImageFs", reflect.TypeOf((*MockDiskInfoProvider)(nil).HasDedicatedImageFs))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDedicatedImageFs", reflect.TypeOf((*MockDiskInfoProvider)(nil).HasDedicatedImageFs), ctx)
|
||||
}
|
||||
|
||||
// MockImageGC is a mock of ImageGC interface.
|
||||
@@ -167,17 +168,17 @@ func (m *MockImageGC) EXPECT() *MockImageGCMockRecorder {
|
||||
}
|
||||
|
||||
// DeleteUnusedImages mocks base method.
|
||||
func (m *MockImageGC) DeleteUnusedImages() error {
|
||||
func (m *MockImageGC) DeleteUnusedImages(ctx context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteUnusedImages")
|
||||
ret := m.ctrl.Call(m, "DeleteUnusedImages", ctx)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteUnusedImages indicates an expected call of DeleteUnusedImages.
|
||||
func (mr *MockImageGCMockRecorder) DeleteUnusedImages() *gomock.Call {
|
||||
func (mr *MockImageGCMockRecorder) DeleteUnusedImages(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUnusedImages", reflect.TypeOf((*MockImageGC)(nil).DeleteUnusedImages))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUnusedImages", reflect.TypeOf((*MockImageGC)(nil).DeleteUnusedImages), ctx)
|
||||
}
|
||||
|
||||
// MockContainerGC is a mock of ContainerGC interface.
|
||||
@@ -204,17 +205,17 @@ func (m *MockContainerGC) EXPECT() *MockContainerGCMockRecorder {
|
||||
}
|
||||
|
||||
// DeleteAllUnusedContainers mocks base method.
|
||||
func (m *MockContainerGC) DeleteAllUnusedContainers() error {
|
||||
func (m *MockContainerGC) DeleteAllUnusedContainers(ctx context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteAllUnusedContainers")
|
||||
ret := m.ctrl.Call(m, "DeleteAllUnusedContainers", ctx)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteAllUnusedContainers indicates an expected call of DeleteAllUnusedContainers.
|
||||
func (mr *MockContainerGCMockRecorder) DeleteAllUnusedContainers() *gomock.Call {
|
||||
func (mr *MockContainerGCMockRecorder) DeleteAllUnusedContainers(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllUnusedContainers", reflect.TypeOf((*MockContainerGC)(nil).DeleteAllUnusedContainers))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllUnusedContainers", reflect.TypeOf((*MockContainerGC)(nil).DeleteAllUnusedContainers), ctx)
|
||||
}
|
||||
|
||||
// MockCgroupNotifier is a mock of CgroupNotifier interface.
|
||||
|
||||
@@ -18,6 +18,7 @@ limitations under the License.
|
||||
package eviction
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@@ -71,19 +72,19 @@ type Manager interface {
|
||||
// DiskInfoProvider is responsible for informing the manager how disk is configured.
|
||||
type DiskInfoProvider interface {
|
||||
// HasDedicatedImageFs returns true if the imagefs is on a separate device from the rootfs.
|
||||
HasDedicatedImageFs() (bool, error)
|
||||
HasDedicatedImageFs(ctx context.Context) (bool, error)
|
||||
}
|
||||
|
||||
// ImageGC is responsible for performing garbage collection of unused images.
|
||||
type ImageGC interface {
|
||||
// DeleteUnusedImages deletes unused images.
|
||||
DeleteUnusedImages() error
|
||||
DeleteUnusedImages(ctx context.Context) error
|
||||
}
|
||||
|
||||
// ContainerGC is responsible for performing garbage collection of unused containers.
|
||||
type ContainerGC interface {
|
||||
// DeleteAllUnusedContainers deletes all unused containers, even those that belong to pods that are terminated, but not deleted.
|
||||
DeleteAllUnusedContainers() error
|
||||
DeleteAllUnusedContainers(ctx context.Context) error
|
||||
}
|
||||
|
||||
// KillPodFunc kills a pod.
|
||||
@@ -131,7 +132,7 @@ type thresholdsObservedAt map[evictionapi.Threshold]time.Time
|
||||
type nodeConditionsObservedAt map[v1.NodeConditionType]time.Time
|
||||
|
||||
// nodeReclaimFunc is a function that knows how to reclaim a resource from the node without impacting pods.
|
||||
type nodeReclaimFunc func() error
|
||||
type nodeReclaimFunc func(ctx context.Context) error
|
||||
|
||||
// nodeReclaimFuncs is an ordered list of nodeReclaimFunc
|
||||
type nodeReclaimFuncs []nodeReclaimFunc
|
||||
|
||||
Reference in New Issue
Block a user