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
9a787531
Commit
9a787531
authored
Dec 18, 2017
by
Da K. Ma
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated PID pressure node condition.
Signed-off-by:
Da K. Ma
<
madaxa@cn.ibm.com
>
parent
3b407025
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
297 additions
and
6 deletions
+297
-6
types.go
pkg/kubelet/apis/stats/v1alpha1/types.go
+13
-0
types.go
pkg/kubelet/eviction/api/types.go
+2
-0
eviction_manager.go
pkg/kubelet/eviction/eviction_manager.go
+9
-1
helpers.go
pkg/kubelet/eviction/helpers.go
+12
-0
types.go
pkg/kubelet/eviction/types.go
+3
-0
kubelet_node_status.go
pkg/kubelet/kubelet_node_status.go
+57
-0
kubelet_node_status_test.go
pkg/kubelet/kubelet_node_status_test.go
+34
-1
server_test.go
pkg/kubelet/server/server_test.go
+4
-3
handler.go
pkg/kubelet/server/stats/handler.go
+3
-0
summary.go
pkg/kubelet/server/stats/summary.go
+5
-0
summary_test.go
pkg/kubelet/server/stats/summary_test.go
+9
-0
mock_stats_provider.go
pkg/kubelet/server/stats/testing/mock_stats_provider.go
+23
-0
BUILD
pkg/kubelet/stats/BUILD
+36
-1
stats_provider.go
pkg/kubelet/stats/stats_provider.go
+5
-0
stats_provider_linux.go
pkg/kubelet/stats/stats_provider_linux.go
+48
-0
stats_provider_unsupported.go
pkg/kubelet/stats/stats_provider_unsupported.go
+27
-0
types.go
staging/src/k8s.io/api/core/v1/types.go
+2
-0
summary_test.go
test/e2e_node/summary_test.go
+5
-0
No files found.
pkg/kubelet/apis/stats/v1alpha1/types.go
View file @
9a787531
...
@@ -56,6 +56,19 @@ type NodeStats struct {
...
@@ -56,6 +56,19 @@ type NodeStats struct {
// Stats about the underlying container runtime.
// Stats about the underlying container runtime.
// +optional
// +optional
Runtime
*
RuntimeStats
`json:"runtime,omitempty"`
Runtime
*
RuntimeStats
`json:"runtime,omitempty"`
// Stats about the rlimit of system.
// +optional
Rlimit
*
RlimitStats
`json:"rlimit,omitempty"`
}
// RlimitStats are stats rlimit of OS.
type
RlimitStats
struct
{
Time
metav1
.
Time
`json:"time"`
// The max PID of OS.
MaxPID
*
int64
`json:"maxpid,omitempty"`
// The number of running process in the OS.
NumOfRunningProcesses
*
int64
`json:"curproc,omitempty"`
}
}
// RuntimeStats are stats pertaining to the underlying container runtime.
// RuntimeStats are stats pertaining to the underlying container runtime.
...
...
pkg/kubelet/eviction/api/types.go
View file @
9a787531
...
@@ -40,6 +40,8 @@ const (
...
@@ -40,6 +40,8 @@ const (
SignalAllocatableMemoryAvailable
Signal
=
"allocatableMemory.available"
SignalAllocatableMemoryAvailable
Signal
=
"allocatableMemory.available"
// SignalAllocatableNodeFsAvailable is amount of local storage available for pod allocation
// SignalAllocatableNodeFsAvailable is amount of local storage available for pod allocation
SignalAllocatableNodeFsAvailable
Signal
=
"allocatableNodeFs.available"
SignalAllocatableNodeFsAvailable
Signal
=
"allocatableNodeFs.available"
// SignalPIDAvailable is amount of PID available for pod allocation
SignalPIDAvailable
Signal
=
"pid.available"
)
)
// ThresholdOperator is the operator used to express a Threshold.
// ThresholdOperator is the operator used to express a Threshold.
...
...
pkg/kubelet/eviction/eviction_manager.go
View file @
9a787531
...
@@ -101,7 +101,8 @@ func NewManager(
...
@@ -101,7 +101,8 @@ func NewManager(
containerGC
ContainerGC
,
containerGC
ContainerGC
,
recorder
record
.
EventRecorder
,
recorder
record
.
EventRecorder
,
nodeRef
*
v1
.
ObjectReference
,
nodeRef
*
v1
.
ObjectReference
,
clock
clock
.
Clock
)
(
Manager
,
lifecycle
.
PodAdmitHandler
)
{
clock
clock
.
Clock
,
)
(
Manager
,
lifecycle
.
PodAdmitHandler
)
{
manager
:=
&
managerImpl
{
manager
:=
&
managerImpl
{
clock
:
clock
,
clock
:
clock
,
killPodFunc
:
killPodFunc
,
killPodFunc
:
killPodFunc
,
...
@@ -176,6 +177,13 @@ func (m *managerImpl) IsUnderDiskPressure() bool {
...
@@ -176,6 +177,13 @@ func (m *managerImpl) IsUnderDiskPressure() bool {
return
hasNodeCondition
(
m
.
nodeConditions
,
v1
.
NodeDiskPressure
)
return
hasNodeCondition
(
m
.
nodeConditions
,
v1
.
NodeDiskPressure
)
}
}
// IsUnderPIDPressure returns true if the node is under PID pressure.
func
(
m
*
managerImpl
)
IsUnderPIDPressure
()
bool
{
m
.
RLock
()
defer
m
.
RUnlock
()
return
hasNodeCondition
(
m
.
nodeConditions
,
v1
.
NodePIDPressure
)
}
func
startMemoryThresholdNotifier
(
thresholds
[]
evictionapi
.
Threshold
,
observations
signalObservations
,
hard
bool
,
handler
thresholdNotifierHandlerFunc
)
error
{
func
startMemoryThresholdNotifier
(
thresholds
[]
evictionapi
.
Threshold
,
observations
signalObservations
,
hard
bool
,
handler
thresholdNotifierHandlerFunc
)
error
{
for
_
,
threshold
:=
range
thresholds
{
for
_
,
threshold
:=
range
thresholds
{
if
threshold
.
Signal
!=
evictionapi
.
SignalMemoryAvailable
||
hard
!=
isHardEvictionThreshold
(
threshold
)
{
if
threshold
.
Signal
!=
evictionapi
.
SignalMemoryAvailable
||
hard
!=
isHardEvictionThreshold
(
threshold
)
{
...
...
pkg/kubelet/eviction/helpers.go
View file @
9a787531
...
@@ -73,6 +73,7 @@ func init() {
...
@@ -73,6 +73,7 @@ func init() {
signalToNodeCondition
[
evictionapi
.
SignalNodeFsAvailable
]
=
v1
.
NodeDiskPressure
signalToNodeCondition
[
evictionapi
.
SignalNodeFsAvailable
]
=
v1
.
NodeDiskPressure
signalToNodeCondition
[
evictionapi
.
SignalImageFsInodesFree
]
=
v1
.
NodeDiskPressure
signalToNodeCondition
[
evictionapi
.
SignalImageFsInodesFree
]
=
v1
.
NodeDiskPressure
signalToNodeCondition
[
evictionapi
.
SignalNodeFsInodesFree
]
=
v1
.
NodeDiskPressure
signalToNodeCondition
[
evictionapi
.
SignalNodeFsInodesFree
]
=
v1
.
NodeDiskPressure
signalToNodeCondition
[
evictionapi
.
SignalPIDAvailable
]
=
v1
.
NodePIDPressure
// map signals to resources (and vice-versa)
// map signals to resources (and vice-versa)
signalToResource
=
map
[
evictionapi
.
Signal
]
v1
.
ResourceName
{}
signalToResource
=
map
[
evictionapi
.
Signal
]
v1
.
ResourceName
{}
...
@@ -764,6 +765,17 @@ func makeSignalObservations(summaryProvider stats.SummaryProvider, capacityProvi
...
@@ -764,6 +765,17 @@ func makeSignalObservations(summaryProvider stats.SummaryProvider, capacityProvi
}
}
}
}
if
rlimit
:=
summary
.
Node
.
Rlimit
;
rlimit
!=
nil
{
if
rlimit
.
NumOfRunningProcesses
!=
nil
&&
rlimit
.
MaxPID
!=
nil
{
available
:=
int64
(
*
rlimit
.
MaxPID
)
-
int64
(
*
rlimit
.
NumOfRunningProcesses
)
result
[
evictionapi
.
SignalPIDAvailable
]
=
signalObservation
{
available
:
resource
.
NewQuantity
(
available
,
resource
.
BinarySI
),
capacity
:
resource
.
NewQuantity
(
int64
(
*
rlimit
.
MaxPID
),
resource
.
BinarySI
),
time
:
rlimit
.
Time
,
}
}
}
if
memoryAllocatableCapacity
,
ok
:=
capacityProvider
.
GetCapacity
()[
v1
.
ResourceMemory
];
ok
{
if
memoryAllocatableCapacity
,
ok
:=
capacityProvider
.
GetCapacity
()[
v1
.
ResourceMemory
];
ok
{
memoryAllocatableAvailable
:=
memoryAllocatableCapacity
.
Copy
()
memoryAllocatableAvailable
:=
memoryAllocatableCapacity
.
Copy
()
if
reserved
,
exists
:=
capacityProvider
.
GetNodeAllocatableReservation
()[
v1
.
ResourceMemory
];
exists
{
if
reserved
,
exists
:=
capacityProvider
.
GetNodeAllocatableReservation
()[
v1
.
ResourceMemory
];
exists
{
...
...
pkg/kubelet/eviction/types.go
View file @
9a787531
...
@@ -60,6 +60,9 @@ type Manager interface {
...
@@ -60,6 +60,9 @@ type Manager interface {
// IsUnderDiskPressure returns true if the node is under disk pressure.
// IsUnderDiskPressure returns true if the node is under disk pressure.
IsUnderDiskPressure
()
bool
IsUnderDiskPressure
()
bool
// IsUnderPIDPressure returns true if the node is under PID pressure.
IsUnderPIDPressure
()
bool
}
}
// DiskInfoProvider is responsible for informing the manager how disk is configured.
// DiskInfoProvider is responsible for informing the manager how disk is configured.
...
...
pkg/kubelet/kubelet_node_status.go
View file @
9a787531
...
@@ -852,6 +852,62 @@ func (kl *Kubelet) setNodeMemoryPressureCondition(node *v1.Node) {
...
@@ -852,6 +852,62 @@ func (kl *Kubelet) setNodeMemoryPressureCondition(node *v1.Node) {
}
}
}
}
// setNodePIDPressureCondition for the node.
// TODO: this needs to move somewhere centralized...
func
(
kl
*
Kubelet
)
setNodePIDPressureCondition
(
node
*
v1
.
Node
)
{
currentTime
:=
metav1
.
NewTime
(
kl
.
clock
.
Now
())
var
condition
*
v1
.
NodeCondition
// Check if NodePIDPressure condition already exists and if it does, just pick it up for update.
for
i
:=
range
node
.
Status
.
Conditions
{
if
node
.
Status
.
Conditions
[
i
]
.
Type
==
v1
.
NodePIDPressure
{
condition
=
&
node
.
Status
.
Conditions
[
i
]
}
}
newCondition
:=
false
// If the NodePIDPressure condition doesn't exist, create one
if
condition
==
nil
{
condition
=
&
v1
.
NodeCondition
{
Type
:
v1
.
NodePIDPressure
,
Status
:
v1
.
ConditionUnknown
,
}
// cannot be appended to node.Status.Conditions here because it gets
// copied to the slice. So if we append to the slice here none of the
// updates we make below are reflected in the slice.
newCondition
=
true
}
// Update the heartbeat time
condition
.
LastHeartbeatTime
=
currentTime
// Note: The conditions below take care of the case when a new NodePIDPressure condition is
// created and as well as the case when the condition already exists. When a new condition
// is created its status is set to v1.ConditionUnknown which matches either
// condition.Status != v1.ConditionTrue or
// condition.Status != v1.ConditionFalse in the conditions below depending on whether
// the kubelet is under PID pressure or not.
if
kl
.
evictionManager
.
IsUnderPIDPressure
()
{
if
condition
.
Status
!=
v1
.
ConditionTrue
{
condition
.
Status
=
v1
.
ConditionTrue
condition
.
Reason
=
"KubeletHasInsufficientPID"
condition
.
Message
=
"kubelet has insufficient PID available"
condition
.
LastTransitionTime
=
currentTime
kl
.
recordNodeStatusEvent
(
v1
.
EventTypeNormal
,
"NodeHasInsufficientPID"
)
}
}
else
if
condition
.
Status
!=
v1
.
ConditionFalse
{
condition
.
Status
=
v1
.
ConditionFalse
condition
.
Reason
=
"KubeletHasSufficientPID"
condition
.
Message
=
"kubelet has sufficient PID available"
condition
.
LastTransitionTime
=
currentTime
kl
.
recordNodeStatusEvent
(
v1
.
EventTypeNormal
,
"NodeHasSufficientPID"
)
}
if
newCondition
{
node
.
Status
.
Conditions
=
append
(
node
.
Status
.
Conditions
,
*
condition
)
}
}
// setNodeDiskPressureCondition for the node.
// setNodeDiskPressureCondition for the node.
// TODO: this needs to move somewhere centralized...
// TODO: this needs to move somewhere centralized...
func
(
kl
*
Kubelet
)
setNodeDiskPressureCondition
(
node
*
v1
.
Node
)
{
func
(
kl
*
Kubelet
)
setNodeDiskPressureCondition
(
node
*
v1
.
Node
)
{
...
@@ -994,6 +1050,7 @@ func (kl *Kubelet) defaultNodeStatusFuncs() []func(*v1.Node) error {
...
@@ -994,6 +1050,7 @@ func (kl *Kubelet) defaultNodeStatusFuncs() []func(*v1.Node) error {
withoutError
(
kl
.
setNodeOODCondition
),
withoutError
(
kl
.
setNodeOODCondition
),
withoutError
(
kl
.
setNodeMemoryPressureCondition
),
withoutError
(
kl
.
setNodeMemoryPressureCondition
),
withoutError
(
kl
.
setNodeDiskPressureCondition
),
withoutError
(
kl
.
setNodeDiskPressureCondition
),
withoutError
(
kl
.
setNodePIDPressureCondition
),
withoutError
(
kl
.
setNodeReadyCondition
),
withoutError
(
kl
.
setNodeReadyCondition
),
withoutError
(
kl
.
setNodeVolumesInUseStatus
),
withoutError
(
kl
.
setNodeVolumesInUseStatus
),
withoutError
(
kl
.
recordNodeSchedulableEvent
),
withoutError
(
kl
.
recordNodeSchedulableEvent
),
...
...
pkg/kubelet/kubelet_node_status_test.go
View file @
9a787531
...
@@ -280,6 +280,14 @@ func TestUpdateNewNodeStatus(t *testing.T) {
...
@@ -280,6 +280,14 @@ func TestUpdateNewNodeStatus(t *testing.T) {
LastTransitionTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
},
},
{
{
Type
:
v1
.
NodePIDPressure
,
Status
:
v1
.
ConditionFalse
,
Reason
:
"KubeletHasSufficientPID"
,
Message
:
fmt
.
Sprintf
(
"kubelet has sufficient PID available"
),
LastHeartbeatTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
},
{
Type
:
v1
.
NodeReady
,
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
Status
:
v1
.
ConditionTrue
,
Reason
:
"KubeletReady"
,
Reason
:
"KubeletReady"
,
...
@@ -335,7 +343,8 @@ func TestUpdateNewNodeStatus(t *testing.T) {
...
@@ -335,7 +343,8 @@ func TestUpdateNewNodeStatus(t *testing.T) {
}
}
// Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961
// Version skew workaround. See: https://github.com/kubernetes/kubernetes/issues/16961
assert
.
Equal
(
t
,
v1
.
NodeReady
,
updatedNode
.
Status
.
Conditions
[
len
(
updatedNode
.
Status
.
Conditions
)
-
1
]
.
Type
,
"NotReady should be last"
)
assert
.
Equal
(
t
,
v1
.
NodeReady
,
updatedNode
.
Status
.
Conditions
[
len
(
updatedNode
.
Status
.
Conditions
)
-
1
]
.
Type
,
"NotReady should be last"
)
assert
.
Len
(
t
,
updatedNode
.
Status
.
Images
,
maxImagesInNodeStatus
)
assert
.
Len
(
t
,
updatedNode
.
Status
.
Images
,
maxImagesInNodeStatus
)
assert
.
True
(
t
,
apiequality
.
Semantic
.
DeepEqual
(
expectedNode
,
updatedNode
),
"%s"
,
diff
.
ObjectDiff
(
expectedNode
,
updatedNode
))
assert
.
True
(
t
,
apiequality
.
Semantic
.
DeepEqual
(
expectedNode
,
updatedNode
),
"%s"
,
diff
.
ObjectDiff
(
expectedNode
,
updatedNode
))
}
}
...
@@ -388,6 +397,14 @@ func TestUpdateExistingNodeStatus(t *testing.T) {
...
@@ -388,6 +397,14 @@ func TestUpdateExistingNodeStatus(t *testing.T) {
LastTransitionTime
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
},
},
{
{
Type
:
v1
.
NodePIDPressure
,
Status
:
v1
.
ConditionFalse
,
Reason
:
"KubeletHasSufficientPID"
,
Message
:
fmt
.
Sprintf
(
"kubelet has sufficient PID available"
),
LastHeartbeatTime
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
LastTransitionTime
:
metav1
.
Date
(
2012
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
),
},
{
Type
:
v1
.
NodeReady
,
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
Status
:
v1
.
ConditionTrue
,
Reason
:
"KubeletReady"
,
Reason
:
"KubeletReady"
,
...
@@ -455,6 +472,14 @@ func TestUpdateExistingNodeStatus(t *testing.T) {
...
@@ -455,6 +472,14 @@ func TestUpdateExistingNodeStatus(t *testing.T) {
LastTransitionTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
},
},
{
{
Type
:
v1
.
NodePIDPressure
,
Status
:
v1
.
ConditionFalse
,
Reason
:
"KubeletHasSufficientPID"
,
Message
:
fmt
.
Sprintf
(
"kubelet has sufficient PID available"
),
LastHeartbeatTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
},
{
Type
:
v1
.
NodeReady
,
Type
:
v1
.
NodeReady
,
Status
:
v1
.
ConditionTrue
,
Status
:
v1
.
ConditionTrue
,
Reason
:
"KubeletReady"
,
Reason
:
"KubeletReady"
,
...
@@ -650,6 +675,14 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) {
...
@@ -650,6 +675,14 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) {
LastHeartbeatTime
:
metav1
.
Time
{},
LastHeartbeatTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
},
},
{
Type
:
v1
.
NodePIDPressure
,
Status
:
v1
.
ConditionFalse
,
Reason
:
"KubeletHasSufficientPID"
,
Message
:
fmt
.
Sprintf
(
"kubelet has sufficient PID available"
),
LastHeartbeatTime
:
metav1
.
Time
{},
LastTransitionTime
:
metav1
.
Time
{},
},
{},
//placeholder
{},
//placeholder
},
},
NodeInfo
:
v1
.
NodeSystemInfo
{
NodeInfo
:
v1
.
NodeSystemInfo
{
...
...
pkg/kubelet/server/server_test.go
View file @
9a787531
...
@@ -173,9 +173,10 @@ func (fk *fakeKubelet) ListVolumesForPod(podUID types.UID) (map[string]volume.Vo
...
@@ -173,9 +173,10 @@ func (fk *fakeKubelet) ListVolumesForPod(podUID types.UID) (map[string]volume.Vo
return
map
[
string
]
volume
.
Volume
{},
true
return
map
[
string
]
volume
.
Volume
{},
true
}
}
func
(
_
*
fakeKubelet
)
RootFsStats
()
(
*
statsapi
.
FsStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
RootFsStats
()
(
*
statsapi
.
FsStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
ListPodStats
()
([]
statsapi
.
PodStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
ListPodStats
()
([]
statsapi
.
PodStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
ImageFsStats
()
(
*
statsapi
.
FsStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
ImageFsStats
()
(
*
statsapi
.
FsStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
RlimitStats
()
(
*
statsapi
.
RlimitStats
,
error
)
{
return
nil
,
nil
}
func
(
_
*
fakeKubelet
)
GetCgroupStats
(
cgroupName
string
,
updateStats
bool
)
(
*
statsapi
.
ContainerStats
,
*
statsapi
.
NetworkStats
,
error
)
{
func
(
_
*
fakeKubelet
)
GetCgroupStats
(
cgroupName
string
,
updateStats
bool
)
(
*
statsapi
.
ContainerStats
,
*
statsapi
.
NetworkStats
,
error
)
{
return
nil
,
nil
,
nil
return
nil
,
nil
,
nil
}
}
...
...
pkg/kubelet/server/stats/handler.go
View file @
9a787531
...
@@ -78,6 +78,9 @@ type StatsProvider interface {
...
@@ -78,6 +78,9 @@ type StatsProvider interface {
ListVolumesForPod
(
podUID
types
.
UID
)
(
map
[
string
]
volume
.
Volume
,
bool
)
ListVolumesForPod
(
podUID
types
.
UID
)
(
map
[
string
]
volume
.
Volume
,
bool
)
// GetPods returns the specs of all the pods running on this node.
// GetPods returns the specs of all the pods running on this node.
GetPods
()
[]
*
v1
.
Pod
GetPods
()
[]
*
v1
.
Pod
// RlimitStats returns the rlimit stats of system.
RlimitStats
()
(
*
statsapi
.
RlimitStats
,
error
)
}
}
type
handler
struct
{
type
handler
struct
{
...
...
pkg/kubelet/server/stats/summary.go
View file @
9a787531
...
@@ -67,6 +67,10 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error)
...
@@ -67,6 +67,10 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to list pod stats: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to list pod stats: %v"
,
err
)
}
}
rlimit
,
err
:=
sp
.
provider
.
RlimitStats
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get rlimit stats: %v"
,
err
)
}
nodeStats
:=
statsapi
.
NodeStats
{
nodeStats
:=
statsapi
.
NodeStats
{
NodeName
:
node
.
Name
,
NodeName
:
node
.
Name
,
...
@@ -76,6 +80,7 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error)
...
@@ -76,6 +80,7 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error)
StartTime
:
rootStats
.
StartTime
,
StartTime
:
rootStats
.
StartTime
,
Fs
:
rootFsStats
,
Fs
:
rootFsStats
,
Runtime
:
&
statsapi
.
RuntimeStats
{
ImageFs
:
imageFsStats
},
Runtime
:
&
statsapi
.
RuntimeStats
{
ImageFs
:
imageFsStats
},
Rlimit
:
rlimit
,
}
}
systemContainers
:=
map
[
string
]
string
{
systemContainers
:=
map
[
string
]
string
{
...
...
pkg/kubelet/server/stats/summary_test.go
View file @
9a787531
...
@@ -58,6 +58,7 @@ func TestSummaryProvider(t *testing.T) {
...
@@ -58,6 +58,7 @@ func TestSummaryProvider(t *testing.T) {
"/misc"
:
{
cs
:
getContainerStats
(),
ns
:
getNetworkStats
()},
"/misc"
:
{
cs
:
getContainerStats
(),
ns
:
getNetworkStats
()},
"/kubelet"
:
{
cs
:
getContainerStats
(),
ns
:
getNetworkStats
()},
"/kubelet"
:
{
cs
:
getContainerStats
(),
ns
:
getNetworkStats
()},
}
}
rlimitStats
=
getRlimitStats
()
)
)
assert
:=
assert
.
New
(
t
)
assert
:=
assert
.
New
(
t
)
...
@@ -69,6 +70,7 @@ func TestSummaryProvider(t *testing.T) {
...
@@ -69,6 +70,7 @@ func TestSummaryProvider(t *testing.T) {
On
(
"ListPodStats"
)
.
Return
(
podStats
,
nil
)
.
On
(
"ListPodStats"
)
.
Return
(
podStats
,
nil
)
.
On
(
"ImageFsStats"
)
.
Return
(
imageFsStats
,
nil
)
.
On
(
"ImageFsStats"
)
.
Return
(
imageFsStats
,
nil
)
.
On
(
"RootFsStats"
)
.
Return
(
rootFsStats
,
nil
)
.
On
(
"RootFsStats"
)
.
Return
(
rootFsStats
,
nil
)
.
On
(
"RlimitStats"
)
.
Return
(
rlimitStats
,
nil
)
.
On
(
"GetCgroupStats"
,
"/"
,
true
)
.
Return
(
cgroupStatsMap
[
"/"
]
.
cs
,
cgroupStatsMap
[
"/"
]
.
ns
,
nil
)
.
On
(
"GetCgroupStats"
,
"/"
,
true
)
.
Return
(
cgroupStatsMap
[
"/"
]
.
cs
,
cgroupStatsMap
[
"/"
]
.
ns
,
nil
)
.
On
(
"GetCgroupStats"
,
"/runtime"
,
false
)
.
Return
(
cgroupStatsMap
[
"/runtime"
]
.
cs
,
cgroupStatsMap
[
"/runtime"
]
.
ns
,
nil
)
.
On
(
"GetCgroupStats"
,
"/runtime"
,
false
)
.
Return
(
cgroupStatsMap
[
"/runtime"
]
.
cs
,
cgroupStatsMap
[
"/runtime"
]
.
ns
,
nil
)
.
On
(
"GetCgroupStats"
,
"/misc"
,
false
)
.
Return
(
cgroupStatsMap
[
"/misc"
]
.
cs
,
cgroupStatsMap
[
"/misc"
]
.
ns
,
nil
)
.
On
(
"GetCgroupStats"
,
"/misc"
,
false
)
.
Return
(
cgroupStatsMap
[
"/misc"
]
.
cs
,
cgroupStatsMap
[
"/misc"
]
.
ns
,
nil
)
.
...
@@ -141,3 +143,10 @@ func getNetworkStats() *statsapi.NetworkStats {
...
@@ -141,3 +143,10 @@ func getNetworkStats() *statsapi.NetworkStats {
f
.
Fuzz
(
v
)
f
.
Fuzz
(
v
)
return
v
return
v
}
}
func
getRlimitStats
()
*
statsapi
.
RlimitStats
{
f
:=
fuzz
.
New
()
.
NilChance
(
0
)
v
:=
&
statsapi
.
RlimitStats
{}
f
.
Fuzz
(
v
)
return
v
}
pkg/kubelet/server/stats/testing/mock_stats_provider.go
View file @
9a787531
...
@@ -278,3 +278,26 @@ func (_m *StatsProvider) RootFsStats() (*v1alpha1.FsStats, error) {
...
@@ -278,3 +278,26 @@ func (_m *StatsProvider) RootFsStats() (*v1alpha1.FsStats, error) {
return
r0
,
r1
return
r0
,
r1
}
}
// RlimitStats provides a mock function with given fields:
func
(
_m
*
StatsProvider
)
RlimitStats
()
(
*
v1alpha1
.
RlimitStats
,
error
)
{
ret
:=
_m
.
Called
()
var
r0
*
v1alpha1
.
RlimitStats
if
rf
,
ok
:=
ret
.
Get
(
0
)
.
(
func
()
*
v1alpha1
.
RlimitStats
);
ok
{
r0
=
rf
()
}
else
{
if
ret
.
Get
(
0
)
!=
nil
{
r0
=
ret
.
Get
(
0
)
.
(
*
v1alpha1
.
RlimitStats
)
}
}
var
r1
error
if
rf
,
ok
:=
ret
.
Get
(
1
)
.
(
func
()
error
);
ok
{
r1
=
rf
()
}
else
{
r1
=
ret
.
Error
(
1
)
}
return
r0
,
r1
}
pkg/kubelet/stats/BUILD
View file @
9a787531
...
@@ -7,7 +7,42 @@ go_library(
...
@@ -7,7 +7,42 @@ go_library(
"cri_stats_provider.go",
"cri_stats_provider.go",
"helper.go",
"helper.go",
"stats_provider.go",
"stats_provider.go",
],
] + select({
"@io_bazel_rules_go//go/platform:android": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"stats_provider_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"stats_provider_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"stats_provider_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/kubelet/stats",
importpath = "k8s.io/kubernetes/pkg/kubelet/stats",
visibility = ["//visibility:public"],
visibility = ["//visibility:public"],
deps = [
deps = [
...
...
pkg/kubelet/stats/stats_provider.go
View file @
9a787531
...
@@ -77,6 +77,7 @@ type StatsProvider struct {
...
@@ -77,6 +77,7 @@ type StatsProvider struct {
podManager
kubepod
.
Manager
podManager
kubepod
.
Manager
runtimeCache
kubecontainer
.
RuntimeCache
runtimeCache
kubecontainer
.
RuntimeCache
containerStatsProvider
containerStatsProvider
rlimitStatsProvider
}
}
// containerStatsProvider is an interface that provides the stats of the
// containerStatsProvider is an interface that provides the stats of the
...
@@ -86,6 +87,10 @@ type containerStatsProvider interface {
...
@@ -86,6 +87,10 @@ type containerStatsProvider interface {
ImageFsStats
()
(
*
statsapi
.
FsStats
,
error
)
ImageFsStats
()
(
*
statsapi
.
FsStats
,
error
)
}
}
type
rlimitStatsProvider
interface
{
RlimitStats
()
(
*
statsapi
.
RlimitStats
,
error
)
}
// GetCgroupStats returns the stats of the cgroup with the cgroupName. Note that
// GetCgroupStats returns the stats of the cgroup with the cgroupName. Note that
// this function doesn't generate filesystem stats.
// this function doesn't generate filesystem stats.
func
(
p
*
StatsProvider
)
GetCgroupStats
(
cgroupName
string
,
updateStats
bool
)
(
*
statsapi
.
ContainerStats
,
*
statsapi
.
NetworkStats
,
error
)
{
func
(
p
*
StatsProvider
)
GetCgroupStats
(
cgroupName
string
,
updateStats
bool
)
(
*
statsapi
.
ContainerStats
,
*
statsapi
.
NetworkStats
,
error
)
{
...
...
pkg/kubelet/stats/stats_provider_linux.go
0 → 100644
View file @
9a787531
// +build linux
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
stats
import
(
"io/ioutil"
"strconv"
"syscall"
"time"
"k8s.io/apimachinery/pkg/apis/meta/v1"
statsapi
"k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
)
func
(
p
*
StatsProvider
)
RlimitStats
()
(
*
statsapi
.
RlimitStats
,
error
)
{
rlimit
:=
&
statsapi
.
RlimitStats
{}
if
content
,
err
:=
ioutil
.
ReadFile
(
"/proc/sys/kernel/pid_max"
);
err
==
nil
{
if
maxPid
,
err
:=
strconv
.
ParseInt
(
string
(
content
[
:
len
(
content
)
-
1
]),
10
,
64
);
err
==
nil
{
rlimit
.
MaxPID
=
&
maxPid
}
}
var
info
syscall
.
Sysinfo_t
syscall
.
Sysinfo
(
&
info
)
procs
:=
int64
(
info
.
Procs
)
rlimit
.
NumOfRunningProcesses
=
&
procs
rlimit
.
Time
=
v1
.
NewTime
(
time
.
Now
())
return
rlimit
,
nil
}
pkg/kubelet/stats/stats_provider_unsupported.go
0 → 100644
View file @
9a787531
// +build !linux
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
stats
import
(
statsapi
"k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
)
func
(
p
*
StatsProvider
)
RlimitStats
()
(
*
statsapi
.
RlimitStats
,
error
)
{
return
nil
,
nil
}
staging/src/k8s.io/api/core/v1/types.go
View file @
9a787531
...
@@ -3944,6 +3944,8 @@ const (
...
@@ -3944,6 +3944,8 @@ const (
NodeMemoryPressure
NodeConditionType
=
"MemoryPressure"
NodeMemoryPressure
NodeConditionType
=
"MemoryPressure"
// NodeDiskPressure means the kubelet is under pressure due to insufficient available disk.
// NodeDiskPressure means the kubelet is under pressure due to insufficient available disk.
NodeDiskPressure
NodeConditionType
=
"DiskPressure"
NodeDiskPressure
NodeConditionType
=
"DiskPressure"
// NodePIDPressure means the kubelet is under pressure due to insufficient available PID.
NodePIDPressure
NodeConditionType
=
"PIDPressure"
// NodeNetworkUnavailable means that network for the node is not correctly configured.
// NodeNetworkUnavailable means that network for the node is not correctly configured.
NodeNetworkUnavailable
NodeConditionType
=
"NetworkUnavailable"
NodeNetworkUnavailable
NodeConditionType
=
"NetworkUnavailable"
// NodeConfigOK indicates whether the kubelet is correctly configured
// NodeConfigOK indicates whether the kubelet is correctly configured
...
...
test/e2e_node/summary_test.go
View file @
9a787531
...
@@ -277,6 +277,11 @@ var _ = framework.KubeDescribe("Summary API", func() {
...
@@ -277,6 +277,11 @@ var _ = framework.KubeDescribe("Summary API", func() {
"InodesUsed"
:
bounded
(
0
,
1E8
),
"InodesUsed"
:
bounded
(
0
,
1E8
),
}),
}),
}),
}),
"Rlimit"
:
ptrMatchAllFields
(
gstruct
.
Fields
{
"Time"
:
recent
(
maxStatsAge
),
"MaxPID"
:
bounded
(
0
,
1E8
),
"NumOfRunningProcesses"
:
bounded
(
0
,
1E8
),
}),
}),
}),
// Ignore extra pods since the tests run in parallel.
// Ignore extra pods since the tests run in parallel.
"Pods"
:
gstruct
.
MatchElements
(
summaryObjectID
,
gstruct
.
IgnoreExtras
,
gstruct
.
Elements
{
"Pods"
:
gstruct
.
MatchElements
(
summaryObjectID
,
gstruct
.
IgnoreExtras
,
gstruct
.
Elements
{
...
...
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