Skip to content

Commit 90cc954

Browse files
committed
add sandbox deletor to delete sandboxes on pod delete event
1 parent d4325f4 commit 90cc954

13 files changed

+338
-18
lines changed

pkg/kubelet/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ go_library(
2525
"kubelet_resources.go",
2626
"kubelet_volumes.go",
2727
"pod_container_deletor.go",
28+
"pod_sandbox_deleter.go",
2829
"pod_workers.go",
2930
"reason_cache.go",
3031
"runonce.go",
@@ -177,6 +178,7 @@ go_test(
177178
"kubelet_volumes_linux_test.go",
178179
"kubelet_volumes_test.go",
179180
"pod_container_deletor_test.go",
181+
"pod_sandbox_deleter_test.go",
180182
"pod_workers_test.go",
181183
"reason_cache_test.go",
182184
"runonce_test.go",

pkg/kubelet/container/runtime.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ type Runtime interface {
114114
GetContainerLogs(ctx context.Context, pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error)
115115
// Delete a container. If the container is still running, an error is returned.
116116
DeleteContainer(containerID ContainerID) error
117+
// Delete a sandbox. If the container is still running, an error is returned.
118+
DeleteSandbox(sandboxID string) error
117119
// ImageService provides methods to image-related methods.
118120
ImageService
119121
// UpdatePodCIDR sends a new podCIDR to the runtime.
@@ -308,6 +310,8 @@ type Status struct {
308310
ID ContainerID
309311
// Name of the container.
310312
Name string
313+
// ID of the sandbox to which this container belongs.
314+
PodSandboxId string
311315
// Status of the container.
312316
State State
313317
// Creation time of the container.

pkg/kubelet/container/testing/fake_runtime.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,14 @@ func (f *FakeRuntime) DeleteContainer(containerID kubecontainer.ContainerID) err
364364
return f.Err
365365
}
366366

367+
func (f *FakeRuntime) DeleteSandbox(sandboxID string) error {
368+
f.Lock()
369+
defer f.Unlock()
370+
371+
f.CalledFunctions = append(f.CalledFunctions, "DeleteSandbox")
372+
return f.Err
373+
}
374+
367375
func (f *FakeRuntime) ImageStats() (*kubecontainer.ImageStats, error) {
368376
f.Lock()
369377
defer f.Unlock()

pkg/kubelet/container/testing/runtime_mock.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ func (r *Mock) DeleteContainer(containerID kubecontainer.ContainerID) error {
147147
return args.Error(0)
148148
}
149149

150+
func (r *Mock) DeleteSandbox(sandboxID string) error {
151+
args := r.Called(sandboxID)
152+
return args.Error(0)
153+
}
154+
150155
func (r *Mock) ImageStats() (*kubecontainer.ImageStats, error) {
151156
args := r.Called()
152157
return args.Get(0).(*kubecontainer.ImageStats), args.Error(1)

pkg/kubelet/kubelet.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
654654
}
655655
klet.containerGC = containerGC
656656
klet.containerDeletor = newPodContainerDeletor(klet.containerRuntime, integer.IntMax(containerGCPolicy.MaxPerPodContainer, minDeadContainerInPod))
657+
klet.sandboxDeleter = newPodSandboxDeleter(klet.containerRuntime)
657658

658659
// setup imageManager
659660
imageManager, err := images.NewImageGCManager(klet.containerRuntime, klet.StatsProvider, kubeDeps.Recorder, nodeRef, imageGCPolicy, crOptions.PodSandboxImage)
@@ -1095,6 +1096,9 @@ type Kubelet struct {
10951096
// trigger deleting containers in a pod
10961097
containerDeletor *podContainerDeletor
10971098

1099+
// trigger deleting sandboxes in a pod
1100+
sandboxDeleter *podSandboxDeleter
1101+
10981102
// config iptables util rules
10991103
makeIPTablesUtilChains bool
11001104

@@ -1866,6 +1870,9 @@ func (kl *Kubelet) syncLoopIteration(configCh <-chan kubetypes.PodUpdate, handle
18661870
klog.V(4).Infof("SyncLoop (PLEG): ignore irrelevant event: %#v", e)
18671871
}
18681872
}
1873+
if e.Type == pleg.ContainerRemoved {
1874+
kl.deletePodSandbox(e.ID)
1875+
}
18691876

18701877
if e.Type == pleg.ContainerDied {
18711878
if containerID, ok := e.Data.(string); ok {
@@ -2193,6 +2200,16 @@ func (kl *Kubelet) fastStatusUpdateOnce() {
21932200
}
21942201
}
21952202

2203+
func (kl *Kubelet) deletePodSandbox(podID types.UID) {
2204+
if podStatus, err := kl.podCache.Get(podID); err == nil {
2205+
toKeep := 1
2206+
if kl.IsPodDeleted(podID) {
2207+
toKeep = 0
2208+
}
2209+
kl.sandboxDeleter.deleteSandboxesInPod(podStatus, toKeep)
2210+
}
2211+
}
2212+
21962213
// isSyncPodWorthy filters out events that are not worthy of pod syncing
21972214
func isSyncPodWorthy(event *pleg.PodLifecycleEvent) bool {
21982215
// ContainerRemoved doesn't affect pod state

pkg/kubelet/kubelet_pods_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2454,7 +2454,7 @@ func TestPodResourcesAreReclaimed(t *testing.T) {
24542454
pod: &v1.Pod{},
24552455
status: v1.PodStatus{},
24562456
runtimeStatus: kubecontainer.PodStatus{
2457-
ContainerStatuses: []*kubecontainer.ContainerStatus{
2457+
ContainerStatuses: []*kubecontainer.Status{
24582458
{},
24592459
},
24602460
},

pkg/kubelet/kuberuntime/kuberuntime_container.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(uid kubetypes.UID, n
474474
cStatus.Message += tMessage
475475
}
476476
}
477+
cStatus.PodSandboxId = c.PodSandboxId
477478
statuses[i] = cStatus
478479
}
479480

pkg/kubelet/kuberuntime/kuberuntime_gc.go

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,13 @@ func (cgc *containerGC) removeOldestNSandboxes(sandboxes []sandboxGCInfo, toRemo
161161
// Remove from oldest to newest (last to first).
162162
for i := len(sandboxes) - 1; i >= numToKeep; i-- {
163163
if !sandboxes[i].active {
164-
cgc.removeSandbox(sandboxes[i].id)
164+
if err := cgc.manager.DeleteSandbox(sandboxes[i].id); err != nil {
165+
klog.Errorf("Failed to remove sandbox %q: %v", sandboxes[i].id, err)
166+
}
165167
}
166168
}
167169
}
168170

169-
// removeSandbox removes the sandbox by sandboxID.
170-
func (cgc *containerGC) removeSandbox(sandboxID string) {
171-
klog.V(4).Infof("Removing sandbox %q", sandboxID)
172-
// In normal cases, kubelet should've already called StopPodSandbox before
173-
// GC kicks in. To guard against the rare cases where this is not true, try
174-
// stopping the sandbox before removing it.
175-
if err := cgc.client.StopPodSandbox(sandboxID); err != nil {
176-
klog.Errorf("Failed to stop sandbox %q before removing: %v", sandboxID, err)
177-
return
178-
}
179-
if err := cgc.client.RemovePodSandbox(sandboxID); err != nil {
180-
klog.Errorf("Failed to remove sandbox %q: %v", sandboxID, err)
181-
}
182-
}
183-
184171
// evictableContainers gets all containers that are evictable. Evictable containers are: not running
185172
// and created more than MinAge ago.
186173
func (cgc *containerGC) evictableContainers(minAge time.Duration) (containersByEvictUnit, error) {

pkg/kubelet/kuberuntime/kuberuntime_manager_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,17 @@ func TestGetPodStatus(t *testing.T) {
318318
}
319319

320320
// Set fake sandbox and faked containers to fakeRuntime.
321-
makeAndSetFakePod(t, m, fakeRuntime, pod)
321+
sandbox, _ := makeAndSetFakePod(t, m, fakeRuntime, pod)
322322

323323
podStatus, err := m.GetPodStatus(pod.UID, pod.Name, pod.Namespace)
324324
assert.NoError(t, err)
325325
assert.Equal(t, pod.UID, podStatus.ID)
326326
assert.Equal(t, pod.Name, podStatus.Name)
327327
assert.Equal(t, pod.Namespace, podStatus.Namespace)
328328
assert.Equal(t, apitest.FakePodSandboxIPs, podStatus.IPs)
329+
for _, containerStatus := range podStatus.ContainerStatuses {
330+
assert.Equal(t, sandbox.Id, containerStatus.PodSandboxId)
331+
}
329332
}
330333

331334
func TestGetPods(t *testing.T) {

pkg/kubelet/kuberuntime/kuberuntime_sandbox.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,15 @@ func (m *kubeGenericRuntimeManager) GetPortForward(podName, podNamespace string,
304304
}
305305
return url.Parse(resp.Url)
306306
}
307+
308+
// DeleteSandbox removes the sandbox by sandboxID..
309+
func (m *kubeGenericRuntimeManager) DeleteSandbox(sandboxID string) error {
310+
klog.V(4).Infof("Removing sandbox %q", sandboxID)
311+
// the stop sandbox is called as part of kill pod but the error is ignored. So,
312+
// we have to call stop sandbox again to make sure that all the resources like
313+
// netwrork are cleaned by runtime.
314+
if err := m.runtimeService.StopPodSandbox(sandboxID); err != nil {
315+
return err
316+
}
317+
return m.runtimeService.RemovePodSandbox(sandboxID)
318+
}

0 commit comments

Comments
 (0)