Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
fed3f37e
Commit
fed3f37e
authored
Sep 22, 2016
by
David Ashpole
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split NodeDiskPressure into NodeInodePressure and NodeDiskPressure
parent
3933ddbc
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
277 additions
and
9 deletions
+277
-9
types.go
pkg/api/types.go
+2
-0
eviction_manager.go
pkg/kubelet/eviction/eviction_manager.go
+7
-0
eviction_manager_test.go
pkg/kubelet/eviction/eviction_manager_test.go
+7
-7
helpers.go
pkg/kubelet/eviction/helpers.go
+2
-2
types.go
pkg/kubelet/eviction/types.go
+3
-0
kubelet_node_status.go
pkg/kubelet/kubelet_node_status.go
+60
-0
kubelet_node_status_test.go
pkg/kubelet/kubelet_node_status_test.go
+32
-0
error.go
plugin/pkg/scheduler/algorithm/predicates/error.go
+1
-0
predicates.go
plugin/pkg/scheduler/algorithm/predicates/predicates.go
+18
-0
predicates_test.go
plugin/pkg/scheduler/algorithm/predicates/predicates_test.go
+72
-0
compatibility_test.go
...cheduler/algorithmprovider/defaults/compatibility_test.go
+70
-0
defaults.go
plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go
+3
-0
No files found.
pkg/api/types.go
View file @
fed3f37e
...
...
@@ -2224,6 +2224,8 @@ const (
NodeDiskPressure
NodeConditionType
=
"DiskPressure"
// NodeNetworkUnavailable means that network for the node is not correctly configured.
NodeNetworkUnavailable
NodeConditionType
=
"NetworkUnavailable"
// NodeInodePressure means the kublet is under pressure due to insufficient available inodes.
NodeInodePressure
NodeConditionType
=
"InodePressure"
)
type
NodeCondition
struct
{
...
...
pkg/kubelet/eviction/eviction_manager.go
View file @
fed3f37e
...
...
@@ -136,6 +136,13 @@ func (m *managerImpl) IsUnderDiskPressure() bool {
return
hasNodeCondition
(
m
.
nodeConditions
,
api
.
NodeDiskPressure
)
}
// IsUnderDiskPressure returns true if the node is under disk pressure.
func
(
m
*
managerImpl
)
IsUnderInodePressure
()
bool
{
m
.
RLock
()
defer
m
.
RUnlock
()
return
hasNodeCondition
(
m
.
nodeConditions
,
api
.
NodeInodePressure
)
}
// synchronize is the main control loop that enforces eviction thresholds.
func
(
m
*
managerImpl
)
synchronize
(
diskInfoProvider
DiskInfoProvider
,
podFunc
ActivePodsFunc
)
{
// if we have nothing to do, just return
...
...
pkg/kubelet/eviction/eviction_manager_test.go
View file @
fed3f37e
...
...
@@ -1014,7 +1014,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should not have disk pressure
if
manager
.
IsUnder
Disk
Pressure
()
{
if
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should not report disk pressure"
)
}
...
...
@@ -1029,7 +1029,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should have disk pressure
if
!
manager
.
IsUnder
Disk
Pressure
()
{
if
!
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should report disk pressure since soft threshold was met"
)
}
...
...
@@ -1044,7 +1044,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should have disk pressure
if
!
manager
.
IsUnder
Disk
Pressure
()
{
if
!
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should report disk pressure since soft threshold was met"
)
}
...
...
@@ -1069,7 +1069,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should not have disk pressure
if
manager
.
IsUnder
Disk
Pressure
()
{
if
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should not report disk pressure"
)
}
...
...
@@ -1079,7 +1079,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should have disk pressure
if
!
manager
.
IsUnder
Disk
Pressure
()
{
if
!
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should report disk pressure"
)
}
...
...
@@ -1104,7 +1104,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should have disk pressure (because transition period not yet met)
if
!
manager
.
IsUnder
Disk
Pressure
()
{
if
!
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should report disk pressure"
)
}
...
...
@@ -1125,7 +1125,7 @@ func TestDiskPressureNodeFsInodes(t *testing.T) {
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
)
// we should not have disk pressure (because transition period met)
if
manager
.
IsUnder
Disk
Pressure
()
{
if
manager
.
IsUnder
Inode
Pressure
()
{
t
.
Errorf
(
"Manager should not report disk pressure"
)
}
...
...
pkg/kubelet/eviction/helpers.go
View file @
fed3f37e
...
...
@@ -68,8 +68,8 @@ func init() {
signalToNodeCondition
[
SignalMemoryAvailable
]
=
api
.
NodeMemoryPressure
signalToNodeCondition
[
SignalImageFsAvailable
]
=
api
.
NodeDiskPressure
signalToNodeCondition
[
SignalNodeFsAvailable
]
=
api
.
NodeDiskPressure
signalToNodeCondition
[
SignalImageFsInodesFree
]
=
api
.
Node
Disk
Pressure
signalToNodeCondition
[
SignalNodeFsInodesFree
]
=
api
.
Node
Disk
Pressure
signalToNodeCondition
[
SignalImageFsInodesFree
]
=
api
.
Node
Inode
Pressure
signalToNodeCondition
[
SignalNodeFsInodesFree
]
=
api
.
Node
Inode
Pressure
// map signals to resources (and vice-versa)
signalToResource
=
map
[
Signal
]
api
.
ResourceName
{}
...
...
pkg/kubelet/eviction/types.go
View file @
fed3f37e
...
...
@@ -104,6 +104,9 @@ type Manager interface {
// IsUnderDiskPressure returns true if the node is under disk pressure.
IsUnderDiskPressure
()
bool
// IsUnderInodePressure returns true if the node is under disk pressure.
IsUnderInodePressure
()
bool
}
// DiskInfoProvider is responsible for informing the manager how disk is configured.
...
...
pkg/kubelet/kubelet_node_status.go
View file @
fed3f37e
...
...
@@ -742,6 +742,65 @@ func (kl *Kubelet) setNodeDiskPressureCondition(node *api.Node) {
}
}
// setNodeInodePressureCondition for the node.
// TODO: this needs to move somewhere centralized...
func
(
kl
*
Kubelet
)
setNodeInodePressureCondition
(
node
*
api
.
Node
)
{
currentTime
:=
unversioned
.
NewTime
(
kl
.
clock
.
Now
())
var
condition
*
api
.
NodeCondition
// Check if NodeInodePressure condition already exists and if it does, just pick it up for update.
for
i
:=
range
node
.
Status
.
Conditions
{
if
node
.
Status
.
Conditions
[
i
]
.
Type
==
api
.
NodeInodePressure
{
condition
=
&
node
.
Status
.
Conditions
[
i
]
}
}
newCondition
:=
false
// If the NodeInodePressure condition doesn't exist, create one
if
condition
==
nil
{
condition
=
&
api
.
NodeCondition
{
Type
:
api
.
NodeInodePressure
,
Status
:
api
.
ConditionUnknown
,
}
// cannot be appended to node.Status.Conditions here because it gets
// copied to the slice. So if we append to the slice here none of the
// updates we make below are reflected in the slice.
newCondition
=
true
}
// Update the heartbeat time
condition
.
LastHeartbeatTime
=
currentTime
// Note: The conditions below take care of the case when a new NodeInodePressure condition is
// created and as well as the case when the condition already exists. When a new condition
// is created its status is set to api.ConditionUnknown which matches either
// condition.Status != api.ConditionTrue or
// condition.Status != api.ConditionFalse in the conditions below depending on whether
// the kubelet is under inode pressure or not.
if
kl
.
evictionManager
.
IsUnderInodePressure
()
{
if
condition
.
Status
!=
api
.
ConditionTrue
{
condition
.
Status
=
api
.
ConditionTrue
condition
.
Reason
=
"KubeletHasInodePressure"
condition
.
Message
=
"kubelet has inode pressure"
condition
.
LastTransitionTime
=
currentTime
kl
.
recordNodeStatusEvent
(
api
.
EventTypeNormal
,
"NodeHasInodePressure"
)
}
}
else
{
if
condition
.
Status
!=
api
.
ConditionFalse
{
condition
.
Status
=
api
.
ConditionFalse
condition
.
Reason
=
"KubeletHasNoInodePressure"
condition
.
Message
=
"kubelet has no inode pressure"
condition
.
LastTransitionTime
=
currentTime
kl
.
recordNodeStatusEvent
(
api
.
EventTypeNormal
,
"NodeHasNoInodePressure"
)
}
}
if
newCondition
{
node
.
Status
.
Conditions
=
append
(
node
.
Status
.
Conditions
,
*
condition
)
}
}
// Set OODcondition for the node.
func
(
kl
*
Kubelet
)
setNodeOODCondition
(
node
*
api
.
Node
)
{
currentTime
:=
unversioned
.
NewTime
(
kl
.
clock
.
Now
())
...
...
@@ -856,6 +915,7 @@ func (kl *Kubelet) defaultNodeStatusFuncs() []func(*api.Node) error {
withoutError
(
kl
.
setNodeOODCondition
),
withoutError
(
kl
.
setNodeMemoryPressureCondition
),
withoutError
(
kl
.
setNodeDiskPressureCondition
),
withoutError
(
kl
.
setNodeInodePressureCondition
),
withoutError
(
kl
.
setNodeReadyCondition
),
withoutError
(
kl
.
setNodeVolumesInUseStatus
),
withoutError
(
kl
.
recordNodeSchedulableEvent
),
...
...
pkg/kubelet/kubelet_node_status_test.go
View file @
fed3f37e
...
...
@@ -150,6 +150,14 @@ func TestUpdateNewNodeStatus(t *testing.T) {
LastTransitionTime
:
unversioned
.
Time
{},
},
{
Type
:
api
.
NodeInodePressure
,
Status
:
api
.
ConditionFalse
,
Reason
:
"KubeletHasNoInodePressure"
,
Message
:
fmt
.
Sprintf
(
"kubelet has no inode pressure"
),
LastHeartbeatTime
:
unversioned
.
Time
{},
LastTransitionTime
:
unversioned
.
Time
{},
},
{
Type
:
api
.
NodeReady
,
Status
:
api
.
ConditionTrue
,
Reason
:
"KubeletReady"
,
...
...
@@ -341,6 +349,14 @@ func TestUpdateExistingNodeStatus(t *testing.T) {
LastTransitionTime
:
unversioned
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
api
.
NodeInodePressure
,
Status
:
api
.
ConditionFalse
,
Reason
:
"KubeletHasSufficientInode"
,
Message
:
fmt
.
Sprintf
(
"kubelet has sufficient inodes available"
),
LastHeartbeatTime
:
unversioned
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
unversioned
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
api
.
NodeReady
,
Status
:
api
.
ConditionTrue
,
Reason
:
"KubeletReady"
,
...
...
@@ -413,6 +429,14 @@ func TestUpdateExistingNodeStatus(t *testing.T) {
LastTransitionTime
:
unversioned
.
Time
{},
},
{
Type
:
api
.
NodeInodePressure
,
Status
:
api
.
ConditionFalse
,
Reason
:
"KubeletHasSufficientInode"
,
Message
:
fmt
.
Sprintf
(
"kubelet has sufficient inodes available"
),
LastHeartbeatTime
:
unversioned
.
Time
{},
LastTransitionTime
:
unversioned
.
Time
{},
},
{
Type
:
api
.
NodeReady
,
Status
:
api
.
ConditionTrue
,
Reason
:
"KubeletReady"
,
...
...
@@ -716,6 +740,14 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) {
LastHeartbeatTime
:
unversioned
.
Time
{},
LastTransitionTime
:
unversioned
.
Time
{},
},
{
Type
:
api
.
NodeInodePressure
,
Status
:
api
.
ConditionFalse
,
Reason
:
"KubeletHasNoInodePressure"
,
Message
:
fmt
.
Sprintf
(
"kubelet has no inode pressure"
),
LastHeartbeatTime
:
unversioned
.
Time
{},
LastTransitionTime
:
unversioned
.
Time
{},
},
{},
//placeholder
},
NodeInfo
:
api
.
NodeSystemInfo
{
...
...
plugin/pkg/scheduler/algorithm/predicates/error.go
View file @
fed3f37e
...
...
@@ -37,6 +37,7 @@ var (
ErrMaxVolumeCountExceeded
=
newPredicateFailureError
(
"MaxVolumeCount"
)
ErrNodeUnderMemoryPressure
=
newPredicateFailureError
(
"NodeUnderMemoryPressure"
)
ErrNodeUnderDiskPressure
=
newPredicateFailureError
(
"NodeUnderDiskPressure"
)
ErrNodeUnderInodePressure
=
newPredicateFailureError
(
"NodeUnderInodePressure"
)
// ErrFakePredicate is used for test only. The fake predicates returning false also returns error
// as ErrFakePredicate.
ErrFakePredicate
=
newPredicateFailureError
(
"FakePredicateError"
)
...
...
plugin/pkg/scheduler/algorithm/predicates/predicates.go
View file @
fed3f37e
...
...
@@ -1168,3 +1168,21 @@ func CheckNodeDiskPressurePredicate(pod *api.Pod, meta interface{}, nodeInfo *sc
return
true
,
nil
,
nil
}
// CheckNodeDiskPressurePredicate checks if a pod can be scheduled on a node
// reporting disk pressure condition.
func
CheckNodeInodePressurePredicate
(
pod
*
api
.
Pod
,
meta
interface
{},
nodeInfo
*
schedulercache
.
NodeInfo
)
(
bool
,
[]
algorithm
.
PredicateFailureReason
,
error
)
{
node
:=
nodeInfo
.
Node
()
if
node
==
nil
{
return
false
,
nil
,
fmt
.
Errorf
(
"node not found"
)
}
// is node under presure?
for
_
,
cond
:=
range
node
.
Status
.
Conditions
{
if
cond
.
Type
==
api
.
NodeInodePressure
&&
cond
.
Status
==
api
.
ConditionTrue
{
return
false
,
[]
algorithm
.
PredicateFailureReason
{
ErrNodeUnderInodePressure
},
nil
}
}
return
true
,
nil
,
nil
}
plugin/pkg/scheduler/algorithm/predicates/predicates_test.go
View file @
fed3f37e
...
...
@@ -3028,3 +3028,75 @@ func TestPodSchedulesOnNodeWithDiskPressureCondition(t *testing.T) {
}
}
}
func
TestPodSchedulesOnNodeWithInodePressureCondition
(
t
*
testing
.
T
)
{
pod
:=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Name
:
"container"
,
Image
:
"image"
,
ImagePullPolicy
:
"Always"
,
},
},
},
}
// specify a node with no inode pressure condition on
noPressureNode
:=
&
api
.
Node
{
Status
:
api
.
NodeStatus
{
Conditions
:
[]
api
.
NodeCondition
{
{
Type
:
"Ready"
,
Status
:
"True"
,
},
},
},
}
// specify a node with pressure condition on
pressureNode
:=
&
api
.
Node
{
Status
:
api
.
NodeStatus
{
Conditions
:
[]
api
.
NodeCondition
{
{
Type
:
"InodePressure"
,
Status
:
"True"
,
},
},
},
}
tests
:=
[]
struct
{
pod
*
api
.
Pod
nodeInfo
*
schedulercache
.
NodeInfo
fits
bool
name
string
}{
{
pod
:
pod
,
nodeInfo
:
makeEmptyNodeInfo
(
noPressureNode
),
fits
:
true
,
name
:
"pod schedulable on node without pressure condition on"
,
},
{
pod
:
pod
,
nodeInfo
:
makeEmptyNodeInfo
(
pressureNode
),
fits
:
false
,
name
:
"pod not schedulable on node with pressure condition on"
,
},
}
expectedFailureReasons
:=
[]
algorithm
.
PredicateFailureReason
{
ErrNodeUnderInodePressure
}
for
_
,
test
:=
range
tests
{
fits
,
reasons
,
err
:=
CheckNodeInodePressurePredicate
(
test
.
pod
,
PredicateMetadata
(
test
.
pod
,
nil
),
test
.
nodeInfo
)
if
err
!=
nil
{
t
.
Errorf
(
"%s: unexpected error: %v"
,
test
.
name
,
err
)
}
if
!
fits
&&
!
reflect
.
DeepEqual
(
reasons
,
expectedFailureReasons
)
{
t
.
Errorf
(
"%s: unexpected failure reasons: %v, want: %v"
,
test
.
name
,
reasons
,
expectedFailureReasons
)
}
if
fits
!=
test
.
fits
{
t
.
Errorf
(
"%s: expected %v got %v"
,
test
.
name
,
test
.
fits
,
fits
)
}
}
}
plugin/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go
View file @
fed3f37e
...
...
@@ -306,6 +306,76 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
},
},
},
// Do not change this JSON after the corresponding release has been tagged.
// A failure indicates backwards compatibility with the specified release was broken.
"1.5"
:
{
JSON
:
`{
"kind": "Policy",
"apiVersion": "v1",
"predicates": [
{"name": "MatchNodeSelector"},
{"name": "PodFitsResources"},
{"name": "PodFitsHostPorts"},
{"name": "HostName"},
{"name": "NoDiskConflict"},
{"name": "NoVolumeZoneConflict"},
{"name": "PodToleratesNodeTaints"},
{"name": "CheckNodeMemoryPressure"},
{"name": "CheckNodeDiskPressure"},
{"name": "CheckNodeInodePressure"},
{"name": "MaxEBSVolumeCount"},
{"name": "MaxGCEPDVolumeCount"},
{"name": "MatchInterPodAffinity"},
{"name": "GeneralPredicates"},
{"name": "TestServiceAffinity", "argument": {"serviceAffinity" : {"labels" : ["region"]}}},
{"name": "TestLabelsPresence", "argument": {"labelsPresence" : {"labels" : ["foo"], "presence":true}}}
],"priorities": [
{"name": "EqualPriority", "weight": 2},
{"name": "ImageLocalityPriority", "weight": 2},
{"name": "LeastRequestedPriority", "weight": 2},
{"name": "BalancedResourceAllocation", "weight": 2},
{"name": "SelectorSpreadPriority", "weight": 2},
{"name": "NodePreferAvoidPodsPriority", "weight": 2},
{"name": "NodeAffinityPriority", "weight": 2},
{"name": "TaintTolerationPriority", "weight": 2},
{"name": "InterPodAffinityPriority", "weight": 2},
{"name": "MostRequestedPriority", "weight": 2}
]
}`
,
ExpectedPolicy
:
schedulerapi
.
Policy
{
Predicates
:
[]
schedulerapi
.
PredicatePolicy
{
{
Name
:
"MatchNodeSelector"
},
{
Name
:
"PodFitsResources"
},
{
Name
:
"PodFitsHostPorts"
},
{
Name
:
"HostName"
},
{
Name
:
"NoDiskConflict"
},
{
Name
:
"NoVolumeZoneConflict"
},
{
Name
:
"PodToleratesNodeTaints"
},
{
Name
:
"CheckNodeMemoryPressure"
},
{
Name
:
"CheckNodeDiskPressure"
},
{
Name
:
"CheckNodeInodePressure"
},
{
Name
:
"MaxEBSVolumeCount"
},
{
Name
:
"MaxGCEPDVolumeCount"
},
{
Name
:
"MatchInterPodAffinity"
},
{
Name
:
"GeneralPredicates"
},
{
Name
:
"TestServiceAffinity"
,
Argument
:
&
schedulerapi
.
PredicateArgument
{
ServiceAffinity
:
&
schedulerapi
.
ServiceAffinity
{
Labels
:
[]
string
{
"region"
}}}},
{
Name
:
"TestLabelsPresence"
,
Argument
:
&
schedulerapi
.
PredicateArgument
{
LabelsPresence
:
&
schedulerapi
.
LabelsPresence
{
Labels
:
[]
string
{
"foo"
},
Presence
:
true
}}},
},
Priorities
:
[]
schedulerapi
.
PriorityPolicy
{
{
Name
:
"EqualPriority"
,
Weight
:
2
},
{
Name
:
"ImageLocalityPriority"
,
Weight
:
2
},
{
Name
:
"LeastRequestedPriority"
,
Weight
:
2
},
{
Name
:
"BalancedResourceAllocation"
,
Weight
:
2
},
{
Name
:
"SelectorSpreadPriority"
,
Weight
:
2
},
{
Name
:
"NodePreferAvoidPodsPriority"
,
Weight
:
2
},
{
Name
:
"NodeAffinityPriority"
,
Weight
:
2
},
{
Name
:
"TaintTolerationPriority"
,
Weight
:
2
},
{
Name
:
"InterPodAffinityPriority"
,
Weight
:
2
},
{
Name
:
"MostRequestedPriority"
,
Weight
:
2
},
},
},
},
}
registeredPredicates
:=
sets
.
NewString
(
factory
.
ListRegisteredFitPredicates
()
...
)
...
...
plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go
View file @
fed3f37e
...
...
@@ -158,6 +158,9 @@ func defaultPredicates() sets.String {
// Fit is determined by node disk pressure condition.
factory
.
RegisterFitPredicate
(
"CheckNodeDiskPressure"
,
predicates
.
CheckNodeDiskPressurePredicate
),
// Fit is determined by node disk pressure condition.
factory
.
RegisterFitPredicate
(
"CheckNodeInodePressure"
,
predicates
.
CheckNodeInodePressurePredicate
),
// Fit is determined by inter-pod affinity.
factory
.
RegisterFitPredicateFactory
(
"MatchInterPodAffinity"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment