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
73d105e2
Commit
73d105e2
authored
Aug 21, 2015
by
Zach Loafman
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12959 from smarterclayton/handle_pods_in_kubelet
Support graceful termination in the Kubelet (5/7)
parents
cc172af2
f5c4a3e7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
164 additions
and
34 deletions
+164
-34
config.go
pkg/kubelet/config/config.go
+19
-4
fake_runtime.go
pkg/kubelet/container/fake_runtime.go
+3
-3
runtime.go
pkg/kubelet/container/runtime.go
+2
-2
manager.go
pkg/kubelet/dockertools/manager.go
+0
-0
manager_test.go
pkg/kubelet/dockertools/manager_test.go
+11
-11
kubelet.go
pkg/kubelet/kubelet.go
+37
-6
mirror_client.go
pkg/kubelet/mirror_client.go
+1
-1
rkt.go
pkg/kubelet/rkt/rkt.go
+4
-4
status_manager.go
pkg/kubelet/status_manager.go
+58
-3
status_manager_test.go
pkg/kubelet/status_manager_test.go
+29
-0
No files found.
pkg/kubelet/config/config.go
View file @
73d105e2
...
@@ -217,9 +217,8 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
...
@@ -217,9 +217,8 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
for
_
,
ref
:=
range
filtered
{
for
_
,
ref
:=
range
filtered
{
name
:=
kubecontainer
.
GetPodFullName
(
ref
)
name
:=
kubecontainer
.
GetPodFullName
(
ref
)
if
existing
,
found
:=
pods
[
name
];
found
{
if
existing
,
found
:=
pods
[
name
];
found
{
if
!
reflect
.
DeepEqual
(
existing
.
Spec
,
ref
.
Spec
)
{
if
checkAndUpdatePod
(
existing
,
ref
)
{
// this is an update
// this is an update
existing
.
Spec
=
ref
.
Spec
updates
.
Pods
=
append
(
updates
.
Pods
,
existing
)
updates
.
Pods
=
append
(
updates
.
Pods
,
existing
)
continue
continue
}
}
...
@@ -261,9 +260,8 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
...
@@ -261,9 +260,8 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
name
:=
kubecontainer
.
GetPodFullName
(
ref
)
name
:=
kubecontainer
.
GetPodFullName
(
ref
)
if
existing
,
found
:=
oldPods
[
name
];
found
{
if
existing
,
found
:=
oldPods
[
name
];
found
{
pods
[
name
]
=
existing
pods
[
name
]
=
existing
if
!
reflect
.
DeepEqual
(
existing
.
Spec
,
ref
.
Spec
)
{
if
checkAndUpdatePod
(
existing
,
ref
)
{
// this is an update
// this is an update
existing
.
Spec
=
ref
.
Spec
updates
.
Pods
=
append
(
updates
.
Pods
,
existing
)
updates
.
Pods
=
append
(
updates
.
Pods
,
existing
)
continue
continue
}
}
...
@@ -335,6 +333,23 @@ func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventReco
...
@@ -335,6 +333,23 @@ func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventReco
return
return
}
}
// checkAndUpdatePod updates existing if ref makes a meaningful change and returns true, or
// returns false if there was no update.
func
checkAndUpdatePod
(
existing
,
ref
*
api
.
Pod
)
bool
{
// TODO: it would be better to update the whole object and only preserve certain things
// like the source annotation or the UID (to ensure safety)
if
reflect
.
DeepEqual
(
existing
.
Spec
,
ref
.
Spec
)
&&
reflect
.
DeepEqual
(
existing
.
DeletionTimestamp
,
ref
.
DeletionTimestamp
)
&&
reflect
.
DeepEqual
(
existing
.
DeletionGracePeriodSeconds
,
ref
.
DeletionGracePeriodSeconds
)
{
return
false
}
// this is an update
existing
.
Spec
=
ref
.
Spec
existing
.
DeletionTimestamp
=
ref
.
DeletionTimestamp
existing
.
DeletionGracePeriodSeconds
=
ref
.
DeletionGracePeriodSeconds
return
true
}
// Sync sends a copy of the current state through the update channel.
// Sync sends a copy of the current state through the update channel.
func
(
s
*
podStorage
)
Sync
()
{
func
(
s
*
podStorage
)
Sync
()
{
s
.
updateLock
.
Lock
()
s
.
updateLock
.
Lock
()
...
...
pkg/kubelet/container/fake_runtime.go
View file @
73d105e2
...
@@ -163,13 +163,13 @@ func (f *FakeRuntime) SyncPod(pod *api.Pod, _ Pod, _ api.PodStatus, _ []api.Secr
...
@@ -163,13 +163,13 @@ func (f *FakeRuntime) SyncPod(pod *api.Pod, _ Pod, _ api.PodStatus, _ []api.Secr
return
f
.
Err
return
f
.
Err
}
}
func
(
f
*
FakeRuntime
)
KillPod
(
pod
Pod
)
error
{
func
(
f
*
FakeRuntime
)
KillPod
(
pod
*
api
.
Pod
,
runningPod
Pod
)
error
{
f
.
Lock
()
f
.
Lock
()
defer
f
.
Unlock
()
defer
f
.
Unlock
()
f
.
CalledFunctions
=
append
(
f
.
CalledFunctions
,
"KillPod"
)
f
.
CalledFunctions
=
append
(
f
.
CalledFunctions
,
"KillPod"
)
f
.
KilledPods
=
append
(
f
.
KilledPods
,
string
(
p
od
.
ID
))
f
.
KilledPods
=
append
(
f
.
KilledPods
,
string
(
runningP
od
.
ID
))
for
_
,
c
:=
range
p
od
.
Containers
{
for
_
,
c
:=
range
runningP
od
.
Containers
{
f
.
KilledContainers
=
append
(
f
.
KilledContainers
,
c
.
Name
)
f
.
KilledContainers
=
append
(
f
.
KilledContainers
,
c
.
Name
)
}
}
return
f
.
Err
return
f
.
Err
...
...
pkg/kubelet/container/runtime.go
View file @
73d105e2
...
@@ -54,8 +54,8 @@ type Runtime interface {
...
@@ -54,8 +54,8 @@ type Runtime interface {
GetPods
(
all
bool
)
([]
*
Pod
,
error
)
GetPods
(
all
bool
)
([]
*
Pod
,
error
)
// Syncs the running pod into the desired pod.
// Syncs the running pod into the desired pod.
SyncPod
(
pod
*
api
.
Pod
,
runningPod
Pod
,
podStatus
api
.
PodStatus
,
pullSecrets
[]
api
.
Secret
)
error
SyncPod
(
pod
*
api
.
Pod
,
runningPod
Pod
,
podStatus
api
.
PodStatus
,
pullSecrets
[]
api
.
Secret
)
error
// KillPod kills all the containers of a pod.
// KillPod kills all the containers of a pod.
Pod may be nil, running pod must not be.
KillPod
(
pod
Pod
)
error
KillPod
(
pod
*
api
.
Pod
,
runningPod
Pod
)
error
// GetPodStatus retrieves the status of the pod, including the information of
// GetPodStatus retrieves the status of the pod, including the information of
// all containers in the pod. Clients of this interface assume the containers
// all containers in the pod. Clients of this interface assume the containers
// statuses in a pod always have a deterministic ordering (eg: sorted by name).
// statuses in a pod always have a deterministic ordering (eg: sorted by name).
...
...
pkg/kubelet/dockertools/manager.go
View file @
73d105e2
This diff is collapsed.
Click to expand it.
pkg/kubelet/dockertools/manager_test.go
View file @
73d105e2
...
@@ -405,7 +405,7 @@ func TestKillContainerInPod(t *testing.T) {
...
@@ -405,7 +405,7 @@ func TestKillContainerInPod(t *testing.T) {
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
}
}
if
err
:=
manager
.
KillContainerInPod
(
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
if
err
:=
manager
.
KillContainerInPod
(
""
,
&
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
}
// Assert the container has been stopped.
// Assert the container has been stopped.
...
@@ -478,14 +478,14 @@ func TestKillContainerInPodWithPreStop(t *testing.T) {
...
@@ -478,14 +478,14 @@ func TestKillContainerInPodWithPreStop(t *testing.T) {
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
}
}
if
err
:=
manager
.
KillContainerInPod
(
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
if
err
:=
manager
.
KillContainerInPod
(
""
,
&
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
}
// Assert the container has been stopped.
// Assert the container has been stopped.
if
err
:=
fakeDocker
.
AssertStopped
([]
string
{
containerToKill
.
ID
});
err
!=
nil
{
if
err
:=
fakeDocker
.
AssertStopped
([]
string
{
containerToKill
.
ID
});
err
!=
nil
{
t
.
Errorf
(
"container was not stopped correctly: %v"
,
err
)
t
.
Errorf
(
"container was not stopped correctly: %v"
,
err
)
}
}
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
"list"
,
"
inspect_container"
,
"
create_exec"
,
"start_exec"
,
"stop"
})
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
"list"
,
"create_exec"
,
"start_exec"
,
"stop"
})
if
!
reflect
.
DeepEqual
(
expectedCmd
,
fakeDocker
.
execCmd
)
{
if
!
reflect
.
DeepEqual
(
expectedCmd
,
fakeDocker
.
execCmd
)
{
t
.
Errorf
(
"expected: %v, got %v"
,
expectedCmd
,
fakeDocker
.
execCmd
)
t
.
Errorf
(
"expected: %v, got %v"
,
expectedCmd
,
fakeDocker
.
execCmd
)
}
}
...
@@ -522,7 +522,7 @@ func TestKillContainerInPodWithError(t *testing.T) {
...
@@ -522,7 +522,7 @@ func TestKillContainerInPodWithError(t *testing.T) {
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
}
}
if
err
:=
manager
.
KillContainerInPod
(
pod
.
Spec
.
Containers
[
0
],
pod
);
err
==
nil
{
if
err
:=
manager
.
KillContainerInPod
(
""
,
&
pod
.
Spec
.
Containers
[
0
],
pod
);
err
==
nil
{
t
.
Errorf
(
"expected error, found nil"
)
t
.
Errorf
(
"expected error, found nil"
)
}
}
...
@@ -1021,7 +1021,7 @@ func TestSyncPodDeletesWithNoPodInfraContainer(t *testing.T) {
...
@@ -1021,7 +1021,7 @@ func TestSyncPodDeletesWithNoPodInfraContainer(t *testing.T) {
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
// Kill the container since pod infra container is not running.
// Kill the container since pod infra container is not running.
"
inspect_container"
,
"
stop"
,
"stop"
,
// Create pod infra container.
// Create pod infra container.
"create"
,
"start"
,
"inspect_container"
,
"create"
,
"start"
,
"inspect_container"
,
// Create container.
// Create container.
...
@@ -1096,7 +1096,7 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
...
@@ -1096,7 +1096,7 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
// Check the pod infra container.
// Check the pod infra container.
"inspect_container"
,
"inspect_container"
,
// Kill the duplicated container.
// Kill the duplicated container.
"
inspect_container"
,
"
stop"
,
"stop"
,
})
})
// Expect one of the duplicates to be killed.
// Expect one of the duplicates to be killed.
if
len
(
fakeDocker
.
Stopped
)
!=
1
||
(
fakeDocker
.
Stopped
[
0
]
!=
"1234"
&&
fakeDocker
.
Stopped
[
0
]
!=
"4567"
)
{
if
len
(
fakeDocker
.
Stopped
)
!=
1
||
(
fakeDocker
.
Stopped
[
0
]
!=
"1234"
&&
fakeDocker
.
Stopped
[
0
]
!=
"4567"
)
{
...
@@ -1150,7 +1150,7 @@ func TestSyncPodBadHash(t *testing.T) {
...
@@ -1150,7 +1150,7 @@ func TestSyncPodBadHash(t *testing.T) {
// Check the pod infra container.
// Check the pod infra container.
"inspect_container"
,
"inspect_container"
,
// Kill and restart the bad hash container.
// Kill and restart the bad hash container.
"
inspect_container"
,
"
stop"
,
"create"
,
"start"
,
"inspect_container"
,
"stop"
,
"create"
,
"start"
,
"inspect_container"
,
})
})
if
err
:=
fakeDocker
.
AssertStopped
([]
string
{
"1234"
});
err
!=
nil
{
if
err
:=
fakeDocker
.
AssertStopped
([]
string
{
"1234"
});
err
!=
nil
{
...
@@ -1208,7 +1208,7 @@ func TestSyncPodsUnhealthy(t *testing.T) {
...
@@ -1208,7 +1208,7 @@ func TestSyncPodsUnhealthy(t *testing.T) {
// Check the pod infra container.
// Check the pod infra container.
"inspect_container"
,
"inspect_container"
,
// Kill the unhealthy container.
// Kill the unhealthy container.
"
inspect_container"
,
"
stop"
,
"stop"
,
// Restart the unhealthy container.
// Restart the unhealthy container.
"create"
,
"start"
,
"inspect_container"
,
"create"
,
"start"
,
"inspect_container"
,
})
})
...
@@ -1441,9 +1441,9 @@ func TestSyncPodWithRestartPolicy(t *testing.T) {
...
@@ -1441,9 +1441,9 @@ func TestSyncPodWithRestartPolicy(t *testing.T) {
api
.
RestartPolicyNever
,
api
.
RestartPolicyNever
,
[]
string
{
[]
string
{
// Check the pod infra container.
// Check the pod infra container.
"inspect_container"
,
"inspect_container"
,
"inspect_container"
,
// Stop the last pod infra container.
// Stop the last pod infra container.
"
inspect_container"
,
"
stop"
,
"stop"
,
},
},
[]
string
{},
[]
string
{},
[]
string
{
"9876"
},
[]
string
{
"9876"
},
...
@@ -1910,7 +1910,7 @@ func TestSyncPodEventHandlerFails(t *testing.T) {
...
@@ -1910,7 +1910,7 @@ func TestSyncPodEventHandlerFails(t *testing.T) {
// Create the container.
// Create the container.
"create"
,
"start"
,
"create"
,
"start"
,
// Kill the container since event handler fails.
// Kill the container since event handler fails.
"
inspect_container"
,
"
stop"
,
"stop"
,
})
})
// TODO(yifan): Check the stopped container's name.
// TODO(yifan): Check the stopped container's name.
...
...
pkg/kubelet/kubelet.go
View file @
73d105e2
...
@@ -1124,8 +1124,8 @@ func parseResolvConf(reader io.Reader) (nameservers []string, searches []string,
...
@@ -1124,8 +1124,8 @@ func parseResolvConf(reader io.Reader) (nameservers []string, searches []string,
}
}
// Kill all running containers in a pod (includes the pod infra container).
// Kill all running containers in a pod (includes the pod infra container).
func
(
kl
*
Kubelet
)
killPod
(
pod
kubecontainer
.
Pod
)
error
{
func
(
kl
*
Kubelet
)
killPod
(
pod
*
api
.
Pod
,
runningPod
kubecontainer
.
Pod
)
error
{
return
kl
.
containerRuntime
.
KillPod
(
pod
)
return
kl
.
containerRuntime
.
KillPod
(
pod
,
runningPod
)
}
}
type
empty
struct
{}
type
empty
struct
{}
...
@@ -1181,9 +1181,10 @@ func (kl *Kubelet) syncPod(pod *api.Pod, mirrorPod *api.Pod, runningPod kubecont
...
@@ -1181,9 +1181,10 @@ func (kl *Kubelet) syncPod(pod *api.Pod, mirrorPod *api.Pod, runningPod kubecont
}()
}()
// Kill pods we can't run.
// Kill pods we can't run.
err
:=
canRunPod
(
pod
)
if
err
:=
canRunPod
(
pod
);
err
!=
nil
||
pod
.
DeletionTimestamp
!=
nil
{
if
err
!=
nil
{
if
err
:=
kl
.
killPod
(
pod
,
runningPod
);
err
!=
nil
{
kl
.
killPod
(
runningPod
)
util
.
HandleError
(
err
)
}
return
err
return
err
}
}
...
@@ -1370,6 +1371,32 @@ func (kl *Kubelet) cleanupOrphanedVolumes(pods []*api.Pod, runningPods []*kubeco
...
@@ -1370,6 +1371,32 @@ func (kl *Kubelet) cleanupOrphanedVolumes(pods []*api.Pod, runningPods []*kubeco
return
nil
return
nil
}
}
// Delete any pods that are no longer running and are marked for deletion.
func
(
kl
*
Kubelet
)
cleanupTerminatedPods
(
pods
[]
*
api
.
Pod
,
runningPods
[]
*
kubecontainer
.
Pod
)
error
{
var
terminating
[]
*
api
.
Pod
for
_
,
pod
:=
range
pods
{
if
pod
.
DeletionTimestamp
!=
nil
{
found
:=
false
for
_
,
runningPod
:=
range
runningPods
{
if
runningPod
.
ID
==
pod
.
UID
{
found
=
true
break
}
}
if
found
{
podFullName
:=
kubecontainer
.
GetPodFullName
(
pod
)
glog
.
V
(
5
)
.
Infof
(
"Keeping terminated pod %q and uid %q, still running"
,
podFullName
,
pod
.
UID
)
continue
}
terminating
=
append
(
terminating
,
pod
)
}
}
if
!
kl
.
statusManager
.
TerminatePods
(
terminating
)
{
return
errors
.
New
(
"not all pods were successfully terminated"
)
}
return
nil
}
// pastActiveDeadline returns true if the pod has been active for more than
// pastActiveDeadline returns true if the pod has been active for more than
// ActiveDeadlineSeconds.
// ActiveDeadlineSeconds.
func
(
kl
*
Kubelet
)
pastActiveDeadline
(
pod
*
api
.
Pod
)
bool
{
func
(
kl
*
Kubelet
)
pastActiveDeadline
(
pod
*
api
.
Pod
)
bool
{
...
@@ -1532,6 +1559,10 @@ func (kl *Kubelet) cleanupPods(allPods []*api.Pod, admittedPods []*api.Pod) erro
...
@@ -1532,6 +1559,10 @@ func (kl *Kubelet) cleanupPods(allPods []*api.Pod, admittedPods []*api.Pod) erro
// Remove any orphaned mirror pods.
// Remove any orphaned mirror pods.
kl
.
podManager
.
DeleteOrphanedMirrorPods
()
kl
.
podManager
.
DeleteOrphanedMirrorPods
()
if
err
:=
kl
.
cleanupTerminatedPods
(
allPods
,
runningPods
);
err
!=
nil
{
glog
.
Errorf
(
"Failed to cleanup terminated pods: %v"
,
err
)
}
return
err
return
err
}
}
...
@@ -1554,7 +1585,7 @@ func (kl *Kubelet) killUnwantedPods(desiredPods map[types.UID]empty,
...
@@ -1554,7 +1585,7 @@ func (kl *Kubelet) killUnwantedPods(desiredPods map[types.UID]empty,
}()
}()
glog
.
V
(
1
)
.
Infof
(
"Killing unwanted pod %q"
,
pod
.
Name
)
glog
.
V
(
1
)
.
Infof
(
"Killing unwanted pod %q"
,
pod
.
Name
)
// Stop the containers.
// Stop the containers.
err
=
kl
.
killPod
(
*
pod
)
err
=
kl
.
killPod
(
nil
,
*
pod
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"Failed killing the pod %q: %v"
,
pod
.
Name
,
err
)
glog
.
Errorf
(
"Failed killing the pod %q: %v"
,
pod
.
Name
,
err
)
return
return
...
...
pkg/kubelet/mirror_client.go
View file @
73d105e2
...
@@ -64,7 +64,7 @@ func (mc *basicMirrorClient) DeleteMirrorPod(podFullName string) error {
...
@@ -64,7 +64,7 @@ func (mc *basicMirrorClient) DeleteMirrorPod(podFullName string) error {
return
err
return
err
}
}
glog
.
V
(
4
)
.
Infof
(
"Deleting a mirror pod %q"
,
podFullName
)
glog
.
V
(
4
)
.
Infof
(
"Deleting a mirror pod %q"
,
podFullName
)
if
err
:=
mc
.
apiserverClient
.
Pods
(
namespace
)
.
Delete
(
name
,
nil
);
err
!=
nil
{
if
err
:=
mc
.
apiserverClient
.
Pods
(
namespace
)
.
Delete
(
name
,
api
.
NewDeleteOptions
(
0
)
);
err
!=
nil
{
glog
.
Errorf
(
"Failed deleting a mirror pod %q: %v"
,
podFullName
,
err
)
glog
.
Errorf
(
"Failed deleting a mirror pod %q: %v"
,
podFullName
,
err
)
}
}
return
nil
return
nil
...
...
pkg/kubelet/rkt/rkt.go
View file @
73d105e2
...
@@ -693,11 +693,11 @@ func (r *runtime) GetPods(all bool) ([]*kubecontainer.Pod, error) {
...
@@ -693,11 +693,11 @@ func (r *runtime) GetPods(all bool) ([]*kubecontainer.Pod, error) {
}
}
// KillPod invokes 'systemctl kill' to kill the unit that runs the pod.
// KillPod invokes 'systemctl kill' to kill the unit that runs the pod.
func
(
r
*
runtime
)
KillPod
(
pod
kubecontainer
.
Pod
)
error
{
func
(
r
*
runtime
)
KillPod
(
pod
*
api
.
Pod
,
runningPod
kubecontainer
.
Pod
)
error
{
glog
.
V
(
4
)
.
Infof
(
"Rkt is killing pod: name %q."
,
p
od
.
Name
)
glog
.
V
(
4
)
.
Infof
(
"Rkt is killing pod: name %q."
,
runningP
od
.
Name
)
// TODO(yifan): More graceful stop. Replace with StopUnit and wait for a timeout.
// TODO(yifan): More graceful stop. Replace with StopUnit and wait for a timeout.
r
.
systemd
.
KillUnit
(
makePodServiceFileName
(
p
od
.
ID
),
int32
(
syscall
.
SIGKILL
))
r
.
systemd
.
KillUnit
(
makePodServiceFileName
(
runningP
od
.
ID
),
int32
(
syscall
.
SIGKILL
))
return
r
.
systemd
.
Reload
()
return
r
.
systemd
.
Reload
()
}
}
...
@@ -966,7 +966,7 @@ func (r *runtime) SyncPod(pod *api.Pod, runningPod kubecontainer.Pod, podStatus
...
@@ -966,7 +966,7 @@ func (r *runtime) SyncPod(pod *api.Pod, runningPod kubecontainer.Pod, podStatus
if
restartPod
{
if
restartPod
{
// TODO(yifan): Handle network plugin.
// TODO(yifan): Handle network plugin.
if
err
:=
r
.
KillPod
(
runningPod
);
err
!=
nil
{
if
err
:=
r
.
KillPod
(
pod
,
runningPod
);
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
r
.
RunPod
(
pod
,
pullSecrets
);
err
!=
nil
{
if
err
:=
r
.
RunPod
(
pod
,
pullSecrets
);
err
!=
nil
{
...
...
pkg/kubelet/status_manager.go
View file @
73d105e2
...
@@ -24,6 +24,7 @@ import (
...
@@ -24,6 +24,7 @@ import (
"github.com/golang/glog"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
client
"k8s.io/kubernetes/pkg/client/unversioned"
client
"k8s.io/kubernetes/pkg/client/unversioned"
kubecontainer
"k8s.io/kubernetes/pkg/kubelet/container"
kubecontainer
"k8s.io/kubernetes/pkg/kubelet/container"
kubeletTypes
"k8s.io/kubernetes/pkg/kubelet/types"
kubeletTypes
"k8s.io/kubernetes/pkg/kubelet/types"
...
@@ -122,7 +123,7 @@ func (s *statusManager) SetPodStatus(pod *api.Pod, status api.PodStatus) {
...
@@ -122,7 +123,7 @@ func (s *statusManager) SetPodStatus(pod *api.Pod, status api.PodStatus) {
// Currently this routine is not called for the same pod from multiple
// Currently this routine is not called for the same pod from multiple
// workers and/or the kubelet but dropping the lock before sending the
// workers and/or the kubelet but dropping the lock before sending the
// status down the channel feels like an easy way to get a bullet in foot.
// status down the channel feels like an easy way to get a bullet in foot.
if
!
found
||
!
isStatusEqual
(
&
oldStatus
,
&
status
)
{
if
!
found
||
!
isStatusEqual
(
&
oldStatus
,
&
status
)
||
pod
.
DeletionTimestamp
!=
nil
{
s
.
podStatuses
[
podFullName
]
=
status
s
.
podStatuses
[
podFullName
]
=
status
s
.
podStatusChannel
<-
podStatusSyncRequest
{
pod
,
status
}
s
.
podStatusChannel
<-
podStatusSyncRequest
{
pod
,
status
}
}
else
{
}
else
{
...
@@ -130,6 +131,29 @@ func (s *statusManager) SetPodStatus(pod *api.Pod, status api.PodStatus) {
...
@@ -130,6 +131,29 @@ func (s *statusManager) SetPodStatus(pod *api.Pod, status api.PodStatus) {
}
}
}
}
// TerminatePods resets the container status for the provided pods to terminated and triggers
// a status update. This function may not enqueue all the provided pods, in which case it will
// return false
func
(
s
*
statusManager
)
TerminatePods
(
pods
[]
*
api
.
Pod
)
bool
{
sent
:=
true
s
.
podStatusesLock
.
Lock
()
defer
s
.
podStatusesLock
.
Unlock
()
for
_
,
pod
:=
range
pods
{
for
i
:=
range
pod
.
Status
.
ContainerStatuses
{
pod
.
Status
.
ContainerStatuses
[
i
]
.
State
=
api
.
ContainerState
{
Terminated
:
&
api
.
ContainerStateTerminated
{},
}
}
select
{
case
s
.
podStatusChannel
<-
podStatusSyncRequest
{
pod
,
pod
.
Status
}
:
default
:
sent
=
false
glog
.
V
(
4
)
.
Infof
(
"Termination notice for %q was dropped because the status channel is full"
,
kubeletUtil
.
FormatPodName
(
pod
))
}
}
return
sent
}
func
(
s
*
statusManager
)
DeletePodStatus
(
podFullName
string
)
{
func
(
s
*
statusManager
)
DeletePodStatus
(
podFullName
string
)
{
s
.
podStatusesLock
.
Lock
()
s
.
podStatusesLock
.
Lock
()
defer
s
.
podStatusesLock
.
Unlock
()
defer
s
.
podStatusesLock
.
Unlock
()
...
@@ -161,13 +185,33 @@ func (s *statusManager) syncBatch() error {
...
@@ -161,13 +185,33 @@ func (s *statusManager) syncBatch() error {
}
}
// TODO: make me easier to express from client code
// TODO: make me easier to express from client code
statusPod
,
err
=
s
.
kubeClient
.
Pods
(
statusPod
.
Namespace
)
.
Get
(
statusPod
.
Name
)
statusPod
,
err
=
s
.
kubeClient
.
Pods
(
statusPod
.
Namespace
)
.
Get
(
statusPod
.
Name
)
if
errors
.
IsNotFound
(
err
)
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q was deleted on the server"
,
pod
.
Name
)
return
nil
}
if
err
==
nil
{
if
err
==
nil
{
if
len
(
pod
.
UID
)
>
0
&&
statusPod
.
UID
!=
pod
.
UID
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q was deleted and then recreated, skipping status update"
,
kubeletUtil
.
FormatPodName
(
pod
))
return
nil
}
statusPod
.
Status
=
status
statusPod
.
Status
=
status
_
,
err
=
s
.
kubeClient
.
Pods
(
pod
.
Namespace
)
.
UpdateStatus
(
statusPod
)
// TODO: handle conflict as a retry, make that easier too.
// TODO: handle conflict as a retry, make that easier too.
statusPod
,
err
=
s
.
kubeClient
.
Pods
(
pod
.
Namespace
)
.
UpdateStatus
(
statusPod
)
if
err
==
nil
{
if
err
==
nil
{
glog
.
V
(
3
)
.
Infof
(
"Status for pod %q updated successfully"
,
kubeletUtil
.
FormatPodName
(
pod
))
glog
.
V
(
3
)
.
Infof
(
"Status for pod %q updated successfully"
,
kubeletUtil
.
FormatPodName
(
pod
))
return
nil
if
pod
.
DeletionTimestamp
==
nil
{
return
nil
}
if
!
notRunning
(
pod
.
Status
.
ContainerStatuses
)
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q is terminated, but some pods are still running"
,
pod
.
Name
)
return
nil
}
if
err
:=
s
.
kubeClient
.
Pods
(
statusPod
.
Namespace
)
.
Delete
(
statusPod
.
Name
,
api
.
NewDeleteOptions
(
0
));
err
==
nil
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q fully terminated and removed from etcd"
,
statusPod
.
Name
)
s
.
DeletePodStatus
(
podFullName
)
return
nil
}
}
}
}
}
...
@@ -181,3 +225,14 @@ func (s *statusManager) syncBatch() error {
...
@@ -181,3 +225,14 @@ func (s *statusManager) syncBatch() error {
go
s
.
DeletePodStatus
(
podFullName
)
go
s
.
DeletePodStatus
(
podFullName
)
return
fmt
.
Errorf
(
"error updating status for pod %q: %v"
,
kubeletUtil
.
FormatPodName
(
pod
),
err
)
return
fmt
.
Errorf
(
"error updating status for pod %q: %v"
,
kubeletUtil
.
FormatPodName
(
pod
),
err
)
}
}
// notRunning returns true if every status is terminated or waiting, or the status list
// is empty.
func
notRunning
(
statuses
[]
api
.
ContainerStatus
)
bool
{
for
_
,
status
:=
range
statuses
{
if
status
.
State
.
Terminated
==
nil
&&
status
.
State
.
Waiting
==
nil
{
return
false
}
}
return
true
}
pkg/kubelet/status_manager_test.go
View file @
73d105e2
...
@@ -153,8 +153,21 @@ func TestUnchangedStatus(t *testing.T) {
...
@@ -153,8 +153,21 @@ func TestUnchangedStatus(t *testing.T) {
verifyUpdates
(
t
,
syncer
,
1
)
verifyUpdates
(
t
,
syncer
,
1
)
}
}
func
TestSyncBatchIgnoresNotFound
(
t
*
testing
.
T
)
{
syncer
:=
newTestStatusManager
()
syncer
.
SetPodStatus
(
testPod
,
getRandomPodStatus
())
err
:=
syncer
.
syncBatch
()
if
err
!=
nil
{
t
.
Errorf
(
"unexpected syncing error: %v"
,
err
)
}
verifyActions
(
t
,
syncer
.
kubeClient
,
[]
testclient
.
Action
{
testclient
.
GetActionImpl
{
ActionImpl
:
testclient
.
ActionImpl
{
Verb
:
"get"
,
Resource
:
"pods"
}},
})
}
func
TestSyncBatch
(
t
*
testing
.
T
)
{
func
TestSyncBatch
(
t
*
testing
.
T
)
{
syncer
:=
newTestStatusManager
()
syncer
:=
newTestStatusManager
()
syncer
.
kubeClient
=
testclient
.
NewSimpleFake
(
testPod
)
syncer
.
SetPodStatus
(
testPod
,
getRandomPodStatus
())
syncer
.
SetPodStatus
(
testPod
,
getRandomPodStatus
())
err
:=
syncer
.
syncBatch
()
err
:=
syncer
.
syncBatch
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -167,6 +180,22 @@ func TestSyncBatch(t *testing.T) {
...
@@ -167,6 +180,22 @@ func TestSyncBatch(t *testing.T) {
)
)
}
}
func
TestSyncBatchChecksMismatchedUID
(
t
*
testing
.
T
)
{
syncer
:=
newTestStatusManager
()
testPod
.
UID
=
"first"
differentPod
:=
*
testPod
differentPod
.
UID
=
"second"
syncer
.
kubeClient
=
testclient
.
NewSimpleFake
(
testPod
)
syncer
.
SetPodStatus
(
&
differentPod
,
getRandomPodStatus
())
err
:=
syncer
.
syncBatch
()
if
err
!=
nil
{
t
.
Errorf
(
"unexpected syncing error: %v"
,
err
)
}
verifyActions
(
t
,
syncer
.
kubeClient
,
[]
testclient
.
Action
{
testclient
.
GetActionImpl
{
ActionImpl
:
testclient
.
ActionImpl
{
Verb
:
"get"
,
Resource
:
"pods"
}},
})
}
// shuffle returns a new shuffled list of container statuses.
// shuffle returns a new shuffled list of container statuses.
func
shuffle
(
statuses
[]
api
.
ContainerStatus
)
[]
api
.
ContainerStatus
{
func
shuffle
(
statuses
[]
api
.
ContainerStatus
)
[]
api
.
ContainerStatus
{
numStatuses
:=
len
(
statuses
)
numStatuses
:=
len
(
statuses
)
...
...
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