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
ce9f93df
Commit
ce9f93df
authored
Jan 30, 2016
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #20061 from mikedanese/copypaste
Auto commit by PR queue bot
parents
1f8bdd27
e2fecf36
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
166 additions
and
18 deletions
+166
-18
controller.go
pkg/controller/daemon/controller.go
+47
-14
controller_test.go
pkg/controller/daemon/controller_test.go
+115
-4
kubelet.go
pkg/kubelet/kubelet.go
+4
-0
No files found.
pkg/controller/daemon/controller.go
View file @
ce9f93df
...
@@ -19,10 +19,12 @@ package daemon
...
@@ -19,10 +19,12 @@ package daemon
import
(
import
(
"reflect"
"reflect"
"sort"
"sort"
"sync"
"time"
"time"
"github.com/golang/glog"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/record"
"k8s.io/kubernetes/pkg/client/record"
...
@@ -32,9 +34,11 @@ import (
...
@@ -32,9 +34,11 @@ import (
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/util/workqueue"
"k8s.io/kubernetes/pkg/util/workqueue"
"k8s.io/kubernetes/pkg/watch"
"k8s.io/kubernetes/pkg/watch"
"
sync
"
"
k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates
"
)
)
const
(
const
(
...
@@ -325,7 +329,7 @@ func (dsc *DaemonSetsController) addNode(obj interface{}) {
...
@@ -325,7 +329,7 @@ func (dsc *DaemonSetsController) addNode(obj interface{}) {
node
:=
obj
.
(
*
api
.
Node
)
node
:=
obj
.
(
*
api
.
Node
)
for
i
:=
range
dsList
.
Items
{
for
i
:=
range
dsList
.
Items
{
ds
:=
&
dsList
.
Items
[
i
]
ds
:=
&
dsList
.
Items
[
i
]
shouldEnqueue
:=
nodeShouldRunDaemonPod
(
node
,
ds
)
shouldEnqueue
:=
dsc
.
nodeShouldRunDaemonPod
(
node
,
ds
)
if
shouldEnqueue
{
if
shouldEnqueue
{
dsc
.
enqueueDaemonSet
(
ds
)
dsc
.
enqueueDaemonSet
(
ds
)
}
}
...
@@ -346,7 +350,7 @@ func (dsc *DaemonSetsController) updateNode(old, cur interface{}) {
...
@@ -346,7 +350,7 @@ func (dsc *DaemonSetsController) updateNode(old, cur interface{}) {
}
}
for
i
:=
range
dsList
.
Items
{
for
i
:=
range
dsList
.
Items
{
ds
:=
&
dsList
.
Items
[
i
]
ds
:=
&
dsList
.
Items
[
i
]
shouldEnqueue
:=
(
nodeShouldRunDaemonPod
(
oldNode
,
ds
)
!=
nodeShouldRunDaemonPod
(
curNode
,
ds
))
shouldEnqueue
:=
(
dsc
.
nodeShouldRunDaemonPod
(
oldNode
,
ds
)
!=
dsc
.
nodeShouldRunDaemonPod
(
curNode
,
ds
))
if
shouldEnqueue
{
if
shouldEnqueue
{
dsc
.
enqueueDaemonSet
(
ds
)
dsc
.
enqueueDaemonSet
(
ds
)
}
}
...
@@ -387,7 +391,7 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) {
...
@@ -387,7 +391,7 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) {
}
}
var
nodesNeedingDaemonPods
,
podsToDelete
[]
string
var
nodesNeedingDaemonPods
,
podsToDelete
[]
string
for
_
,
node
:=
range
nodeList
.
Items
{
for
_
,
node
:=
range
nodeList
.
Items
{
shouldRun
:=
nodeShouldRunDaemonPod
(
&
node
,
ds
)
shouldRun
:=
dsc
.
nodeShouldRunDaemonPod
(
&
node
,
ds
)
daemonPods
,
isRunning
:=
nodeToDaemonPods
[
node
.
Name
]
daemonPods
,
isRunning
:=
nodeToDaemonPods
[
node
.
Name
]
...
@@ -498,7 +502,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet)
...
@@ -498,7 +502,7 @@ func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet)
var
desiredNumberScheduled
,
currentNumberScheduled
,
numberMisscheduled
int
var
desiredNumberScheduled
,
currentNumberScheduled
,
numberMisscheduled
int
for
_
,
node
:=
range
nodeList
.
Items
{
for
_
,
node
:=
range
nodeList
.
Items
{
shouldRun
:=
nodeShouldRunDaemonPod
(
&
node
,
ds
)
shouldRun
:=
dsc
.
nodeShouldRunDaemonPod
(
&
node
,
ds
)
numDaemonPods
:=
len
(
nodeToDaemonPods
[
node
.
Name
])
numDaemonPods
:=
len
(
nodeToDaemonPods
[
node
.
Name
])
...
@@ -563,21 +567,50 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error {
...
@@ -563,21 +567,50 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error {
return
nil
return
nil
}
}
func
nodeShouldRunDaemonPod
(
node
*
api
.
Node
,
ds
*
extensions
.
DaemonSet
)
bool
{
func
(
dsc
*
DaemonSetsController
)
nodeShouldRunDaemonPod
(
node
*
api
.
Node
,
ds
*
extensions
.
DaemonSet
)
bool
{
// Check if the node satisfies the daemon set's node selector.
// Check if the node satisfies the daemon set's node selector.
nodeSelector
:=
labels
.
Set
(
ds
.
Spec
.
Template
.
Spec
.
NodeSelector
)
.
AsSelector
()
nodeSelector
:=
labels
.
Set
(
ds
.
Spec
.
Template
.
Spec
.
NodeSelector
)
.
AsSelector
()
shouldRun
:=
nodeSelector
.
Matches
(
labels
.
Set
(
node
.
Labels
))
if
!
nodeSelector
.
Matches
(
labels
.
Set
(
node
.
Labels
))
{
return
false
}
// If the daemon set specifies a node name, check that it matches with node.Name.
// If the daemon set specifies a node name, check that it matches with node.Name.
shouldRun
=
shouldRun
&&
(
ds
.
Spec
.
Template
.
Spec
.
NodeName
==
""
||
ds
.
Spec
.
Template
.
Spec
.
NodeName
==
node
.
Name
)
if
!
(
ds
.
Spec
.
Template
.
Spec
.
NodeName
==
""
||
ds
.
Spec
.
Template
.
Spec
.
NodeName
==
node
.
Name
)
{
return
false
}
// If the node is not ready, don't run on it.
// If the node is not ready, don't run on it.
// TODO(mikedanese): remove this once daemonpods forgive nodes
// TODO(mikedanese): remove this once daemonpods forgive nodes
shouldRun
=
shouldRun
&&
api
.
IsNodeReady
(
node
)
if
!
api
.
IsNodeReady
(
node
)
{
return
false
}
for
_
,
c
:=
range
node
.
Status
.
Conditions
{
if
c
.
Type
==
api
.
NodeOutOfDisk
&&
c
.
Status
==
api
.
ConditionTrue
{
return
false
}
}
newPod
:=
&
api
.
Pod
{
Spec
:
ds
.
Spec
.
Template
.
Spec
}
newPod
.
Spec
.
NodeName
=
node
.
Name
pods
:=
[]
*
api
.
Pod
{
newPod
}
// If the node is unschedulable, don't run it
for
_
,
m
:=
range
dsc
.
podStore
.
Store
.
List
()
{
// TODO(mikedanese): remove this once we have the right node admitance levels.
pod
:=
m
.
(
*
api
.
Pod
)
// See https://github.com/kubernetes/kubernetes/issues/17297#issuecomment-156857375.
if
pod
.
Spec
.
NodeName
!=
node
.
Name
{
shouldRun
=
shouldRun
&&
!
node
.
Spec
.
Unschedulable
continue
return
shouldRun
}
pods
=
append
(
pods
,
pod
)
}
_
,
notFittingCPU
,
notFittingMemory
:=
predicates
.
CheckPodsExceedingFreeResources
(
pods
,
node
.
Status
.
Allocatable
)
if
len
(
notFittingCPU
)
+
len
(
notFittingMemory
)
!=
0
{
return
false
}
ports
:=
sets
.
String
{}
for
_
,
pod
:=
range
pods
{
if
errs
:=
validation
.
AccumulateUniqueHostPorts
(
pod
.
Spec
.
Containers
,
&
ports
,
field
.
NewPath
(
"spec"
,
"containers"
));
len
(
errs
)
>
0
{
return
false
}
}
return
true
}
}
// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker.
// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker.
...
...
pkg/controller/daemon/controller_test.go
View file @
ce9f93df
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"testing"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/extensions"
...
@@ -200,17 +201,127 @@ func TestNotReadNodeDaemonDoesNotLaunchPod(t *testing.T) {
...
@@ -200,17 +201,127 @@ func TestNotReadNodeDaemonDoesNotLaunchPod(t *testing.T) {
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
0
,
0
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
0
,
0
)
}
}
// DaemonSets should not place onto
Unschedulable
nodes
// DaemonSets should not place onto
OutOfDisk
nodes
func
Test
Unschedulable
NodeDaemonDoesNotLaunchPod
(
t
*
testing
.
T
)
{
func
Test
OutOfDisk
NodeDaemonDoesNotLaunchPod
(
t
*
testing
.
T
)
{
manager
,
podControl
:=
newTestController
()
manager
,
podControl
:=
newTestController
()
node
:=
newNode
(
"not-ready"
,
nil
)
node
:=
newNode
(
"not-enough-disk"
,
nil
)
node
.
Spec
.
Unschedulable
=
true
node
.
Status
.
Conditions
=
[]
api
.
NodeCondition
{{
Type
:
api
.
NodeOutOfDisk
,
Status
:
api
.
ConditionTrue
}}
manager
.
nodeStore
.
Add
(
node
)
ds
:=
newDaemonSet
(
"foo"
)
manager
.
dsStore
.
Add
(
ds
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
0
,
0
)
}
// DaemonSets should not place onto nodes with insufficient free resource
func
TestInsufficentCapacityNodeDaemonDoesNotLaunchPod
(
t
*
testing
.
T
)
{
podSpec
:=
api
.
PodSpec
{
NodeName
:
"too-much-mem"
,
Containers
:
[]
api
.
Container
{{
Resources
:
api
.
ResourceRequirements
{
Requests
:
api
.
ResourceList
{
api
.
ResourceMemory
:
resource
.
MustParse
(
"75M"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"75m"
),
},
},
}},
}
manager
,
podControl
:=
newTestController
()
node
:=
newNode
(
"too-much-mem"
,
nil
)
node
.
Status
.
Allocatable
=
api
.
ResourceList
{
api
.
ResourceMemory
:
resource
.
MustParse
(
"100M"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
),
}
manager
.
nodeStore
.
Add
(
node
)
manager
.
podStore
.
Add
(
&
api
.
Pod
{
Spec
:
podSpec
,
})
ds
:=
newDaemonSet
(
"foo"
)
ds
.
Spec
.
Template
.
Spec
=
podSpec
manager
.
dsStore
.
Add
(
ds
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
0
,
0
)
}
// DaemonSets should place onto nodes with sufficient free resource
func
TestSufficentCapacityNodeDaemonLaunchesPod
(
t
*
testing
.
T
)
{
podSpec
:=
api
.
PodSpec
{
NodeName
:
"not-too-much-mem"
,
Containers
:
[]
api
.
Container
{{
Resources
:
api
.
ResourceRequirements
{
Requests
:
api
.
ResourceList
{
api
.
ResourceMemory
:
resource
.
MustParse
(
"75M"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"75m"
),
},
},
}},
}
manager
,
podControl
:=
newTestController
()
node
:=
newNode
(
"not-too-much-mem"
,
nil
)
node
.
Status
.
Allocatable
=
api
.
ResourceList
{
api
.
ResourceMemory
:
resource
.
MustParse
(
"200M"
),
api
.
ResourceCPU
:
resource
.
MustParse
(
"200m"
),
}
manager
.
nodeStore
.
Add
(
node
)
manager
.
podStore
.
Add
(
&
api
.
Pod
{
Spec
:
podSpec
,
})
ds
:=
newDaemonSet
(
"foo"
)
ds
.
Spec
.
Template
.
Spec
=
podSpec
manager
.
dsStore
.
Add
(
ds
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
1
,
0
)
}
// DaemonSets should not place onto nodes that would cause port conflicts
func
TestPortConflictNodeDaemonDoesNotLaunchPod
(
t
*
testing
.
T
)
{
podSpec
:=
api
.
PodSpec
{
NodeName
:
"port-conflict"
,
Containers
:
[]
api
.
Container
{{
Ports
:
[]
api
.
ContainerPort
{{
HostPort
:
666
,
}},
}},
}
manager
,
podControl
:=
newTestController
()
node
:=
newNode
(
"port-conflict"
,
nil
)
manager
.
nodeStore
.
Add
(
node
)
manager
.
nodeStore
.
Add
(
node
)
manager
.
podStore
.
Add
(
&
api
.
Pod
{
Spec
:
podSpec
,
})
ds
:=
newDaemonSet
(
"foo"
)
ds
:=
newDaemonSet
(
"foo"
)
ds
.
Spec
.
Template
.
Spec
=
podSpec
manager
.
dsStore
.
Add
(
ds
)
manager
.
dsStore
.
Add
(
ds
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
0
,
0
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
0
,
0
)
}
}
// DaemonSets should place onto nodes that would not cause port conflicts
func
TestNoPortConflictNodeDaemonLaunchesPod
(
t
*
testing
.
T
)
{
podSpec1
:=
api
.
PodSpec
{
NodeName
:
"no-port-conflict"
,
Containers
:
[]
api
.
Container
{{
Ports
:
[]
api
.
ContainerPort
{{
HostPort
:
6661
,
}},
}},
}
podSpec2
:=
api
.
PodSpec
{
NodeName
:
"no-port-conflict"
,
Containers
:
[]
api
.
Container
{{
Ports
:
[]
api
.
ContainerPort
{{
HostPort
:
6662
,
}},
}},
}
manager
,
podControl
:=
newTestController
()
node
:=
newNode
(
"no-port-conflict"
,
nil
)
manager
.
nodeStore
.
Add
(
node
)
manager
.
podStore
.
Add
(
&
api
.
Pod
{
Spec
:
podSpec1
,
})
ds
:=
newDaemonSet
(
"foo"
)
ds
.
Spec
.
Template
.
Spec
=
podSpec2
manager
.
dsStore
.
Add
(
ds
)
syncAndValidateDaemonSets
(
t
,
manager
,
ds
,
podControl
,
1
,
0
)
}
// Controller should not create pods on nodes which have daemon pods, and should remove excess pods from nodes that have extra pods.
// Controller should not create pods on nodes which have daemon pods, and should remove excess pods from nodes that have extra pods.
func
TestDealsWithExistingPods
(
t
*
testing
.
T
)
{
func
TestDealsWithExistingPods
(
t
*
testing
.
T
)
{
manager
,
podControl
:=
newTestController
()
manager
,
podControl
:=
newTestController
()
...
...
pkg/kubelet/kubelet.go
View file @
ce9f93df
...
@@ -2193,6 +2193,10 @@ func (kl *Kubelet) rejectPod(pod *api.Pod, reason, message string) {
...
@@ -2193,6 +2193,10 @@ func (kl *Kubelet) rejectPod(pod *api.Pod, reason, message string) {
// new pod. The function returns a boolean value indicating whether the pod
// new pod. The function returns a boolean value indicating whether the pod
// can be admitted, a brief single-word reason and a message explaining why
// can be admitted, a brief single-word reason and a message explaining why
// the pod cannot be admitted.
// the pod cannot be admitted.
//
// This needs to be kept in sync with the scheduler's and daemonset's fit predicates,
// otherwise there will inevitably be pod delete create loops. This will be fixed
// once we can extract these predicates into a common library. (#12744)
func
(
kl
*
Kubelet
)
canAdmitPod
(
pods
[]
*
api
.
Pod
,
pod
*
api
.
Pod
)
(
bool
,
string
,
string
)
{
func
(
kl
*
Kubelet
)
canAdmitPod
(
pods
[]
*
api
.
Pod
,
pod
*
api
.
Pod
)
(
bool
,
string
,
string
)
{
if
hasHostPortConflicts
(
pods
)
{
if
hasHostPortConflicts
(
pods
)
{
return
false
,
"HostPortConflict"
,
"cannot start the pod due to host port conflict."
return
false
,
"HostPortConflict"
,
"cannot start the pod due to host port conflict."
...
...
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