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
fd1f19fc
Commit
fd1f19fc
authored
May 23, 2018
by
David Ashpole
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add metadata to kubelet eviction event annotations
parent
8f4674d2
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
58 additions
and
18 deletions
+58
-18
test_utils.go
pkg/controller/testutil/test_utils.go
+5
-0
helpers.go
pkg/kubelet/container/helpers.go
+7
-0
eviction_manager.go
pkg/kubelet/eviction/eviction_manager.go
+7
-6
helpers.go
pkg/kubelet/eviction/helpers.go
+19
-5
event.go
staging/src/k8s.io/client-go/tools/record/event.go
+15
-7
fake.go
staging/src/k8s.io/client-go/tools/record/fake.go
+4
-0
BUILD
test/e2e_node/BUILD
+1
-0
eviction_test.go
test/e2e_node/eviction_test.go
+0
-0
No files found.
pkg/controller/testutil/test_utils.go
View file @
fd1f19fc
...
...
@@ -365,6 +365,11 @@ func (f *FakeRecorder) Eventf(obj runtime.Object, eventtype, reason, messageFmt
func
(
f
*
FakeRecorder
)
PastEventf
(
obj
runtime
.
Object
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
}
// AnnotatedEventf emits a fake formatted event to the fake recorder
func
(
f
*
FakeRecorder
)
AnnotatedEventf
(
obj
runtime
.
Object
,
annotations
map
[
string
]
string
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
f
.
Eventf
(
obj
,
eventtype
,
reason
,
messageFmt
,
args
)
}
func
(
f
*
FakeRecorder
)
generateEvent
(
obj
runtime
.
Object
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
message
string
)
{
f
.
Lock
()
defer
f
.
Unlock
()
...
...
pkg/kubelet/container/helpers.go
View file @
fd1f19fc
...
...
@@ -193,6 +193,13 @@ func (irecorder *innerEventRecorder) PastEventf(object runtime.Object, timestamp
}
}
func
(
irecorder
*
innerEventRecorder
)
AnnotatedEventf
(
object
runtime
.
Object
,
annotations
map
[
string
]
string
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
if
ref
,
ok
:=
irecorder
.
shouldRecordEvent
(
object
);
ok
{
irecorder
.
recorder
.
AnnotatedEventf
(
ref
,
annotations
,
eventtype
,
reason
,
messageFmt
,
args
...
)
}
}
// Pod must not be nil.
func
IsHostNetworkPod
(
pod
*
v1
.
Pod
)
bool
{
return
pod
.
Spec
.
HostNetwork
...
...
pkg/kubelet/eviction/eviction_manager.go
View file @
fd1f19fc
...
...
@@ -429,7 +429,8 @@ func (m *managerImpl) synchronize(diskInfoProvider DiskInfoProvider, podFunc Act
if
!
isHardEvictionThreshold
(
thresholdToReclaim
)
{
gracePeriodOverride
=
m
.
config
.
MaxPodGracePeriodSeconds
}
if
m
.
evictPod
(
pod
,
gracePeriodOverride
,
evictionMessage
(
resourceToReclaim
,
pod
,
statsFunc
))
{
message
,
annotations
:=
evictionMessage
(
resourceToReclaim
,
pod
,
statsFunc
)
if
m
.
evictPod
(
pod
,
gracePeriodOverride
,
message
,
annotations
)
{
return
[]
*
v1
.
Pod
{
pod
}
}
}
...
...
@@ -534,7 +535,7 @@ func (m *managerImpl) emptyDirLimitEviction(podStats statsapi.PodStats, pod *v1.
used
:=
podVolumeUsed
[
pod
.
Spec
.
Volumes
[
i
]
.
Name
]
if
used
!=
nil
&&
size
!=
nil
&&
size
.
Sign
()
==
1
&&
used
.
Cmp
(
*
size
)
>
0
{
// the emptyDir usage exceeds the size limit, evict the pod
return
m
.
evictPod
(
pod
,
0
,
fmt
.
Sprintf
(
emptyDirMessage
,
pod
.
Spec
.
Volumes
[
i
]
.
Name
,
size
.
String
()))
return
m
.
evictPod
(
pod
,
0
,
fmt
.
Sprintf
(
emptyDirMessage
,
pod
.
Spec
.
Volumes
[
i
]
.
Name
,
size
.
String
())
,
nil
)
}
}
}
...
...
@@ -566,7 +567,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat
podEphemeralStorageLimit
:=
podLimits
[
v1
.
ResourceEphemeralStorage
]
if
podEphemeralStorageTotalUsage
.
Cmp
(
podEphemeralStorageLimit
)
>
0
{
// the total usage of pod exceeds the total size limit of containers, evict the pod
return
m
.
evictPod
(
pod
,
0
,
fmt
.
Sprintf
(
podEphemeralStorageMessage
,
podEphemeralStorageLimit
.
String
()))
return
m
.
evictPod
(
pod
,
0
,
fmt
.
Sprintf
(
podEphemeralStorageMessage
,
podEphemeralStorageLimit
.
String
())
,
nil
)
}
return
false
}
...
...
@@ -588,7 +589,7 @@ func (m *managerImpl) containerEphemeralStorageLimitEviction(podStats statsapi.P
if
ephemeralStorageThreshold
,
ok
:=
thresholdsMap
[
containerStat
.
Name
];
ok
{
if
ephemeralStorageThreshold
.
Cmp
(
*
containerUsed
)
<
0
{
return
m
.
evictPod
(
pod
,
0
,
fmt
.
Sprintf
(
containerEphemeralStorageMessage
,
containerStat
.
Name
,
ephemeralStorageThreshold
.
String
()))
return
m
.
evictPod
(
pod
,
0
,
fmt
.
Sprintf
(
containerEphemeralStorageMessage
,
containerStat
.
Name
,
ephemeralStorageThreshold
.
String
())
,
nil
)
}
}
...
...
@@ -596,7 +597,7 @@ func (m *managerImpl) containerEphemeralStorageLimitEviction(podStats statsapi.P
return
false
}
func
(
m
*
managerImpl
)
evictPod
(
pod
*
v1
.
Pod
,
gracePeriodOverride
int64
,
evictMsg
string
)
bool
{
func
(
m
*
managerImpl
)
evictPod
(
pod
*
v1
.
Pod
,
gracePeriodOverride
int64
,
evictMsg
string
,
annotations
map
[
string
]
string
)
bool
{
// If the pod is marked as critical and static, and support for critical pod annotations is enabled,
// do not evict such pods. Static pods are not re-admitted after evictions.
// https://github.com/kubernetes/kubernetes/issues/40573 has more details.
...
...
@@ -611,7 +612,7 @@ func (m *managerImpl) evictPod(pod *v1.Pod, gracePeriodOverride int64, evictMsg
Reason
:
Reason
,
}
// record that we are evicting the pod
m
.
recorder
.
Eventf
(
pod
,
v1
.
EventTypeWarning
,
Reason
,
evictMsg
)
m
.
recorder
.
AnnotatedEventf
(
pod
,
annotations
,
v1
.
EventTypeWarning
,
Reason
,
evictMsg
)
// this is a blocking call and should only return when the pod and its containers are killed.
err
:=
m
.
killPodFunc
(
pod
,
status
,
&
gracePeriodOverride
)
if
err
!=
nil
{
...
...
pkg/kubelet/eviction/helpers.go
View file @
fd1f19fc
...
...
@@ -55,6 +55,12 @@ const (
// this prevents constantly updating the memcg notifier if synchronize
// is run frequently.
notifierRefreshInterval
=
10
*
time
.
Second
// OffendingContainersKey is the key in eviction event annotations for the list of container names which exceeded their requests
OffendingContainersKey
=
"offending_containers"
// OffendingContainersUsageKey is the key in eviction event annotations for the list of usage of containers which exceeded their requests
OffendingContainersUsageKey
=
"offending_containers_usage"
// StarvedResourceKey is the key for the starved resource in eviction event annotations
StarvedResourceKey
=
"starved_resource"
)
var
(
...
...
@@ -1053,12 +1059,15 @@ func buildSignalToNodeReclaimFuncs(imageGC ImageGC, containerGC ContainerGC, wit
return
signalToReclaimFunc
}
// evictionMessage constructs a useful message about why an eviction occurred
func
evictionMessage
(
resourceToReclaim
v1
.
ResourceName
,
pod
*
v1
.
Pod
,
stats
statsFunc
)
string
{
message
:=
fmt
.
Sprintf
(
message
,
resourceToReclaim
)
// evictionMessage constructs a useful message about why an eviction occurred, and annotations to provide metadata about the eviction
func
evictionMessage
(
resourceToReclaim
v1
.
ResourceName
,
pod
*
v1
.
Pod
,
stats
statsFunc
)
(
message
string
,
annotations
map
[
string
]
string
)
{
annotations
=
make
(
map
[
string
]
string
)
message
=
fmt
.
Sprintf
(
message
,
resourceToReclaim
)
containers
:=
[]
string
{}
containerUsage
:=
[]
string
{}
podStats
,
ok
:=
stats
(
pod
)
if
!
ok
{
return
message
return
}
for
_
,
containerStats
:=
range
podStats
.
Containers
{
for
_
,
container
:=
range
pod
.
Spec
.
Containers
{
...
...
@@ -1077,11 +1086,16 @@ func evictionMessage(resourceToReclaim v1.ResourceName, pod *v1.Pod, stats stats
}
if
usage
!=
nil
&&
usage
.
Cmp
(
requests
)
>
0
{
message
+=
fmt
.
Sprintf
(
containerMessage
,
container
.
Name
,
usage
.
String
(),
requests
.
String
())
containers
=
append
(
containers
,
container
.
Name
)
containerUsage
=
append
(
containerUsage
,
usage
.
String
())
}
}
}
}
return
message
annotations
[
OffendingContainersKey
]
=
strings
.
Join
(
containers
,
","
)
annotations
[
OffendingContainersUsageKey
]
=
strings
.
Join
(
containerUsage
,
","
)
annotations
[
StarvedResourceKey
]
=
string
(
resourceToReclaim
)
return
}
// thresholdStopCh is a ThresholdStopCh which can only be closed after notifierRefreshInterval time has passed
...
...
staging/src/k8s.io/client-go/tools/record/event.go
View file @
fd1f19fc
...
...
@@ -72,6 +72,9 @@ type EventRecorder interface {
// PastEventf is just like Eventf, but with an option to specify the event's 'timestamp' field.
PastEventf
(
object
runtime
.
Object
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
// AnnotatedEventf is just like eventf, but with annotations attached
AnnotatedEventf
(
object
runtime
.
Object
,
annotations
map
[
string
]
string
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
}
// EventBroadcaster knows how to receive events and send them to any EventSink, watcher, or log.
...
...
@@ -250,7 +253,7 @@ type recorderImpl struct {
clock
clock
.
Clock
}
func
(
recorder
*
recorderImpl
)
generateEvent
(
object
runtime
.
Object
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
message
string
)
{
func
(
recorder
*
recorderImpl
)
generateEvent
(
object
runtime
.
Object
,
annotations
map
[
string
]
string
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
message
string
)
{
ref
,
err
:=
ref
.
GetReference
(
recorder
.
scheme
,
object
)
if
err
!=
nil
{
glog
.
Errorf
(
"Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v' '%v'"
,
object
,
err
,
eventtype
,
reason
,
message
)
...
...
@@ -262,7 +265,7 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp met
return
}
event
:=
recorder
.
makeEvent
(
ref
,
eventtype
,
reason
,
message
)
event
:=
recorder
.
makeEvent
(
ref
,
annotations
,
eventtype
,
reason
,
message
)
event
.
Source
=
recorder
.
source
go
func
()
{
...
...
@@ -281,7 +284,7 @@ func validateEventType(eventtype string) bool {
}
func
(
recorder
*
recorderImpl
)
Event
(
object
runtime
.
Object
,
eventtype
,
reason
,
message
string
)
{
recorder
.
generateEvent
(
object
,
metav1
.
Now
(),
eventtype
,
reason
,
message
)
recorder
.
generateEvent
(
object
,
nil
,
metav1
.
Now
(),
eventtype
,
reason
,
message
)
}
func
(
recorder
*
recorderImpl
)
Eventf
(
object
runtime
.
Object
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
...
...
@@ -289,10 +292,14 @@ func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, m
}
func
(
recorder
*
recorderImpl
)
PastEventf
(
object
runtime
.
Object
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
recorder
.
generateEvent
(
object
,
timestamp
,
eventtype
,
reason
,
fmt
.
Sprintf
(
messageFmt
,
args
...
))
recorder
.
generateEvent
(
object
,
nil
,
timestamp
,
eventtype
,
reason
,
fmt
.
Sprintf
(
messageFmt
,
args
...
))
}
func
(
recorder
*
recorderImpl
)
AnnotatedEventf
(
object
runtime
.
Object
,
annotations
map
[
string
]
string
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
recorder
.
generateEvent
(
object
,
annotations
,
metav1
.
Now
(),
eventtype
,
reason
,
fmt
.
Sprintf
(
messageFmt
,
args
...
))
}
func
(
recorder
*
recorderImpl
)
makeEvent
(
ref
*
v1
.
ObjectReference
,
eventtype
,
reason
,
message
string
)
*
v1
.
Event
{
func
(
recorder
*
recorderImpl
)
makeEvent
(
ref
*
v1
.
ObjectReference
,
annotations
map
[
string
]
string
,
eventtype
,
reason
,
message
string
)
*
v1
.
Event
{
t
:=
metav1
.
Time
{
Time
:
recorder
.
clock
.
Now
()}
namespace
:=
ref
.
Namespace
if
namespace
==
""
{
...
...
@@ -300,8 +307,9 @@ func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, eventtype, reas
}
return
&
v1
.
Event
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"%v.%x"
,
ref
.
Name
,
t
.
UnixNano
()),
Namespace
:
namespace
,
Name
:
fmt
.
Sprintf
(
"%v.%x"
,
ref
.
Name
,
t
.
UnixNano
()),
Namespace
:
namespace
,
Annotations
:
annotations
,
},
InvolvedObject
:
*
ref
,
Reason
:
reason
,
...
...
staging/src/k8s.io/client-go/tools/record/fake.go
View file @
fd1f19fc
...
...
@@ -45,6 +45,10 @@ func (f *FakeRecorder) Eventf(object runtime.Object, eventtype, reason, messageF
func
(
f
*
FakeRecorder
)
PastEventf
(
object
runtime
.
Object
,
timestamp
metav1
.
Time
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
}
func
(
f
*
FakeRecorder
)
AnnotatedEventf
(
object
runtime
.
Object
,
annotations
map
[
string
]
string
,
eventtype
,
reason
,
messageFmt
string
,
args
...
interface
{})
{
f
.
Eventf
(
object
,
eventtype
,
reason
,
messageFmt
,
args
)
}
// NewFakeRecorder creates new fake event recorder with event channel with
// buffer of given size.
func
NewFakeRecorder
(
bufferSize
int
)
*
FakeRecorder
{
...
...
test/e2e_node/BUILD
View file @
fd1f19fc
...
...
@@ -152,6 +152,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
...
...
test/e2e_node/eviction_test.go
View file @
fd1f19fc
This diff is collapsed.
Click to expand it.
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