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
55fa10c1
Commit
55fa10c1
authored
Jul 19, 2017
by
Klaus Ma
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Tainted node by condition.
parent
13b006ac
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
296 additions
and
19 deletions
+296
-19
core.go
cmd/kube-controller-manager/app/core.go
+1
-0
BUILD
pkg/controller/node/BUILD
+1
-0
node_controller.go
pkg/controller/node/node_controller.go
+67
-8
nodecontroller_test.go
pkg/controller/node/nodecontroller_test.go
+182
-0
controller_utils.go
pkg/controller/node/util/controller_utils.go
+14
-10
taints.go
pkg/util/taints/taints.go
+31
-1
No files found.
cmd/kube-controller-manager/app/core.go
View file @
55fa10c1
...
@@ -112,6 +112,7 @@ func startNodeController(ctx ControllerContext) (bool, error) {
...
@@ -112,6 +112,7 @@ func startNodeController(ctx ControllerContext) (bool, error) {
ipam
.
CIDRAllocatorType
(
ctx
.
Options
.
CIDRAllocatorType
),
ipam
.
CIDRAllocatorType
(
ctx
.
Options
.
CIDRAllocatorType
),
ctx
.
Options
.
EnableTaintManager
,
ctx
.
Options
.
EnableTaintManager
,
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
TaintBasedEvictions
),
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
TaintBasedEvictions
),
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
TaintNodesByCondition
),
)
)
if
err
!=
nil
{
if
err
!=
nil
{
return
true
,
err
return
true
,
err
...
...
pkg/controller/node/BUILD
View file @
55fa10c1
...
@@ -24,6 +24,7 @@ go_test(
...
@@ -24,6 +24,7 @@ go_test(
"//pkg/kubelet/apis:go_default_library",
"//pkg/kubelet/apis:go_default_library",
"//pkg/util/node:go_default_library",
"//pkg/util/node:go_default_library",
"//pkg/util/taints:go_default_library",
"//pkg/util/taints:go_default_library",
"//plugin/pkg/scheduler/algorithm:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
...
...
pkg/controller/node/node_controller.go
View file @
55fa10c1
...
@@ -76,6 +76,20 @@ var (
...
@@ -76,6 +76,20 @@ var (
Key
:
algorithm
.
TaintNodeNotReady
,
Key
:
algorithm
.
TaintNodeNotReady
,
Effect
:
v1
.
TaintEffectNoExecute
,
Effect
:
v1
.
TaintEffectNoExecute
,
}
}
nodeConditionToTaintKeyMap
=
map
[
v1
.
NodeConditionType
]
string
{
v1
.
NodeMemoryPressure
:
algorithm
.
TaintNodeMemoryPressure
,
v1
.
NodeOutOfDisk
:
algorithm
.
TaintNodeOutOfDisk
,
v1
.
NodeDiskPressure
:
algorithm
.
TaintNodeDiskPressure
,
v1
.
NodeNetworkUnavailable
:
algorithm
.
TaintNodeNetworkUnavailable
,
}
taintKeyToNodeConditionMap
=
map
[
string
]
v1
.
NodeConditionType
{
algorithm
.
TaintNodeNetworkUnavailable
:
v1
.
NodeNetworkUnavailable
,
algorithm
.
TaintNodeMemoryPressure
:
v1
.
NodeMemoryPressure
,
algorithm
.
TaintNodeOutOfDisk
:
v1
.
NodeOutOfDisk
,
algorithm
.
TaintNodeDiskPressure
:
v1
.
NodeDiskPressure
,
}
)
)
const
(
const
(
...
@@ -180,6 +194,10 @@ type NodeController struct {
...
@@ -180,6 +194,10 @@ type NodeController struct {
// if set to true NodeController will taint Nodes with 'TaintNodeNotReady' and 'TaintNodeUnreachable'
// if set to true NodeController will taint Nodes with 'TaintNodeNotReady' and 'TaintNodeUnreachable'
// taints instead of evicting Pods itself.
// taints instead of evicting Pods itself.
useTaintBasedEvictions
bool
useTaintBasedEvictions
bool
// if set to true, NodeController will taint Nodes based on its condition for 'NetworkUnavailable',
// 'MemoryPressure', 'OutOfDisk' and 'DiskPressure'.
taintNodeByCondition
bool
}
}
// NewNodeController returns a new node controller to sync instances from cloudprovider.
// NewNodeController returns a new node controller to sync instances from cloudprovider.
...
@@ -206,7 +224,9 @@ func NewNodeController(
...
@@ -206,7 +224,9 @@ func NewNodeController(
allocateNodeCIDRs
bool
,
allocateNodeCIDRs
bool
,
allocatorType
ipam
.
CIDRAllocatorType
,
allocatorType
ipam
.
CIDRAllocatorType
,
runTaintManager
bool
,
runTaintManager
bool
,
useTaintBasedEvictions
bool
)
(
*
NodeController
,
error
)
{
useTaintBasedEvictions
bool
,
taintNodeByCondition
bool
,
)
(
*
NodeController
,
error
)
{
eventBroadcaster
:=
record
.
NewBroadcaster
()
eventBroadcaster
:=
record
.
NewBroadcaster
()
recorder
:=
eventBroadcaster
.
NewRecorder
(
scheme
.
Scheme
,
v1
.
EventSource
{
Component
:
"controllermanager"
})
recorder
:=
eventBroadcaster
.
NewRecorder
(
scheme
.
Scheme
,
v1
.
EventSource
{
Component
:
"controllermanager"
})
eventBroadcaster
.
StartLogging
(
glog
.
Infof
)
eventBroadcaster
.
StartLogging
(
glog
.
Infof
)
...
@@ -387,6 +407,17 @@ func NewNodeController(
...
@@ -387,6 +407,17 @@ func NewNodeController(
nc
.
taintManager
=
scheduler
.
NewNoExecuteTaintManager
(
kubeClient
)
nc
.
taintManager
=
scheduler
.
NewNoExecuteTaintManager
(
kubeClient
)
}
}
if
nc
.
taintNodeByCondition
{
nodeInformer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
util
.
CreateAddNodeHandler
(
func
(
node
*
v1
.
Node
)
error
{
return
nc
.
doNoScheduleTaintingPass
(
node
)
}),
UpdateFunc
:
util
.
CreateUpdateNodeHandler
(
func
(
_
,
newNode
*
v1
.
Node
)
error
{
return
nc
.
doNoScheduleTaintingPass
(
newNode
)
}),
})
}
nc
.
nodeLister
=
nodeInformer
.
Lister
()
nc
.
nodeLister
=
nodeInformer
.
Lister
()
nc
.
nodeInformerSynced
=
nodeInformer
.
Informer
()
.
HasSynced
nc
.
nodeInformerSynced
=
nodeInformer
.
Informer
()
.
HasSynced
...
@@ -425,6 +456,34 @@ func (nc *NodeController) doEvictionPass() {
...
@@ -425,6 +456,34 @@ func (nc *NodeController) doEvictionPass() {
}
}
}
}
func
(
nc
*
NodeController
)
doNoScheduleTaintingPass
(
node
*
v1
.
Node
)
error
{
// Map node's condition to Taints.
taints
:=
[]
v1
.
Taint
{}
for
_
,
condition
:=
range
node
.
Status
.
Conditions
{
if
_
,
found
:=
nodeConditionToTaintKeyMap
[
condition
.
Type
];
found
{
if
condition
.
Status
==
v1
.
ConditionTrue
{
taints
=
append
(
taints
,
v1
.
Taint
{
Key
:
nodeConditionToTaintKeyMap
[
condition
.
Type
],
Effect
:
v1
.
TaintEffectNoSchedule
,
})
}
}
}
nodeTaints
:=
taintutils
.
TaintSetFilter
(
node
.
Spec
.
Taints
,
func
(
t
*
v1
.
Taint
)
bool
{
_
,
found
:=
taintKeyToNodeConditionMap
[
t
.
Key
]
return
found
})
taintsToAdd
,
taintsToDel
:=
taintutils
.
TaintSetDiff
(
taints
,
nodeTaints
)
// If nothing to add not delete, return true directly.
if
len
(
taintsToAdd
)
==
0
&&
len
(
taintsToDel
)
==
0
{
return
nil
}
if
!
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
taintsToAdd
,
taintsToDel
,
node
)
{
return
fmt
.
Errorf
(
"failed to swap taints of node %+v"
,
node
)
}
return
nil
}
func
(
nc
*
NodeController
)
doNoExecuteTaintingPass
()
{
func
(
nc
*
NodeController
)
doNoExecuteTaintingPass
()
{
nc
.
evictorLock
.
Lock
()
nc
.
evictorLock
.
Lock
()
defer
nc
.
evictorLock
.
Unlock
()
defer
nc
.
evictorLock
.
Unlock
()
...
@@ -459,7 +518,7 @@ func (nc *NodeController) doNoExecuteTaintingPass() {
...
@@ -459,7 +518,7 @@ func (nc *NodeController) doNoExecuteTaintingPass() {
return
true
,
0
return
true
,
0
}
}
return
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
&
taintToAdd
,
&
oppositeTaint
,
node
),
0
return
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
[]
*
v1
.
Taint
{
&
taintToAdd
},
[]
*
v1
.
Taint
{
&
oppositeTaint
}
,
node
),
0
})
})
}
}
}
}
...
@@ -542,7 +601,7 @@ func (nc *NodeController) monitorNodeStatus() error {
...
@@ -542,7 +601,7 @@ func (nc *NodeController) monitorNodeStatus() error {
nc
.
knownNodeSet
[
added
[
i
]
.
Name
]
=
added
[
i
]
nc
.
knownNodeSet
[
added
[
i
]
.
Name
]
=
added
[
i
]
nc
.
addPodEvictorForNewZone
(
added
[
i
])
nc
.
addPodEvictorForNewZone
(
added
[
i
])
if
nc
.
useTaintBasedEvictions
{
if
nc
.
useTaintBasedEvictions
{
nc
.
markNodeAs
Healthy
(
added
[
i
])
nc
.
markNodeAs
Reachable
(
added
[
i
])
}
else
{
}
else
{
nc
.
cancelPodEviction
(
added
[
i
])
nc
.
cancelPodEviction
(
added
[
i
])
}
}
...
@@ -596,7 +655,7 @@ func (nc *NodeController) monitorNodeStatus() error {
...
@@ -596,7 +655,7 @@ func (nc *NodeController) monitorNodeStatus() error {
// We want to update the taint straight away if Node is already tainted with the UnreachableTaint
// We want to update the taint straight away if Node is already tainted with the UnreachableTaint
if
taintutils
.
TaintExists
(
node
.
Spec
.
Taints
,
UnreachableTaintTemplate
)
{
if
taintutils
.
TaintExists
(
node
.
Spec
.
Taints
,
UnreachableTaintTemplate
)
{
taintToAdd
:=
*
NotReadyTaintTemplate
taintToAdd
:=
*
NotReadyTaintTemplate
if
!
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
&
taintToAdd
,
UnreachableTaintTemplate
,
node
)
{
if
!
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
[]
*
v1
.
Taint
{
&
taintToAdd
},
[]
*
v1
.
Taint
{
UnreachableTaintTemplate
}
,
node
)
{
glog
.
Errorf
(
"Failed to instantly swap UnreachableTaint to NotReadyTaint. Will try again in the next cycle."
)
glog
.
Errorf
(
"Failed to instantly swap UnreachableTaint to NotReadyTaint. Will try again in the next cycle."
)
}
}
}
else
if
nc
.
markNodeForTainting
(
node
)
{
}
else
if
nc
.
markNodeForTainting
(
node
)
{
...
@@ -623,7 +682,7 @@ func (nc *NodeController) monitorNodeStatus() error {
...
@@ -623,7 +682,7 @@ func (nc *NodeController) monitorNodeStatus() error {
// We want to update the taint straight away if Node is already tainted with the UnreachableTaint
// We want to update the taint straight away if Node is already tainted with the UnreachableTaint
if
taintutils
.
TaintExists
(
node
.
Spec
.
Taints
,
NotReadyTaintTemplate
)
{
if
taintutils
.
TaintExists
(
node
.
Spec
.
Taints
,
NotReadyTaintTemplate
)
{
taintToAdd
:=
*
UnreachableTaintTemplate
taintToAdd
:=
*
UnreachableTaintTemplate
if
!
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
&
taintToAdd
,
NotReadyTaintTemplate
,
node
)
{
if
!
util
.
SwapNodeControllerTaint
(
nc
.
kubeClient
,
[]
*
v1
.
Taint
{
&
taintToAdd
},
[]
*
v1
.
Taint
{
NotReadyTaintTemplate
}
,
node
)
{
glog
.
Errorf
(
"Failed to instantly swap UnreachableTaint to NotReadyTaint. Will try again in the next cycle."
)
glog
.
Errorf
(
"Failed to instantly swap UnreachableTaint to NotReadyTaint. Will try again in the next cycle."
)
}
}
}
else
if
nc
.
markNodeForTainting
(
node
)
{
}
else
if
nc
.
markNodeForTainting
(
node
)
{
...
@@ -647,7 +706,7 @@ func (nc *NodeController) monitorNodeStatus() error {
...
@@ -647,7 +706,7 @@ func (nc *NodeController) monitorNodeStatus() error {
}
}
if
observedReadyCondition
.
Status
==
v1
.
ConditionTrue
{
if
observedReadyCondition
.
Status
==
v1
.
ConditionTrue
{
if
nc
.
useTaintBasedEvictions
{
if
nc
.
useTaintBasedEvictions
{
removed
,
err
:=
nc
.
markNodeAs
Healthy
(
node
)
removed
,
err
:=
nc
.
markNodeAs
Reachable
(
node
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to remove taints from node %v. Will retry in next iteration."
,
node
.
Name
)
glog
.
Errorf
(
"Failed to remove taints from node %v. Will retry in next iteration."
,
node
.
Name
)
}
}
...
@@ -742,7 +801,7 @@ func (nc *NodeController) handleDisruption(zoneToNodeConditions map[string][]*v1
...
@@ -742,7 +801,7 @@ func (nc *NodeController) handleDisruption(zoneToNodeConditions map[string][]*v1
glog
.
V
(
0
)
.
Info
(
"NodeController detected that all Nodes are not-Ready. Entering master disruption mode."
)
glog
.
V
(
0
)
.
Info
(
"NodeController detected that all Nodes are not-Ready. Entering master disruption mode."
)
for
i
:=
range
nodes
{
for
i
:=
range
nodes
{
if
nc
.
useTaintBasedEvictions
{
if
nc
.
useTaintBasedEvictions
{
_
,
err
:=
nc
.
markNodeAs
Healthy
(
nodes
[
i
])
_
,
err
:=
nc
.
markNodeAs
Reachable
(
nodes
[
i
])
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to remove taints from Node %v"
,
nodes
[
i
]
.
Name
)
glog
.
Errorf
(
"Failed to remove taints from Node %v"
,
nodes
[
i
]
.
Name
)
}
}
...
@@ -1060,7 +1119,7 @@ func (nc *NodeController) markNodeForTainting(node *v1.Node) bool {
...
@@ -1060,7 +1119,7 @@ func (nc *NodeController) markNodeForTainting(node *v1.Node) bool {
return
nc
.
zoneNoExecuteTainer
[
utilnode
.
GetZoneKey
(
node
)]
.
Add
(
node
.
Name
,
string
(
node
.
UID
))
return
nc
.
zoneNoExecuteTainer
[
utilnode
.
GetZoneKey
(
node
)]
.
Add
(
node
.
Name
,
string
(
node
.
UID
))
}
}
func
(
nc
*
NodeController
)
markNodeAs
Healthy
(
node
*
v1
.
Node
)
(
bool
,
error
)
{
func
(
nc
*
NodeController
)
markNodeAs
Reachable
(
node
*
v1
.
Node
)
(
bool
,
error
)
{
nc
.
evictorLock
.
Lock
()
nc
.
evictorLock
.
Lock
()
defer
nc
.
evictorLock
.
Unlock
()
defer
nc
.
evictorLock
.
Unlock
()
err
:=
controller
.
RemoveTaintOffNode
(
nc
.
kubeClient
,
node
.
Name
,
node
,
UnreachableTaintTemplate
)
err
:=
controller
.
RemoveTaintOffNode
(
nc
.
kubeClient
,
node
.
Name
,
node
,
UnreachableTaintTemplate
)
...
...
pkg/controller/node/nodecontroller_test.go
View file @
55fa10c1
...
@@ -46,6 +46,7 @@ import (
...
@@ -46,6 +46,7 @@ import (
kubeletapis
"k8s.io/kubernetes/pkg/kubelet/apis"
kubeletapis
"k8s.io/kubernetes/pkg/kubelet/apis"
"k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/pkg/util/node"
taintutils
"k8s.io/kubernetes/pkg/util/taints"
taintutils
"k8s.io/kubernetes/pkg/util/taints"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
)
)
const
(
const
(
...
@@ -109,6 +110,7 @@ func NewNodeControllerFromClient(
...
@@ -109,6 +110,7 @@ func NewNodeControllerFromClient(
ipam
.
RangeAllocatorType
,
ipam
.
RangeAllocatorType
,
useTaints
,
useTaints
,
useTaints
,
useTaints
,
useTaints
,
)
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -2060,6 +2062,186 @@ func TestSwapUnreachableNotReadyTaints(t *testing.T) {
...
@@ -2060,6 +2062,186 @@ func TestSwapUnreachableNotReadyTaints(t *testing.T) {
}
}
}
}
func
TestTaintsNodeByCondition
(
t
*
testing
.
T
)
{
fakeNow
:=
metav1
.
Date
(
2017
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
)
evictionTimeout
:=
10
*
time
.
Minute
fakeNodeHandler
:=
&
testutil
.
FakeNodeHandler
{
Existing
:
[]
*
v1
.
Node
{
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"node0"
,
CreationTimestamp
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
Labels
:
map
[
string
]
string
{
kubeletapis
.
LabelZoneRegion
:
"region1"
,
kubeletapis
.
LabelZoneFailureDomain
:
"zone1"
,
},
},
Status
:
v1
.
NodeStatus
{
Conditions
:
[]
v1
.
NodeCondition
{
{
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
},
},
},
},
Clientset
:
fake
.
NewSimpleClientset
(
&
v1
.
PodList
{
Items
:
[]
v1
.
Pod
{
*
testutil
.
NewPod
(
"pod0"
,
"node0"
)}}),
}
nodeController
,
_
:=
NewNodeControllerFromClient
(
nil
,
fakeNodeHandler
,
evictionTimeout
,
testRateLimiterQPS
,
testRateLimiterQPS
,
testLargeClusterThreshold
,
testUnhealthyThreshold
,
testNodeMonitorGracePeriod
,
testNodeStartupGracePeriod
,
testNodeMonitorPeriod
,
nil
,
nil
,
0
,
false
,
true
)
nodeController
.
now
=
func
()
metav1
.
Time
{
return
fakeNow
}
nodeController
.
recorder
=
testutil
.
NewFakeRecorder
()
outOfDiskTaint
:=
&
v1
.
Taint
{
Key
:
algorithm
.
TaintNodeOutOfDisk
,
Effect
:
v1
.
TaintEffectNoSchedule
,
}
networkUnavailableTaint
:=
&
v1
.
Taint
{
Key
:
algorithm
.
TaintNodeNetworkUnavailable
,
Effect
:
v1
.
TaintEffectNoSchedule
,
}
tests
:=
[]
struct
{
Name
string
Node
*
v1
.
Node
ExpectedTaints
[]
*
v1
.
Taint
}{
{
Name
:
"NetworkUnavailable is true"
,
Node
:
&
v1
.
Node
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"node0"
,
CreationTimestamp
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
Labels
:
map
[
string
]
string
{
kubeletapis
.
LabelZoneRegion
:
"region1"
,
kubeletapis
.
LabelZoneFailureDomain
:
"zone1"
,
},
},
Status
:
v1
.
NodeStatus
{
Conditions
:
[]
v1
.
NodeCondition
{
{
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
v1
.
NodeNetworkUnavailable
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
},
},
},
ExpectedTaints
:
[]
*
v1
.
Taint
{
networkUnavailableTaint
},
},
{
Name
:
"NetworkUnavailable and OutOfDisk are true"
,
Node
:
&
v1
.
Node
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"node0"
,
CreationTimestamp
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
Labels
:
map
[
string
]
string
{
kubeletapis
.
LabelZoneRegion
:
"region1"
,
kubeletapis
.
LabelZoneFailureDomain
:
"zone1"
,
},
},
Status
:
v1
.
NodeStatus
{
Conditions
:
[]
v1
.
NodeCondition
{
{
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
v1
.
NodeNetworkUnavailable
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
v1
.
NodeOutOfDisk
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
},
},
},
ExpectedTaints
:
[]
*
v1
.
Taint
{
networkUnavailableTaint
,
outOfDiskTaint
},
},
{
Name
:
"NetworkUnavailable is true, OutOfDisk is unknown"
,
Node
:
&
v1
.
Node
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"node0"
,
CreationTimestamp
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
Labels
:
map
[
string
]
string
{
kubeletapis
.
LabelZoneRegion
:
"region1"
,
kubeletapis
.
LabelZoneFailureDomain
:
"zone1"
,
},
},
Status
:
v1
.
NodeStatus
{
Conditions
:
[]
v1
.
NodeCondition
{
{
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
v1
.
NodeNetworkUnavailable
,
Status
:
v1
.
ConditionTrue
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
v1
.
NodeOutOfDisk
,
Status
:
v1
.
ConditionUnknown
,
LastHeartbeatTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2015
,
1
,
1
,
12
,
0
,
0
,
0
,
time
.
UTC
),
},
},
},
},
ExpectedTaints
:
[]
*
v1
.
Taint
{
networkUnavailableTaint
},
},
}
for
_
,
test
:=
range
tests
{
fakeNodeHandler
.
Update
(
test
.
Node
)
if
err
:=
syncNodeStore
(
nodeController
,
fakeNodeHandler
);
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
nodeController
.
doNoScheduleTaintingPass
(
test
.
Node
)
if
err
:=
syncNodeStore
(
nodeController
,
fakeNodeHandler
);
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
node0
,
err
:=
nodeController
.
nodeLister
.
Get
(
"node0"
)
if
err
!=
nil
{
t
.
Errorf
(
"Can't get current node0..."
)
return
}
if
len
(
node0
.
Spec
.
Taints
)
!=
len
(
test
.
ExpectedTaints
)
{
t
.
Errorf
(
"%s: Unexpected number of taints: expected %d, got %d"
,
test
.
Name
,
len
(
test
.
ExpectedTaints
),
len
(
node0
.
Spec
.
Taints
))
}
for
_
,
taint
:=
range
test
.
ExpectedTaints
{
if
!
taintutils
.
TaintExists
(
node0
.
Spec
.
Taints
,
taint
)
{
t
.
Errorf
(
"%s: Can't find taint %v in %v"
,
test
.
Name
,
taint
,
node0
.
Spec
.
Taints
)
}
}
}
}
func
TestNodeEventGeneration
(
t
*
testing
.
T
)
{
func
TestNodeEventGeneration
(
t
*
testing
.
T
)
{
fakeNow
:=
metav1
.
Date
(
2016
,
9
,
10
,
12
,
0
,
0
,
0
,
time
.
UTC
)
fakeNow
:=
metav1
.
Date
(
2016
,
9
,
10
,
12
,
0
,
0
,
0
,
time
.
UTC
)
fakeNodeHandler
:=
&
testutil
.
FakeNodeHandler
{
fakeNodeHandler
:=
&
testutil
.
FakeNodeHandler
{
...
...
pkg/controller/node/util/controller_utils.go
View file @
55fa10c1
...
@@ -256,31 +256,35 @@ func RecordNodeStatusChange(recorder record.EventRecorder, node *v1.Node, newSta
...
@@ -256,31 +256,35 @@ func RecordNodeStatusChange(recorder record.EventRecorder, node *v1.Node, newSta
// SwapNodeControllerTaint returns true in case of success and false
// SwapNodeControllerTaint returns true in case of success and false
// otherwise.
// otherwise.
func
SwapNodeControllerTaint
(
kubeClient
clientset
.
Interface
,
taintToAdd
,
taintToRemove
*
v1
.
Taint
,
node
*
v1
.
Node
)
bool
{
func
SwapNodeControllerTaint
(
kubeClient
clientset
.
Interface
,
taintsToAdd
,
taintsToRemove
[]
*
v1
.
Taint
,
node
*
v1
.
Node
)
bool
{
taintToAdd
.
TimeAdded
=
metav1
.
Now
()
for
_
,
taintToAdd
:=
range
taintsToAdd
{
err
:=
controller
.
AddOrUpdateTaintOnNode
(
kubeClient
,
node
.
Name
,
taintToAdd
)
taintToAdd
.
TimeAdded
=
metav1
.
Now
()
}
err
:=
controller
.
AddOrUpdateTaintOnNode
(
kubeClient
,
node
.
Name
,
taintsToAdd
...
)
if
err
!=
nil
{
if
err
!=
nil
{
utilruntime
.
HandleError
(
utilruntime
.
HandleError
(
fmt
.
Errorf
(
fmt
.
Errorf
(
"unable to taint %v unresponsive Node %q: %v"
,
"unable to taint %
+
v unresponsive Node %q: %v"
,
taint
ToAdd
.
Key
,
taint
sToAdd
,
node
.
Name
,
node
.
Name
,
err
))
err
))
return
false
return
false
}
}
glog
.
V
(
4
)
.
Infof
(
"Added %
v Taint to Node %v"
,
taint
ToAdd
,
node
.
Name
)
glog
.
V
(
4
)
.
Infof
(
"Added %
+v Taint to Node %v"
,
taints
ToAdd
,
node
.
Name
)
err
=
controller
.
RemoveTaintOffNode
(
kubeClient
,
node
.
Name
,
node
,
taint
ToRemove
)
err
=
controller
.
RemoveTaintOffNode
(
kubeClient
,
node
.
Name
,
node
,
taint
sToRemove
...
)
if
err
!=
nil
{
if
err
!=
nil
{
utilruntime
.
HandleError
(
utilruntime
.
HandleError
(
fmt
.
Errorf
(
fmt
.
Errorf
(
"unable to remove %v unneeded taint from unresponsive Node %q: %v"
,
"unable to remove %
+
v unneeded taint from unresponsive Node %q: %v"
,
taint
ToRemove
.
Key
,
taint
sToRemove
,
node
.
Name
,
node
.
Name
,
err
))
err
))
return
false
return
false
}
}
glog
.
V
(
4
)
.
Infof
(
"Made sure that Node %v has no %v Taint"
,
node
.
Name
,
taintToRemove
)
glog
.
V
(
4
)
.
Infof
(
"Made sure that Node %+v has no %v Taint"
,
node
.
Name
,
taintsToRemove
)
return
true
return
true
}
}
...
...
pkg/util/taints/taints.go
View file @
55fa10c1
...
@@ -19,11 +19,11 @@ package taints
...
@@ -19,11 +19,11 @@ package taints
import
(
import
(
"fmt"
"fmt"
"k8s.io/apimachinery/pkg/util/sets"
"strings"
"strings"
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
utilerrors
"k8s.io/apimachinery/pkg/util/errors"
utilerrors
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/helper"
"k8s.io/kubernetes/pkg/api/helper"
...
@@ -299,3 +299,33 @@ func TaintExists(taints []v1.Taint, taintToFind *v1.Taint) bool {
...
@@ -299,3 +299,33 @@ func TaintExists(taints []v1.Taint, taintToFind *v1.Taint) bool {
}
}
return
false
return
false
}
}
func
TaintSetDiff
(
t1
,
t2
[]
v1
.
Taint
)
(
taintsToAdd
[]
*
v1
.
Taint
,
taintsToRemove
[]
*
v1
.
Taint
)
{
for
_
,
taint
:=
range
t1
{
if
!
TaintExists
(
t2
,
&
taint
)
{
t
:=
taint
taintsToAdd
=
append
(
taintsToAdd
,
&
t
)
}
}
for
_
,
taint
:=
range
t2
{
if
!
TaintExists
(
t1
,
&
taint
)
{
t
:=
taint
taintsToRemove
=
append
(
taintsToRemove
,
&
t
)
}
}
return
}
func
TaintSetFilter
(
taints
[]
v1
.
Taint
,
fn
func
(
*
v1
.
Taint
)
bool
)
[]
v1
.
Taint
{
res
:=
[]
v1
.
Taint
{}
for
_
,
taint
:=
range
taints
{
if
fn
(
&
taint
)
{
res
=
append
(
res
,
taint
)
}
}
return
res
}
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