Commit 8b440c64 authored by David Ashpole's avatar David Ashpole

Fix PidPressure, make it evict by priority, and add fork-bomb node e2e test

parent 3d9c6eb9
...@@ -63,6 +63,7 @@ var OpForSignal = map[Signal]ThresholdOperator{ ...@@ -63,6 +63,7 @@ var OpForSignal = map[Signal]ThresholdOperator{
SignalNodeFsInodesFree: OpLessThan, SignalNodeFsInodesFree: OpLessThan,
SignalImageFsAvailable: OpLessThan, SignalImageFsAvailable: OpLessThan,
SignalImageFsInodesFree: OpLessThan, SignalImageFsInodesFree: OpLessThan,
SignalPIDAvailable: OpLessThan,
} }
// ThresholdValue is a value holder that abstracts literal versus percentage based quantity // ThresholdValue is a value holder that abstracts literal versus percentage based quantity
......
...@@ -157,7 +157,7 @@ func (m *managerImpl) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAd ...@@ -157,7 +157,7 @@ func (m *managerImpl) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAd
return lifecycle.PodAdmitResult{ return lifecycle.PodAdmitResult{
Admit: false, Admit: false,
Reason: Reason, Reason: Reason,
Message: fmt.Sprintf(nodeLowMessageFmt, m.nodeConditions), Message: fmt.Sprintf(nodeConditionMessageFmt, m.nodeConditions),
} }
} }
......
...@@ -40,6 +40,8 @@ const ( ...@@ -40,6 +40,8 @@ const (
Reason = "Evicted" Reason = "Evicted"
// nodeLowMessageFmt is the message for evictions due to resource pressure. // nodeLowMessageFmt is the message for evictions due to resource pressure.
nodeLowMessageFmt = "The node was low on resource: %v. " nodeLowMessageFmt = "The node was low on resource: %v. "
// nodeConditionMessageFmt is the message for evictions due to resource pressure.
nodeConditionMessageFmt = "The node had condition: %v. "
// containerMessageFmt provides additional information for containers exceeding requests // containerMessageFmt provides additional information for containers exceeding requests
containerMessageFmt = "Container %s was using %s, which exceeds its request of %s. " containerMessageFmt = "Container %s was using %s, which exceeds its request of %s. "
// containerEphemeralStorageMessageFmt provides additional information for containers which have exceeded their ES limit // containerEphemeralStorageMessageFmt provides additional information for containers which have exceeded their ES limit
...@@ -50,6 +52,8 @@ const ( ...@@ -50,6 +52,8 @@ const (
emptyDirMessageFmt = "Usage of EmptyDir volume %q exceeds the limit %q. " emptyDirMessageFmt = "Usage of EmptyDir volume %q exceeds the limit %q. "
// inodes, number. internal to this module, used to account for local disk inode consumption. // inodes, number. internal to this module, used to account for local disk inode consumption.
resourceInodes v1.ResourceName = "inodes" resourceInodes v1.ResourceName = "inodes"
// resourcePids, number. internal to this module, used to account for local pid consumption.
resourcePids v1.ResourceName = "pids"
// OffendingContainersKey is the key in eviction event annotations for the list of container names which exceeded their requests // OffendingContainersKey is the key in eviction event annotations for the list of container names which exceeded their requests
OffendingContainersKey = "offending_containers" OffendingContainersKey = "offending_containers"
// OffendingContainersUsageKey is the key in eviction event annotations for the list of usage of containers which exceeded their requests // OffendingContainersUsageKey is the key in eviction event annotations for the list of usage of containers which exceeded their requests
...@@ -84,6 +88,7 @@ func init() { ...@@ -84,6 +88,7 @@ func init() {
signalToResource[evictionapi.SignalImageFsInodesFree] = resourceInodes signalToResource[evictionapi.SignalImageFsInodesFree] = resourceInodes
signalToResource[evictionapi.SignalNodeFsAvailable] = v1.ResourceEphemeralStorage signalToResource[evictionapi.SignalNodeFsAvailable] = v1.ResourceEphemeralStorage
signalToResource[evictionapi.SignalNodeFsInodesFree] = resourceInodes signalToResource[evictionapi.SignalNodeFsInodesFree] = resourceInodes
signalToResource[evictionapi.SignalPIDAvailable] = resourcePids
} }
// validSignal returns true if the signal is supported. // validSignal returns true if the signal is supported.
...@@ -674,6 +679,11 @@ func rankMemoryPressure(pods []*v1.Pod, stats statsFunc) { ...@@ -674,6 +679,11 @@ func rankMemoryPressure(pods []*v1.Pod, stats statsFunc) {
orderedBy(exceedMemoryRequests(stats), priority, memory(stats)).Sort(pods) orderedBy(exceedMemoryRequests(stats), priority, memory(stats)).Sort(pods)
} }
// rankPIDPressure orders the input pods by priority in response to PID pressure.
func rankPIDPressure(pods []*v1.Pod, stats statsFunc) {
orderedBy(priority).Sort(pods)
}
// rankDiskPressureFunc returns a rankFunc that measures the specified fs stats. // rankDiskPressureFunc returns a rankFunc that measures the specified fs stats.
func rankDiskPressureFunc(fsStatsToMeasure []fsStatsType, diskResource v1.ResourceName) rankFunc { func rankDiskPressureFunc(fsStatsToMeasure []fsStatsType, diskResource v1.ResourceName) rankFunc {
return func(pods []*v1.Pod, stats statsFunc) { return func(pods []*v1.Pod, stats statsFunc) {
...@@ -987,6 +997,7 @@ func buildSignalToRankFunc(withImageFs bool) map[evictionapi.Signal]rankFunc { ...@@ -987,6 +997,7 @@ func buildSignalToRankFunc(withImageFs bool) map[evictionapi.Signal]rankFunc {
signalToRankFunc := map[evictionapi.Signal]rankFunc{ signalToRankFunc := map[evictionapi.Signal]rankFunc{
evictionapi.SignalMemoryAvailable: rankMemoryPressure, evictionapi.SignalMemoryAvailable: rankMemoryPressure,
evictionapi.SignalAllocatableMemoryAvailable: rankMemoryPressure, evictionapi.SignalAllocatableMemoryAvailable: rankMemoryPressure,
evictionapi.SignalPIDAvailable: rankPIDPressure,
} }
// usage of an imagefs is optional // usage of an imagefs is optional
if withImageFs { if withImageFs {
......
...@@ -943,13 +943,13 @@ func TestSortByEvictionPriority(t *testing.T) { ...@@ -943,13 +943,13 @@ func TestSortByEvictionPriority(t *testing.T) {
expected: []evictionapi.Threshold{}, expected: []evictionapi.Threshold{},
}, },
{ {
name: "memory first, PID last", name: "memory first",
thresholds: []evictionapi.Threshold{ thresholds: []evictionapi.Threshold{
{ {
Signal: evictionapi.SignalPIDAvailable, Signal: evictionapi.SignalNodeFsAvailable,
}, },
{ {
Signal: evictionapi.SignalNodeFsAvailable, Signal: evictionapi.SignalPIDAvailable,
}, },
{ {
Signal: evictionapi.SignalMemoryAvailable, Signal: evictionapi.SignalMemoryAvailable,
...@@ -968,13 +968,13 @@ func TestSortByEvictionPriority(t *testing.T) { ...@@ -968,13 +968,13 @@ func TestSortByEvictionPriority(t *testing.T) {
}, },
}, },
{ {
name: "allocatable memory first, PID last", name: "allocatable memory first",
thresholds: []evictionapi.Threshold{ thresholds: []evictionapi.Threshold{
{ {
Signal: evictionapi.SignalPIDAvailable, Signal: evictionapi.SignalNodeFsAvailable,
}, },
{ {
Signal: evictionapi.SignalNodeFsAvailable, Signal: evictionapi.SignalPIDAvailable,
}, },
{ {
Signal: evictionapi.SignalAllocatableMemoryAvailable, Signal: evictionapi.SignalAllocatableMemoryAvailable,
......
...@@ -122,6 +122,7 @@ go_test( ...@@ -122,6 +122,7 @@ go_test(
"//pkg/kubelet/cm/cpuset:go_default_library", "//pkg/kubelet/cm/cpuset:go_default_library",
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/eviction:go_default_library", "//pkg/kubelet/eviction:go_default_library",
"//pkg/kubelet/eviction/api:go_default_library",
"//pkg/kubelet/images:go_default_library", "//pkg/kubelet/images:go_default_library",
"//pkg/kubelet/kubeletconfig:go_default_library", "//pkg/kubelet/kubeletconfig:go_default_library",
"//pkg/kubelet/kubeletconfig/status:go_default_library", "//pkg/kubelet/kubeletconfig/status:go_default_library",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment