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
889afa5e
Commit
889afa5e
authored
May 22, 2017
by
David Ashpole
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
trigger aggressive container garbage collection when under disk pressure
parent
07f85565
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
193 additions
and
105 deletions
+193
-105
container_gc.go
pkg/kubelet/container/container_gc.go
+22
-6
runtime.go
pkg/kubelet/container/runtime.go
+3
-1
fake_runtime.go
pkg/kubelet/container/testing/fake_runtime.go
+1
-1
runtime_mock.go
pkg/kubelet/container/testing/runtime_mock.go
+2
-2
eviction_manager.go
pkg/kubelet/eviction/eviction_manager.go
+5
-2
eviction_manager_test.go
pkg/kubelet/eviction/eviction_manager_test.go
+47
-31
helpers.go
pkg/kubelet/eviction/helpers.go
+15
-13
types.go
pkg/kubelet/eviction/types.go
+7
-0
kubelet.go
pkg/kubelet/kubelet.go
+3
-3
kubelet_test.go
pkg/kubelet/kubelet_test.go
+1
-1
kuberuntime_gc.go
pkg/kubelet/kuberuntime/kuberuntime_gc.go
+7
-7
kuberuntime_gc_test.go
pkg/kubelet/kuberuntime/kuberuntime_gc_test.go
+74
-33
kuberuntime_manager.go
pkg/kubelet/kuberuntime/kuberuntime_manager.go
+2
-2
rkt.go
pkg/kubelet/rkt/rkt.go
+1
-1
rkt_test.go
pkg/kubelet/rkt/rkt_test.go
+2
-1
runonce_test.go
pkg/kubelet/runonce_test.go
+1
-1
No files found.
pkg/kubelet/container/container_gc.go
View file @
889afa5e
...
...
@@ -39,7 +39,15 @@ type ContainerGCPolicy struct {
// Implementation is thread-compatible.
type
ContainerGC
interface
{
// Garbage collect containers.
GarbageCollect
(
allSourcesReady
bool
)
error
GarbageCollect
()
error
// Deletes all unused containers, including containers belonging to pods that are terminated but not deleted
DeleteAllUnusedContainers
()
error
}
// SourcesReadyProvider knows how to determine if configuration sources are ready
type
SourcesReadyProvider
interface
{
// AllReady returns true if the currently configured sources have all been seen.
AllReady
()
bool
}
// TODO(vmarmol): Preferentially remove pod infra containers.
...
...
@@ -49,20 +57,28 @@ type realContainerGC struct {
// Policy for garbage collection.
policy
ContainerGCPolicy
// sourcesReadyProvider provides the readyness of kubelet configuration sources.
sourcesReadyProvider
SourcesReadyProvider
}
// New ContainerGC instance with the specified policy.
func
NewContainerGC
(
runtime
Runtime
,
policy
ContainerGCPolicy
)
(
ContainerGC
,
error
)
{
func
NewContainerGC
(
runtime
Runtime
,
policy
ContainerGCPolicy
,
sourcesReadyProvider
SourcesReadyProvider
)
(
ContainerGC
,
error
)
{
if
policy
.
MinAge
<
0
{
return
nil
,
fmt
.
Errorf
(
"invalid minimum garbage collection age: %v"
,
policy
.
MinAge
)
}
return
&
realContainerGC
{
runtime
:
runtime
,
policy
:
policy
,
runtime
:
runtime
,
policy
:
policy
,
sourcesReadyProvider
:
sourcesReadyProvider
,
},
nil
}
func
(
cgc
*
realContainerGC
)
GarbageCollect
(
allSourcesReady
bool
)
error
{
return
cgc
.
runtime
.
GarbageCollect
(
cgc
.
policy
,
allSourcesReady
)
func
(
cgc
*
realContainerGC
)
GarbageCollect
()
error
{
return
cgc
.
runtime
.
GarbageCollect
(
cgc
.
policy
,
cgc
.
sourcesReadyProvider
.
AllReady
(),
false
)
}
func
(
cgc
*
realContainerGC
)
DeleteAllUnusedContainers
()
error
{
return
cgc
.
runtime
.
GarbageCollect
(
cgc
.
policy
,
cgc
.
sourcesReadyProvider
.
AllReady
(),
true
)
}
pkg/kubelet/container/runtime.go
View file @
889afa5e
...
...
@@ -82,8 +82,10 @@ type Runtime interface {
// complete list of pods from all avialble sources (e.g., apiserver, http,
// file). In this case, garbage collector should refrain itself from aggressive
// behavior such as removing all containers of unrecognized pods (yet).
// If evictNonDeletedPods is set to true, containers and sandboxes belonging to pods
// that are terminated, but not deleted will be evicted. Otherwise, only deleted pods will be GC'd.
// TODO: Revisit this method and make it cleaner.
GarbageCollect
(
gcPolicy
ContainerGCPolicy
,
allSourcesReady
bool
)
error
GarbageCollect
(
gcPolicy
ContainerGCPolicy
,
allSourcesReady
bool
,
evictNonDeletedPods
bool
)
error
// Syncs the running pod into the desired pod.
SyncPod
(
pod
*
v1
.
Pod
,
apiPodStatus
v1
.
PodStatus
,
podStatus
*
PodStatus
,
pullSecrets
[]
v1
.
Secret
,
backOff
*
flowcontrol
.
Backoff
)
PodSyncResult
// KillPod kills all the containers of a pod. Pod may be nil, running pod must not be.
...
...
pkg/kubelet/container/testing/fake_runtime.go
View file @
889afa5e
...
...
@@ -431,7 +431,7 @@ func (f *FakeRuntime) GetPodContainerID(pod *Pod) (ContainerID, error) {
return
ContainerID
{},
f
.
Err
}
func
(
f
*
FakeRuntime
)
GarbageCollect
(
gcPolicy
ContainerGCPolicy
,
ready
bool
)
error
{
func
(
f
*
FakeRuntime
)
GarbageCollect
(
gcPolicy
ContainerGCPolicy
,
ready
bool
,
evictNonDeletedPods
bool
)
error
{
f
.
Lock
()
defer
f
.
Unlock
()
...
...
pkg/kubelet/container/testing/runtime_mock.go
View file @
889afa5e
...
...
@@ -140,8 +140,8 @@ func (r *Mock) GetPodContainerID(pod *Pod) (ContainerID, error) {
return
ContainerID
{},
args
.
Error
(
0
)
}
func
(
r
*
Mock
)
GarbageCollect
(
gcPolicy
ContainerGCPolicy
,
ready
bool
)
error
{
args
:=
r
.
Called
(
gcPolicy
,
ready
)
func
(
r
*
Mock
)
GarbageCollect
(
gcPolicy
ContainerGCPolicy
,
ready
bool
,
evictNonDeletedPods
bool
)
error
{
args
:=
r
.
Called
(
gcPolicy
,
ready
,
evictNonDeletedPods
)
return
args
.
Error
(
0
)
}
...
...
pkg/kubelet/eviction/eviction_manager.go
View file @
889afa5e
...
...
@@ -58,6 +58,8 @@ type managerImpl struct {
killPodFunc
KillPodFunc
// the interface that knows how to do image gc
imageGC
ImageGC
// the interface that knows how to do image gc
containerGC
ContainerGC
// protects access to internal state
sync
.
RWMutex
// node conditions are the set of conditions present
...
...
@@ -95,6 +97,7 @@ func NewManager(
config
Config
,
killPodFunc
KillPodFunc
,
imageGC
ImageGC
,
containerGC
ContainerGC
,
recorder
record
.
EventRecorder
,
nodeRef
*
clientv1
.
ObjectReference
,
clock
clock
.
Clock
)
(
Manager
,
lifecycle
.
PodAdmitHandler
)
{
...
...
@@ -102,6 +105,7 @@ func NewManager(
clock
:
clock
,
killPodFunc
:
killPodFunc
,
imageGC
:
imageGC
,
containerGC
:
containerGC
,
config
:
config
,
recorder
:
recorder
,
summaryProvider
:
summaryProvider
,
...
...
@@ -223,8 +227,7 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act
}
m
.
dedicatedImageFs
=
&
hasImageFs
m
.
resourceToRankFunc
=
buildResourceToRankFunc
(
hasImageFs
)
m
.
resourceToNodeReclaimFuncs
=
buildResourceToNodeReclaimFuncs
(
m
.
imageGC
,
hasImageFs
)
m
.
resourceToNodeReclaimFuncs
=
buildResourceToNodeReclaimFuncs
(
m
.
imageGC
,
m
.
containerGC
,
hasImageFs
)
}
activePods
:=
podFunc
()
...
...
pkg/kubelet/eviction/eviction_manager_test.go
View file @
889afa5e
...
...
@@ -77,17 +77,24 @@ func (m *mockNodeProvider) GetNode() (*v1.Node, error) {
return
&
m
.
node
,
nil
}
// mockImageGC is used to simulate invoking image garbage collection.
type
mockImageGC
struct
{
err
error
freed
int64
invoked
bool
// mockDiskGC is used to simulate invoking image and container garbage collection.
type
mockDiskGC
struct
{
err
error
imageBytesFreed
int64
imageGCInvoked
bool
containerGCInvoked
bool
}
// DeleteUnusedImages returns the mocked values.
func
(
m
*
mockImageGC
)
DeleteUnusedImages
()
(
int64
,
error
)
{
m
.
invoked
=
true
return
m
.
freed
,
m
.
err
func
(
m
*
mockDiskGC
)
DeleteUnusedImages
()
(
int64
,
error
)
{
m
.
imageGCInvoked
=
true
return
m
.
imageBytesFreed
,
m
.
err
}
// DeleteAllUnusedContainers returns the mocked value
func
(
m
*
mockDiskGC
)
DeleteAllUnusedContainers
()
error
{
m
.
containerGCInvoked
=
true
return
m
.
err
}
func
makePodWithMemoryStats
(
name
string
,
requests
v1
.
ResourceList
,
limits
v1
.
ResourceList
,
memoryWorkingSet
string
)
(
*
v1
.
Pod
,
statsapi
.
PodStats
)
{
...
...
@@ -194,7 +201,7 @@ func TestMemoryPressure(t *testing.T) {
podKiller
:=
&
mockPodKiller
{}
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGC
:=
&
mock
ImageGC
{
f
reed
:
int64
(
0
),
err
:
nil
}
imageGC
:=
&
mock
DiskGC
{
imageBytesF
reed
:
int64
(
0
),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
}
config
:=
Config
{
...
...
@@ -412,7 +419,7 @@ func TestDiskPressureNodeFs(t *testing.T) {
podKiller
:=
&
mockPodKiller
{}
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGC
:=
&
mockImageGC
{
f
reed
:
int64
(
0
),
err
:
nil
}
diskGC
:=
&
mockDiskGC
{
imageBytesF
reed
:
int64
(
0
),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
}
config
:=
Config
{
...
...
@@ -440,7 +447,8 @@ func TestDiskPressureNodeFs(t *testing.T) {
manager
:=
&
managerImpl
{
clock
:
fakeClock
,
killPodFunc
:
podKiller
.
killPodNow
,
imageGC
:
imageGC
,
imageGC
:
diskGC
,
containerGC
:
diskGC
,
config
:
config
,
recorder
:
&
record
.
FakeRecorder
{},
summaryProvider
:
summaryProvider
,
...
...
@@ -610,7 +618,7 @@ func TestMinReclaim(t *testing.T) {
podKiller
:=
&
mockPodKiller
{}
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGC
:=
&
mockImageGC
{
f
reed
:
int64
(
0
),
err
:
nil
}
diskGC
:=
&
mockDiskGC
{
imageBytesF
reed
:
int64
(
0
),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
}
config
:=
Config
{
...
...
@@ -633,7 +641,8 @@ func TestMinReclaim(t *testing.T) {
manager
:=
&
managerImpl
{
clock
:
fakeClock
,
killPodFunc
:
podKiller
.
killPodNow
,
imageGC
:
imageGC
,
imageGC
:
diskGC
,
containerGC
:
diskGC
,
config
:
config
,
recorder
:
&
record
.
FakeRecorder
{},
summaryProvider
:
summaryProvider
,
...
...
@@ -750,7 +759,7 @@ func TestNodeReclaimFuncs(t *testing.T) {
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGcFree
:=
resource
.
MustParse
(
"700Mi"
)
imageGC
:=
&
mockImageGC
{
f
reed
:
imageGcFree
.
Value
(),
err
:
nil
}
diskGC
:=
&
mockDiskGC
{
imageBytesF
reed
:
imageGcFree
.
Value
(),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
}
config
:=
Config
{
...
...
@@ -773,7 +782,8 @@ func TestNodeReclaimFuncs(t *testing.T) {
manager
:=
&
managerImpl
{
clock
:
fakeClock
,
killPodFunc
:
podKiller
.
killPodNow
,
imageGC
:
imageGC
,
imageGC
:
diskGC
,
containerGC
:
diskGC
,
config
:
config
,
recorder
:
&
record
.
FakeRecorder
{},
summaryProvider
:
summaryProvider
,
...
...
@@ -801,7 +811,7 @@ func TestNodeReclaimFuncs(t *testing.T) {
}
// verify image gc was invoked
if
!
imageGC
.
i
nvoked
{
if
!
diskGC
.
imageGCInvoked
||
!
diskGC
.
containerGCI
nvoked
{
t
.
Errorf
(
"Manager should have invoked image gc"
)
}
...
...
@@ -811,7 +821,8 @@ func TestNodeReclaimFuncs(t *testing.T) {
}
// reset state
imageGC
.
invoked
=
false
diskGC
.
imageGCInvoked
=
false
diskGC
.
containerGCInvoked
=
false
// remove disk pressure
fakeClock
.
Step
(
20
*
time
.
Minute
)
...
...
@@ -833,8 +844,8 @@ func TestNodeReclaimFuncs(t *testing.T) {
t
.
Errorf
(
"Manager should report disk pressure"
)
}
// ensure
image
gc was invoked
if
!
imageGC
.
i
nvoked
{
// ensure
disk
gc was invoked
if
!
diskGC
.
imageGCInvoked
||
!
diskGC
.
containerGCI
nvoked
{
t
.
Errorf
(
"Manager should have invoked image gc"
)
}
...
...
@@ -850,8 +861,9 @@ func TestNodeReclaimFuncs(t *testing.T) {
// reduce disk pressure
fakeClock
.
Step
(
1
*
time
.
Minute
)
summaryProvider
.
result
=
summaryStatsMaker
(
"16Gi"
,
"200Gi"
,
podStats
)
imageGC
.
invoked
=
false
// reset state
podKiller
.
pod
=
nil
// reset state
diskGC
.
imageGCInvoked
=
false
// reset state
diskGC
.
containerGCInvoked
=
false
// reset state
podKiller
.
pod
=
nil
// reset state
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
,
nodeProvider
)
// we should have disk pressure (because transition period not yet met)
...
...
@@ -860,7 +872,7 @@ func TestNodeReclaimFuncs(t *testing.T) {
}
// no image gc should have occurred
if
imageGC
.
i
nvoked
{
if
diskGC
.
imageGCInvoked
||
diskGC
.
containerGCI
nvoked
{
t
.
Errorf
(
"Manager chose to perform image gc when it was not neeed"
)
}
...
...
@@ -872,8 +884,9 @@ func TestNodeReclaimFuncs(t *testing.T) {
// move the clock past transition period to ensure that we stop reporting pressure
fakeClock
.
Step
(
5
*
time
.
Minute
)
summaryProvider
.
result
=
summaryStatsMaker
(
"16Gi"
,
"200Gi"
,
podStats
)
imageGC
.
invoked
=
false
// reset state
podKiller
.
pod
=
nil
// reset state
diskGC
.
imageGCInvoked
=
false
// reset state
diskGC
.
containerGCInvoked
=
false
// reset state
podKiller
.
pod
=
nil
// reset state
manager
.
synchronize
(
diskInfoProvider
,
activePodsFunc
,
nodeProvider
)
// we should not have disk pressure (because transition period met)
...
...
@@ -882,7 +895,7 @@ func TestNodeReclaimFuncs(t *testing.T) {
}
// no image gc should have occurred
if
imageGC
.
i
nvoked
{
if
diskGC
.
imageGCInvoked
||
diskGC
.
containerGCI
nvoked
{
t
.
Errorf
(
"Manager chose to perform image gc when it was not neeed"
)
}
...
...
@@ -943,7 +956,7 @@ func TestInodePressureNodeFsInodes(t *testing.T) {
podKiller
:=
&
mockPodKiller
{}
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGC
:=
&
mockImageGC
{
f
reed
:
int64
(
0
),
err
:
nil
}
diskGC
:=
&
mockDiskGC
{
imageBytesF
reed
:
int64
(
0
),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
}
config
:=
Config
{
...
...
@@ -971,7 +984,8 @@ func TestInodePressureNodeFsInodes(t *testing.T) {
manager
:=
&
managerImpl
{
clock
:
fakeClock
,
killPodFunc
:
podKiller
.
killPodNow
,
imageGC
:
imageGC
,
imageGC
:
diskGC
,
containerGC
:
diskGC
,
config
:
config
,
recorder
:
&
record
.
FakeRecorder
{},
summaryProvider
:
summaryProvider
,
...
...
@@ -1144,7 +1158,7 @@ func TestCriticalPodsAreNotEvicted(t *testing.T) {
podKiller
:=
&
mockPodKiller
{}
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGC
:=
&
mockImageGC
{
f
reed
:
int64
(
0
),
err
:
nil
}
diskGC
:=
&
mockDiskGC
{
imageBytesF
reed
:
int64
(
0
),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
,
}
...
...
@@ -1174,7 +1188,8 @@ func TestCriticalPodsAreNotEvicted(t *testing.T) {
manager
:=
&
managerImpl
{
clock
:
fakeClock
,
killPodFunc
:
podKiller
.
killPodNow
,
imageGC
:
imageGC
,
imageGC
:
diskGC
,
containerGC
:
diskGC
,
config
:
config
,
recorder
:
&
record
.
FakeRecorder
{},
summaryProvider
:
summaryProvider
,
...
...
@@ -1276,7 +1291,7 @@ func TestAllocatableMemoryPressure(t *testing.T) {
podKiller
:=
&
mockPodKiller
{}
diskInfoProvider
:=
&
mockDiskInfoProvider
{
dedicatedImageFs
:
false
}
nodeProvider
:=
newMockNodeProvider
(
v1
.
ResourceList
{
v1
.
ResourceMemory
:
*
quantityMustParse
(
"2Gi"
)})
imageGC
:=
&
mockImageGC
{
f
reed
:
int64
(
0
),
err
:
nil
}
diskGC
:=
&
mockDiskGC
{
imageBytesF
reed
:
int64
(
0
),
err
:
nil
}
nodeRef
:=
&
clientv1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
"test"
,
UID
:
types
.
UID
(
"test"
),
Namespace
:
""
}
config
:=
Config
{
...
...
@@ -1296,7 +1311,8 @@ func TestAllocatableMemoryPressure(t *testing.T) {
manager
:=
&
managerImpl
{
clock
:
fakeClock
,
killPodFunc
:
podKiller
.
killPodNow
,
imageGC
:
imageGC
,
imageGC
:
diskGC
,
containerGC
:
diskGC
,
config
:
config
,
recorder
:
&
record
.
FakeRecorder
{},
summaryProvider
:
summaryProvider
,
...
...
pkg/kubelet/eviction/helpers.go
View file @
889afa5e
...
...
@@ -1019,32 +1019,34 @@ func PodIsEvicted(podStatus v1.PodStatus) bool {
}
// buildResourceToNodeReclaimFuncs returns reclaim functions associated with resources.
func
buildResourceToNodeReclaimFuncs
(
imageGC
ImageGC
,
withImageFs
bool
)
map
[
v1
.
ResourceName
]
nodeReclaimFuncs
{
func
buildResourceToNodeReclaimFuncs
(
imageGC
ImageGC
,
containerGC
ContainerGC
,
withImageFs
bool
)
map
[
v1
.
ResourceName
]
nodeReclaimFuncs
{
resourceToReclaimFunc
:=
map
[
v1
.
ResourceName
]
nodeReclaimFuncs
{}
// usage of an imagefs is optional
if
withImageFs
{
// with an imagefs, nodefs pressure should just delete logs
resourceToReclaimFunc
[
resourceNodeFs
]
=
nodeReclaimFuncs
{
deleteLogs
()
}
resourceToReclaimFunc
[
resourceNodeFsInodes
]
=
nodeReclaimFuncs
{
deleteLogs
()
}
resourceToReclaimFunc
[
resourceNodeFs
]
=
nodeReclaimFuncs
{}
resourceToReclaimFunc
[
resourceNodeFsInodes
]
=
nodeReclaimFuncs
{}
// with an imagefs, imagefs pressure should delete unused images
resourceToReclaimFunc
[
resourceImageFs
]
=
nodeReclaimFuncs
{
deleteImages
(
imageGC
,
true
)}
resourceToReclaimFunc
[
resourceImageFsInodes
]
=
nodeReclaimFuncs
{
deleteImages
(
imageGC
,
false
)}
resourceToReclaimFunc
[
resourceImageFs
]
=
nodeReclaimFuncs
{
delete
TerminatedContainers
(
containerGC
),
delete
Images
(
imageGC
,
true
)}
resourceToReclaimFunc
[
resourceImageFsInodes
]
=
nodeReclaimFuncs
{
delete
TerminatedContainers
(
containerGC
),
delete
Images
(
imageGC
,
false
)}
}
else
{
// without an imagefs, nodefs pressure should delete logs, and unused images
// since imagefs and nodefs share a common device, they share common reclaim functions
resourceToReclaimFunc
[
resourceNodeFs
]
=
nodeReclaimFuncs
{
delete
Logs
(
),
deleteImages
(
imageGC
,
true
)}
resourceToReclaimFunc
[
resourceNodeFsInodes
]
=
nodeReclaimFuncs
{
delete
Logs
(
),
deleteImages
(
imageGC
,
false
)}
resourceToReclaimFunc
[
resourceImageFs
]
=
nodeReclaimFuncs
{
delete
Logs
(
),
deleteImages
(
imageGC
,
true
)}
resourceToReclaimFunc
[
resourceImageFsInodes
]
=
nodeReclaimFuncs
{
delete
Logs
(
),
deleteImages
(
imageGC
,
false
)}
resourceToReclaimFunc
[
resourceNodeFs
]
=
nodeReclaimFuncs
{
delete
TerminatedContainers
(
containerGC
),
deleteImages
(
imageGC
,
true
)}
resourceToReclaimFunc
[
resourceNodeFsInodes
]
=
nodeReclaimFuncs
{
delete
TerminatedContainers
(
containerGC
),
deleteImages
(
imageGC
,
false
)}
resourceToReclaimFunc
[
resourceImageFs
]
=
nodeReclaimFuncs
{
delete
TerminatedContainers
(
containerGC
),
deleteImages
(
imageGC
,
true
)}
resourceToReclaimFunc
[
resourceImageFsInodes
]
=
nodeReclaimFuncs
{
delete
TerminatedContainers
(
containerGC
),
deleteImages
(
imageGC
,
false
)}
}
return
resourceToReclaimFunc
}
// delete
Logs will delete log
s to free up disk pressure.
func
delete
Logs
(
)
nodeReclaimFunc
{
// delete
TerminatedContainers will delete terminated container
s to free up disk pressure.
func
delete
TerminatedContainers
(
containerGC
ContainerGC
)
nodeReclaimFunc
{
return
func
()
(
*
resource
.
Quantity
,
error
)
{
// TODO: not yet supported.
return
resource
.
NewQuantity
(
int64
(
0
),
resource
.
BinarySI
),
nil
glog
.
Infof
(
"eviction manager: attempting to delete unused containers"
)
err
:=
containerGC
.
DeleteAllUnusedContainers
()
// Calculating bytes freed is not yet supported.
return
resource
.
NewQuantity
(
int64
(
0
),
resource
.
BinarySI
),
err
}
}
...
...
pkg/kubelet/eviction/types.go
View file @
889afa5e
...
...
@@ -81,6 +81,13 @@ type ImageGC interface {
DeleteUnusedImages
()
(
int64
,
error
)
}
// ContainerGC is responsible for performing garbage collection of unused containers.
type
ContainerGC
interface
{
// DeleteAllUnusedContainers deletes all unused containers, even those that belong to pods that are terminated, but not deleted.
// It returns an error if it is unsuccessful.
DeleteAllUnusedContainers
()
error
}
// KillPodFunc kills a pod.
// The pod status is updated, and then it is killed with the specified grace period.
// This function must block until either the pod is killed or an error is encountered.
...
...
pkg/kubelet/kubelet.go
View file @
889afa5e
...
...
@@ -671,7 +671,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub
klet
.
updatePodCIDR
(
kubeCfg
.
PodCIDR
)
// setup containerGC
containerGC
,
err
:=
kubecontainer
.
NewContainerGC
(
klet
.
containerRuntime
,
containerGCPolicy
)
containerGC
,
err
:=
kubecontainer
.
NewContainerGC
(
klet
.
containerRuntime
,
containerGCPolicy
,
klet
.
sourcesReady
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -761,7 +761,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub
klet
.
setNodeStatusFuncs
=
klet
.
defaultNodeStatusFuncs
()
// setup eviction manager
evictionManager
,
evictionAdmitHandler
:=
eviction
.
NewManager
(
klet
.
resourceAnalyzer
,
evictionConfig
,
killPodNow
(
klet
.
podWorkers
,
kubeDeps
.
Recorder
),
klet
.
imageManager
,
kubeDeps
.
Recorder
,
nodeRef
,
klet
.
clock
)
evictionManager
,
evictionAdmitHandler
:=
eviction
.
NewManager
(
klet
.
resourceAnalyzer
,
evictionConfig
,
killPodNow
(
klet
.
podWorkers
,
kubeDeps
.
Recorder
),
klet
.
imageManager
,
k
let
.
containerGC
,
k
ubeDeps
.
Recorder
,
nodeRef
,
klet
.
clock
)
klet
.
evictionManager
=
evictionManager
klet
.
admitHandlers
.
AddPodAdmitHandler
(
evictionAdmitHandler
)
...
...
@@ -1184,7 +1184,7 @@ func (kl *Kubelet) setupDataDirs() error {
func
(
kl
*
Kubelet
)
StartGarbageCollection
()
{
loggedContainerGCFailure
:=
false
go
wait
.
Until
(
func
()
{
if
err
:=
kl
.
containerGC
.
GarbageCollect
(
kl
.
sourcesReady
.
AllReady
()
);
err
!=
nil
{
if
err
:=
kl
.
containerGC
.
GarbageCollect
();
err
!=
nil
{
glog
.
Errorf
(
"Container garbage collection failed: %v"
,
err
)
kl
.
recorder
.
Eventf
(
kl
.
nodeRef
,
v1
.
EventTypeWarning
,
events
.
ContainerGCFailed
,
err
.
Error
())
loggedContainerGCFailure
=
true
...
...
pkg/kubelet/kubelet_test.go
View file @
889afa5e
...
...
@@ -270,7 +270,7 @@ func newTestKubeletWithImageList(
Namespace
:
""
,
}
// setup eviction manager
evictionManager
,
evictionAdmitHandler
:=
eviction
.
NewManager
(
kubelet
.
resourceAnalyzer
,
eviction
.
Config
{},
killPodNow
(
kubelet
.
podWorkers
,
fakeRecorder
),
kubelet
.
imageManager
,
fakeRecorder
,
nodeRef
,
kubelet
.
clock
)
evictionManager
,
evictionAdmitHandler
:=
eviction
.
NewManager
(
kubelet
.
resourceAnalyzer
,
eviction
.
Config
{},
killPodNow
(
kubelet
.
podWorkers
,
fakeRecorder
),
kubelet
.
imageManager
,
kubelet
.
containerGC
,
fakeRecorder
,
nodeRef
,
kubelet
.
clock
)
kubelet
.
evictionManager
=
evictionManager
kubelet
.
admitHandlers
.
AddPodAdmitHandler
(
evictionAdmitHandler
)
...
...
pkg/kubelet/kuberuntime/kuberuntime_gc.go
View file @
889afa5e
...
...
@@ -209,7 +209,7 @@ func (cgc *containerGC) evictableContainers(minAge time.Duration) (containersByE
}
// evict all containers that are evictable
func
(
cgc
*
containerGC
)
evictContainers
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
)
error
{
func
(
cgc
*
containerGC
)
evictContainers
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
,
evictNonDeletedPods
bool
)
error
{
// Separate containers by evict units.
evictUnits
,
err
:=
cgc
.
evictableContainers
(
gcPolicy
.
MinAge
)
if
err
!=
nil
{
...
...
@@ -219,7 +219,7 @@ func (cgc *containerGC) evictContainers(gcPolicy kubecontainer.ContainerGCPolicy
// Remove deleted pod containers if all sources are ready.
if
allSourcesReady
{
for
key
,
unit
:=
range
evictUnits
{
if
cgc
.
isPodDeleted
(
key
.
uid
)
{
if
cgc
.
isPodDeleted
(
key
.
uid
)
||
evictNonDeletedPods
{
cgc
.
removeOldestN
(
unit
,
len
(
unit
))
// Remove all.
delete
(
evictUnits
,
key
)
}
...
...
@@ -261,7 +261,7 @@ func (cgc *containerGC) evictContainers(gcPolicy kubecontainer.ContainerGCPolicy
// 2. contains no containers.
// 3. belong to a non-existent (i.e., already removed) pod, or is not the
// most recently created sandbox for the pod.
func
(
cgc
*
containerGC
)
evictSandboxes
()
error
{
func
(
cgc
*
containerGC
)
evictSandboxes
(
evictNonDeletedPods
bool
)
error
{
containers
,
err
:=
cgc
.
manager
.
getKubeletContainers
(
true
)
if
err
!=
nil
{
return
err
...
...
@@ -307,7 +307,7 @@ func (cgc *containerGC) evictSandboxes() error {
}
for
podUID
,
sandboxes
:=
range
sandboxesByPod
{
if
cgc
.
isPodDeleted
(
podUID
)
{
if
cgc
.
isPodDeleted
(
podUID
)
||
evictNonDeletedPods
{
// Remove all evictable sandboxes if the pod has been removed.
// Note that the latest dead sandbox is also removed if there is
// already an active one.
...
...
@@ -367,14 +367,14 @@ func (cgc *containerGC) evictPodLogsDirectories(allSourcesReady bool) error {
// * removes oldest dead containers by enforcing gcPolicy.MaxContainers.
// * gets evictable sandboxes which are not ready and contains no containers.
// * removes evictable sandboxes.
func
(
cgc
*
containerGC
)
GarbageCollect
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
)
error
{
func
(
cgc
*
containerGC
)
GarbageCollect
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
,
evictNonDeletedPods
bool
)
error
{
// Remove evictable containers
if
err
:=
cgc
.
evictContainers
(
gcPolicy
,
allSourcesReady
);
err
!=
nil
{
if
err
:=
cgc
.
evictContainers
(
gcPolicy
,
allSourcesReady
,
evictNonDeletedPods
);
err
!=
nil
{
return
err
}
// Remove sandboxes with zero containers
if
err
:=
cgc
.
evictSandboxes
();
err
!=
nil
{
if
err
:=
cgc
.
evictSandboxes
(
evictNonDeletedPods
);
err
!=
nil
{
return
err
}
...
...
pkg/kubelet/kuberuntime/kuberuntime_gc_test.go
View file @
889afa5e
This diff is collapsed.
Click to expand it.
pkg/kubelet/kuberuntime/kuberuntime_manager.go
View file @
889afa5e
...
...
@@ -877,8 +877,8 @@ func (m *kubeGenericRuntimeManager) GetNetNS(_ kubecontainer.ContainerID) (strin
}
// GarbageCollect removes dead containers using the specified container gc policy.
func
(
m
*
kubeGenericRuntimeManager
)
GarbageCollect
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
)
error
{
return
m
.
containerGC
.
GarbageCollect
(
gcPolicy
,
allSourcesReady
)
func
(
m
*
kubeGenericRuntimeManager
)
GarbageCollect
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
,
evictNonDeletedPods
bool
)
error
{
return
m
.
containerGC
.
GarbageCollect
(
gcPolicy
,
allSourcesReady
,
evictNonDeletedPods
)
}
// GetPodContainerID gets pod sandbox ID
...
...
pkg/kubelet/rkt/rkt.go
View file @
889afa5e
...
...
@@ -1955,7 +1955,7 @@ func (r *Runtime) getPodSystemdServiceFiles() ([]os.FileInfo, error) {
// - If the number of containers exceeds gcPolicy.MaxContainers,
// then containers whose ages are older than gcPolicy.minAge will
// be removed.
func
(
r
*
Runtime
)
GarbageCollect
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
)
error
{
func
(
r
*
Runtime
)
GarbageCollect
(
gcPolicy
kubecontainer
.
ContainerGCPolicy
,
allSourcesReady
bool
,
_
bool
)
error
{
var
errlist
[]
error
var
totalInactiveContainers
int
var
inactivePods
[]
*
rktapi
.
Pod
...
...
pkg/kubelet/rkt/rkt_test.go
View file @
889afa5e
...
...
@@ -1831,7 +1831,8 @@ func TestGarbageCollect(t *testing.T) {
}
allSourcesReady
:=
true
err
:=
rkt
.
GarbageCollect
(
tt
.
gcPolicy
,
allSourcesReady
)
evictNonDeletedPods
:=
false
err
:=
rkt
.
GarbageCollect
(
tt
.
gcPolicy
,
allSourcesReady
,
evictNonDeletedPods
)
assert
.
NoError
(
t
,
err
,
testCaseHint
)
sort
.
Sort
(
sortedStringList
(
tt
.
expectedCommands
))
...
...
pkg/kubelet/runonce_test.go
View file @
889afa5e
...
...
@@ -126,7 +126,7 @@ func TestRunOnce(t *testing.T) {
fakeKillPodFunc
:=
func
(
pod
*
v1
.
Pod
,
podStatus
v1
.
PodStatus
,
gracePeriodOverride
*
int64
)
error
{
return
nil
}
evictionManager
,
evictionAdmitHandler
:=
eviction
.
NewManager
(
kb
.
resourceAnalyzer
,
eviction
.
Config
{},
fakeKillPodFunc
,
nil
,
kb
.
recorder
,
nodeRef
,
kb
.
clock
)
evictionManager
,
evictionAdmitHandler
:=
eviction
.
NewManager
(
kb
.
resourceAnalyzer
,
eviction
.
Config
{},
fakeKillPodFunc
,
nil
,
nil
,
kb
.
recorder
,
nodeRef
,
kb
.
clock
)
kb
.
evictionManager
=
evictionManager
kb
.
admitHandlers
.
AddPodAdmitHandler
(
evictionAdmitHandler
)
...
...
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