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
16d09925
Unverified
Commit
16d09925
authored
Nov 07, 2018
by
k8s-ci-robot
Committed by
GitHub
Nov 07, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #69753 from wangzhen127/diff-node-status
Update kubelet node status report logic with node lease feature
parents
ac217310
98fc4a10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
225 additions
and
32 deletions
+225
-32
internal.yaml
.../app/util/config/testdata/conversion/master/internal.yaml
+1
-0
v1alpha3.yaml
.../app/util/config/testdata/conversion/master/v1alpha3.yaml
+1
-0
v1beta1.yaml
...m/app/util/config/testdata/conversion/master/v1beta1.yaml
+1
-0
defaulted.yaml
...app/util/config/testdata/defaulting/master/defaulted.yaml
+1
-0
BUILD
pkg/kubelet/BUILD
+2
-0
fuzzer.go
pkg/kubelet/apis/config/fuzzer/fuzzer.go
+1
-0
helpers_test.go
pkg/kubelet/apis/config/helpers_test.go
+1
-0
types.go
pkg/kubelet/apis/config/types.go
+9
-3
defaults.go
pkg/kubelet/apis/config/v1beta1/defaults.go
+10
-0
zz_generated.conversion.go
pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go
+2
-0
zz_generated.deepcopy.go
pkg/kubelet/apis/config/zz_generated.deepcopy.go
+1
-0
kubelet.go
pkg/kubelet/kubelet.go
+13
-4
kubelet_network.go
pkg/kubelet/kubelet_network.go
+7
-5
kubelet_node_status.go
pkg/kubelet/kubelet_node_status.go
+72
-5
kubelet_node_status_test.go
pkg/kubelet/kubelet_node_status_test.go
+0
-0
types.go
staging/src/k8s.io/kubelet/config/v1beta1/types.go
+15
-3
zz_generated.deepcopy.go
...rc/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go
+1
-0
BUILD
test/e2e/common/BUILD
+1
-0
node_lease.go
test/e2e/common/node_lease.go
+86
-12
No files found.
cmd/kubeadm/app/util/config/testdata/conversion/master/internal.yaml
View file @
16d09925
...
...
@@ -141,6 +141,7 @@ ComponentConfigs:
MaxOpenFiles
:
1000000
MaxPods
:
110
NodeLeaseDurationSeconds
:
40
NodeStatusReportFrequency
:
1m0s
NodeStatusUpdateFrequency
:
10s
OOMScoreAdj
:
-999
PodCIDR
:
"
"
...
...
cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml
View file @
16d09925
...
...
@@ -148,6 +148,7 @@ makeIPTablesUtilChains: true
maxOpenFiles
:
1000000
maxPods
:
110
nodeLeaseDurationSeconds
:
40
nodeStatusReportFrequency
:
1m0s
nodeStatusUpdateFrequency
:
10s
oomScoreAdj
:
-999
podPidsLimit
:
-1
...
...
cmd/kubeadm/app/util/config/testdata/conversion/master/v1beta1.yaml
View file @
16d09925
...
...
@@ -152,6 +152,7 @@ makeIPTablesUtilChains: true
maxOpenFiles
:
1000000
maxPods
:
110
nodeLeaseDurationSeconds
:
40
nodeStatusReportFrequency
:
1m0s
nodeStatusUpdateFrequency
:
10s
oomScoreAdj
:
-999
podPidsLimit
:
-1
...
...
cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml
View file @
16d09925
...
...
@@ -139,6 +139,7 @@ makeIPTablesUtilChains: true
maxOpenFiles
:
1000000
maxPods
:
110
nodeLeaseDurationSeconds
:
40
nodeStatusReportFrequency
:
1m0s
nodeStatusUpdateFrequency
:
10s
oomScoreAdj
:
-999
podPidsLimit
:
-1
...
...
pkg/kubelet/BUILD
View file @
16d09925
...
...
@@ -117,6 +117,7 @@ go_library(
"//pkg/volume/validation:go_default_library",
"//staging/src/k8s.io/api/authentication/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...
...
@@ -234,6 +235,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
...
...
pkg/kubelet/apis/config/fuzzer/fuzzer.go
View file @
16d09925
...
...
@@ -62,6 +62,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
obj
.
MaxPods
=
110
obj
.
PodPidsLimit
=
-
1
obj
.
NodeStatusUpdateFrequency
=
metav1
.
Duration
{
Duration
:
10
*
time
.
Second
}
obj
.
NodeStatusReportFrequency
=
metav1
.
Duration
{
Duration
:
time
.
Minute
}
obj
.
NodeLeaseDurationSeconds
=
40
obj
.
CPUManagerPolicy
=
"none"
obj
.
CPUManagerReconcilePeriod
=
obj
.
NodeStatusUpdateFrequency
...
...
pkg/kubelet/apis/config/helpers_test.go
View file @
16d09925
...
...
@@ -197,6 +197,7 @@ var (
"MaxOpenFiles"
,
"MaxPods"
,
"NodeStatusUpdateFrequency.Duration"
,
"NodeStatusReportFrequency.Duration"
,
"NodeLeaseDurationSeconds"
,
"OOMScoreAdj"
,
"PodCIDR"
,
...
...
pkg/kubelet/apis/config/types.go
View file @
16d09925
...
...
@@ -151,10 +151,16 @@ type KubeletConfiguration struct {
// streamingConnectionIdleTimeout is the maximum time a streaming connection
// can be idle before the connection is automatically closed.
StreamingConnectionIdleTimeout
metav1
.
Duration
// nodeStatusUpdateFrequency is the frequency that kubelet posts node
// status to master. Note: be cautious when changing the constant, it
// must work with nodeMonitorGracePeriod in nodecontroller.
// nodeStatusUpdateFrequency is the frequency that kubelet computes node
// status. If node lease feature is not enabled, it is also the frequency that
// kubelet posts node status to master. In that case, be cautious when
// changing the constant, it must work with nodeMonitorGracePeriod in nodecontroller.
NodeStatusUpdateFrequency
metav1
.
Duration
// nodeStatusReportFrequency is the frequency that kubelet posts node
// status to master if node status does not change. Kubelet will ignore this
// frequency and post node status immediately if any change is detected. It is
// only used when node lease feature is enabled.
NodeStatusReportFrequency
metav1
.
Duration
// nodeLeaseDurationSeconds is the duration the Kubelet will set on its corresponding Lease.
NodeLeaseDurationSeconds
int32
// imageMinimumGCAge is the minimum age for an unused image before it is
...
...
pkg/kubelet/apis/config/v1beta1/defaults.go
View file @
16d09925
...
...
@@ -107,6 +107,16 @@ func SetDefaults_KubeletConfiguration(obj *kubeletconfigv1beta1.KubeletConfigura
if
obj
.
StreamingConnectionIdleTimeout
==
zeroDuration
{
obj
.
StreamingConnectionIdleTimeout
=
metav1
.
Duration
{
Duration
:
4
*
time
.
Hour
}
}
if
obj
.
NodeStatusReportFrequency
==
zeroDuration
{
// For backward compatibility, NodeStatusReportFrequency's default value is
// set to NodeStatusUpdateFrequency if NodeStatusUpdateFrequency is set
// explicitly.
if
obj
.
NodeStatusUpdateFrequency
==
zeroDuration
{
obj
.
NodeStatusReportFrequency
=
metav1
.
Duration
{
Duration
:
time
.
Minute
}
}
else
{
obj
.
NodeStatusReportFrequency
=
obj
.
NodeStatusUpdateFrequency
}
}
if
obj
.
NodeStatusUpdateFrequency
==
zeroDuration
{
obj
.
NodeStatusUpdateFrequency
=
metav1
.
Duration
{
Duration
:
10
*
time
.
Second
}
}
...
...
pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go
View file @
16d09925
...
...
@@ -251,6 +251,7 @@ func autoConvert_v1beta1_KubeletConfiguration_To_config_KubeletConfiguration(in
out
.
ClusterDNS
=
*
(
*
[]
string
)(
unsafe
.
Pointer
(
&
in
.
ClusterDNS
))
out
.
StreamingConnectionIdleTimeout
=
in
.
StreamingConnectionIdleTimeout
out
.
NodeStatusUpdateFrequency
=
in
.
NodeStatusUpdateFrequency
out
.
NodeStatusReportFrequency
=
in
.
NodeStatusReportFrequency
out
.
NodeLeaseDurationSeconds
=
in
.
NodeLeaseDurationSeconds
out
.
ImageMinimumGCAge
=
in
.
ImageMinimumGCAge
if
err
:=
v1
.
Convert_Pointer_int32_To_int32
(
&
in
.
ImageGCHighThresholdPercent
,
&
out
.
ImageGCHighThresholdPercent
,
s
);
err
!=
nil
{
...
...
@@ -380,6 +381,7 @@ func autoConvert_config_KubeletConfiguration_To_v1beta1_KubeletConfiguration(in
out
.
ClusterDNS
=
*
(
*
[]
string
)(
unsafe
.
Pointer
(
&
in
.
ClusterDNS
))
out
.
StreamingConnectionIdleTimeout
=
in
.
StreamingConnectionIdleTimeout
out
.
NodeStatusUpdateFrequency
=
in
.
NodeStatusUpdateFrequency
out
.
NodeStatusReportFrequency
=
in
.
NodeStatusReportFrequency
out
.
NodeLeaseDurationSeconds
=
in
.
NodeLeaseDurationSeconds
out
.
ImageMinimumGCAge
=
in
.
ImageMinimumGCAge
if
err
:=
v1
.
Convert_int32_To_Pointer_int32
(
&
in
.
ImageGCHighThresholdPercent
,
&
out
.
ImageGCHighThresholdPercent
,
s
);
err
!=
nil
{
...
...
pkg/kubelet/apis/config/zz_generated.deepcopy.go
View file @
16d09925
...
...
@@ -112,6 +112,7 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
}
out
.
StreamingConnectionIdleTimeout
=
in
.
StreamingConnectionIdleTimeout
out
.
NodeStatusUpdateFrequency
=
in
.
NodeStatusUpdateFrequency
out
.
NodeStatusReportFrequency
=
in
.
NodeStatusReportFrequency
out
.
ImageMinimumGCAge
=
in
.
ImageMinimumGCAge
out
.
VolumeStatsAggPeriod
=
in
.
VolumeStatsAggPeriod
out
.
CPUManagerReconcilePeriod
=
in
.
CPUManagerReconcilePeriod
...
...
pkg/kubelet/kubelet.go
View file @
16d09925
...
...
@@ -510,6 +510,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
nodeRef
:
nodeRef
,
nodeLabels
:
nodeLabels
,
nodeStatusUpdateFrequency
:
kubeCfg
.
NodeStatusUpdateFrequency
.
Duration
,
nodeStatusReportFrequency
:
kubeCfg
.
NodeStatusReportFrequency
.
Duration
,
os
:
kubeDeps
.
OSInterface
,
oomWatcher
:
oomWatcher
,
cgroupsPerQOS
:
kubeCfg
.
CgroupsPerQOS
,
...
...
@@ -716,7 +717,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
klet
.
pleg
=
pleg
.
NewGenericPLEG
(
klet
.
containerRuntime
,
plegChannelCapacity
,
plegRelistPeriod
,
klet
.
podCache
,
clock
.
RealClock
{})
klet
.
runtimeState
=
newRuntimeState
(
maxWaitForContainerRuntime
)
klet
.
runtimeState
.
addHealthCheck
(
"PLEG"
,
klet
.
pleg
.
Healthy
)
if
err
:=
klet
.
updatePodCIDR
(
kubeCfg
.
PodCIDR
);
err
!=
nil
{
if
_
,
err
:=
klet
.
updatePodCIDR
(
kubeCfg
.
PodCIDR
);
err
!=
nil
{
glog
.
Errorf
(
"Pod CIDR update failed %v"
,
err
)
}
...
...
@@ -1035,8 +1036,9 @@ type Kubelet struct {
// used for generating ContainerStatus.
reasonCache
*
ReasonCache
// nodeStatusUpdateFrequency specifies how often kubelet posts node status to master.
// Note: be cautious when changing the constant, it must work with nodeMonitorGracePeriod
// nodeStatusUpdateFrequency specifies how often kubelet computes node status. If node lease
// feature is not enabled, it is also the frequency that kubelet posts node status to master.
// In that case, be cautious when changing the constant, it must work with nodeMonitorGracePeriod
// in nodecontroller. There are several constraints:
// 1. nodeMonitorGracePeriod must be N times more than nodeStatusUpdateFrequency, where
// N means number of retries allowed for kubelet to post node status. It is pointless
...
...
@@ -1048,6 +1050,13 @@ type Kubelet struct {
// as it takes time to gather all necessary node information.
nodeStatusUpdateFrequency
time
.
Duration
// nodeStatusUpdateFrequency is the frequency that kubelet posts node
// status to master. It is only used when node lease feature is enabled.
nodeStatusReportFrequency
time
.
Duration
// lastStatusReportTime is the time when node status was last reported.
lastStatusReportTime
time
.
Time
// syncNodeStatusMux is a lock on updating the node status, because this path is not thread-safe.
// This lock is used by Kublet.syncNodeStatus function and shouldn't be used anywhere else.
syncNodeStatusMux
sync
.
Mutex
...
...
@@ -2236,7 +2245,7 @@ func (kl *Kubelet) fastStatusUpdateOnce() {
continue
}
if
node
.
Spec
.
PodCIDR
!=
""
{
if
err
:=
kl
.
updatePodCIDR
(
node
.
Spec
.
PodCIDR
);
err
!=
nil
{
if
_
,
err
:=
kl
.
updatePodCIDR
(
node
.
Spec
.
PodCIDR
);
err
!=
nil
{
glog
.
Errorf
(
"Pod CIDR update failed %v"
,
err
)
continue
}
...
...
pkg/kubelet/kubelet_network.go
View file @
16d09925
...
...
@@ -55,26 +55,28 @@ func (kl *Kubelet) providerRequiresNetworkingConfiguration() bool {
}
// updatePodCIDR updates the pod CIDR in the runtime state if it is different
// from the current CIDR.
func
(
kl
*
Kubelet
)
updatePodCIDR
(
cidr
string
)
error
{
// from the current CIDR.
Return true if pod CIDR is actually changed.
func
(
kl
*
Kubelet
)
updatePodCIDR
(
cidr
string
)
(
bool
,
error
)
{
kl
.
updatePodCIDRMux
.
Lock
()
defer
kl
.
updatePodCIDRMux
.
Unlock
()
podCIDR
:=
kl
.
runtimeState
.
podCIDR
()
if
podCIDR
==
cidr
{
return
nil
return
false
,
nil
}
// kubelet -> generic runtime -> runtime shim -> network plugin
// docker/non-cri implementations have a passthrough UpdatePodCIDR
if
err
:=
kl
.
getRuntime
()
.
UpdatePodCIDR
(
cidr
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to update pod CIDR: %v"
,
err
)
// If updatePodCIDR would fail, theoretically pod CIDR could not change.
// But it is better to be on the safe side to still return true here.
return
true
,
fmt
.
Errorf
(
"failed to update pod CIDR: %v"
,
err
)
}
glog
.
Infof
(
"Setting Pod CIDR: %v -> %v"
,
podCIDR
,
cidr
)
kl
.
runtimeState
.
setPodCIDR
(
cidr
)
return
nil
return
true
,
nil
}
// GetPodDNS returns DNS settings for the pod.
...
...
pkg/kubelet/kubelet_node_status.go
View file @
16d09925
...
...
@@ -21,11 +21,13 @@ import (
"fmt"
"net"
goruntime
"runtime"
"sort"
"time"
"github.com/golang/glog"
"k8s.io/api/core/v1"
apiequality
"k8s.io/apimachinery/pkg/api/equality"
apierrors
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
...
...
@@ -348,8 +350,8 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) {
}
// syncNodeStatus should be called periodically from a goroutine.
// It synchronizes node status to master
, registering the kubelet first if
// necessary.
// It synchronizes node status to master
if there is any change or enough time
//
passed from the last sync, registering the kubelet first if
necessary.
func
(
kl
*
Kubelet
)
syncNodeStatus
()
{
kl
.
syncNodeStatusMux
.
Lock
()
defer
kl
.
syncNodeStatusMux
.
Unlock
()
...
...
@@ -366,7 +368,8 @@ func (kl *Kubelet) syncNodeStatus() {
}
}
// updateNodeStatus updates node status to master with retries.
// updateNodeStatus updates node status to master with retries if there is any
// change or enough time passed from the last sync.
func
(
kl
*
Kubelet
)
updateNodeStatus
()
error
{
glog
.
V
(
5
)
.
Infof
(
"Updating node status"
)
for
i
:=
0
;
i
<
nodeStatusUpdateRetry
;
i
++
{
...
...
@@ -382,7 +385,8 @@ func (kl *Kubelet) updateNodeStatus() error {
return
fmt
.
Errorf
(
"update node status exceeds retry count"
)
}
// tryUpdateNodeStatus tries to update node status to master.
// tryUpdateNodeStatus tries to update node status to master if there is any
// change or enough time passed from the last sync.
func
(
kl
*
Kubelet
)
tryUpdateNodeStatus
(
tryNumber
int
)
error
{
// In large clusters, GET and PUT operations on Node objects coming
// from here are the majority of load on apiserver and etcd.
...
...
@@ -404,18 +408,31 @@ func (kl *Kubelet) tryUpdateNodeStatus(tryNumber int) error {
return
fmt
.
Errorf
(
"nil %q node object"
,
kl
.
nodeName
)
}
podCIDRChanged
:=
false
if
node
.
Spec
.
PodCIDR
!=
""
{
if
err
:=
kl
.
updatePodCIDR
(
node
.
Spec
.
PodCIDR
);
err
!=
nil
{
// Pod CIDR could have been updated before, so we cannot rely on
// node.Spec.PodCIDR being non-empty. We also need to know if pod CIDR is
// actually changed.
if
podCIDRChanged
,
err
=
kl
.
updatePodCIDR
(
node
.
Spec
.
PodCIDR
);
err
!=
nil
{
glog
.
Errorf
(
err
.
Error
())
}
}
kl
.
setNodeStatus
(
node
)
now
:=
kl
.
clock
.
Now
()
if
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
NodeLease
)
&&
now
.
Before
(
kl
.
lastStatusReportTime
.
Add
(
kl
.
nodeStatusReportFrequency
))
{
if
!
podCIDRChanged
&&
!
nodeStatusHasChanged
(
&
originalNode
.
Status
,
&
node
.
Status
)
{
return
nil
}
}
// Patch the current status on the API server
updatedNode
,
_
,
err
:=
nodeutil
.
PatchNodeStatus
(
kl
.
heartbeatClient
.
CoreV1
(),
types
.
NodeName
(
kl
.
nodeName
),
originalNode
,
node
)
if
err
!=
nil
{
return
err
}
kl
.
lastStatusReportTime
=
now
kl
.
setLastObservedNodeAddresses
(
updatedNode
.
Status
.
Addresses
)
// If update finishes successfully, mark the volumeInUse as reportedInUse to indicate
// those volumes are already updated in the node's status
...
...
@@ -553,3 +570,53 @@ func validateNodeIP(nodeIP net.IP) error {
}
return
fmt
.
Errorf
(
"Node IP: %q not found in the host's network interfaces"
,
nodeIP
.
String
())
}
// nodeStatusHasChanged compares the original node and current node's status and
// returns true if any change happens. The heartbeat timestamp is ignored.
func
nodeStatusHasChanged
(
originalStatus
*
v1
.
NodeStatus
,
status
*
v1
.
NodeStatus
)
bool
{
if
originalStatus
==
nil
&&
status
==
nil
{
return
false
}
if
originalStatus
==
nil
||
status
==
nil
{
return
true
}
// Compare node conditions here because we need to ignore the heartbeat timestamp.
if
nodeConditionsHaveChanged
(
originalStatus
.
Conditions
,
status
.
Conditions
)
{
return
true
}
// Compare other fields of NodeStatus.
originalStatusCopy
:=
originalStatus
.
DeepCopy
()
statusCopy
:=
status
.
DeepCopy
()
originalStatusCopy
.
Conditions
=
nil
statusCopy
.
Conditions
=
nil
return
!
apiequality
.
Semantic
.
DeepEqual
(
originalStatusCopy
,
statusCopy
)
}
// nodeConditionsHaveChanged compares the original node and current node's
// conditions and returns true if any change happens. The heartbeat timestamp is
// ignored.
func
nodeConditionsHaveChanged
(
originalConditions
[]
v1
.
NodeCondition
,
conditions
[]
v1
.
NodeCondition
)
bool
{
if
len
(
originalConditions
)
!=
len
(
conditions
)
{
return
true
}
originalConditionsCopy
:=
make
([]
v1
.
NodeCondition
,
0
,
len
(
originalConditions
))
originalConditionsCopy
=
append
(
originalConditionsCopy
,
originalConditions
...
)
conditionsCopy
:=
make
([]
v1
.
NodeCondition
,
0
,
len
(
conditions
))
conditionsCopy
=
append
(
conditionsCopy
,
conditions
...
)
sort
.
SliceStable
(
originalConditionsCopy
,
func
(
i
,
j
int
)
bool
{
return
originalConditionsCopy
[
i
]
.
Type
<
originalConditionsCopy
[
j
]
.
Type
})
sort
.
SliceStable
(
conditionsCopy
,
func
(
i
,
j
int
)
bool
{
return
conditionsCopy
[
i
]
.
Type
<
conditionsCopy
[
j
]
.
Type
})
replacedheartbeatTime
:=
metav1
.
Time
{}
for
i
:=
range
conditionsCopy
{
originalConditionsCopy
[
i
]
.
LastHeartbeatTime
=
replacedheartbeatTime
conditionsCopy
[
i
]
.
LastHeartbeatTime
=
replacedheartbeatTime
if
!
apiequality
.
Semantic
.
DeepEqual
(
&
originalConditionsCopy
[
i
],
&
conditionsCopy
[
i
])
{
return
true
}
}
return
false
}
pkg/kubelet/kubelet_node_status_test.go
View file @
16d09925
This diff is collapsed.
Click to expand it.
staging/src/k8s.io/kubelet/config/v1beta1/types.go
View file @
16d09925
...
...
@@ -292,9 +292,11 @@ type KubeletConfiguration struct {
// Default: "4h"
// +optional
StreamingConnectionIdleTimeout
metav1
.
Duration
`json:"streamingConnectionIdleTimeout,omitempty"`
// nodeStatusUpdateFrequency is the frequency that kubelet posts node
// status to master. Note: be cautious when changing the constant, it
// must work with nodeMonitorGracePeriod in nodecontroller.
// nodeStatusUpdateFrequency is the frequency that kubelet computes node
// status. If node lease feature is not enabled, it is also the frequency that
// kubelet posts node status to master.
// Note: When node lease feature is not enabled, be cautious when changing the
// constant, it must work with nodeMonitorGracePeriod in nodecontroller.
// Dynamic Kubelet Config (beta): If dynamically updating this field, consider that
// it may impact node scalability, and also that the node controller's
// nodeMonitorGracePeriod must be set to N*NodeStatusUpdateFrequency,
...
...
@@ -303,6 +305,16 @@ type KubeletConfiguration struct {
// Default: "10s"
// +optional
NodeStatusUpdateFrequency
metav1
.
Duration
`json:"nodeStatusUpdateFrequency,omitempty"`
// nodeStatusReportFrequency is the frequency that kubelet posts node
// status to master if node status does not change. Kubelet will ignore this
// frequency and post node status immediately if any change is detected. It is
// only used when node lease feature is enabled. nodeStatusReportFrequency's
// default value is 1m. But if nodeStatusUpdateFrequency is set explicitly,
// nodeStatusReportFrequency's default value will be set to
// nodeStatusUpdateFrequency for backward compatibility.
// Default: "1m"
// +optional
NodeStatusReportFrequency
metav1
.
Duration
`json:"nodeStatusReportFrequency,omitempty"`
// nodeLeaseDurationSeconds is the duration the Kubelet will set on its corresponding Lease,
// when the NodeLease feature is enabled. This feature provides an indicator of node
// health by having the Kublet create and periodically renew a lease, named after the node,
...
...
staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go
View file @
16d09925
...
...
@@ -143,6 +143,7 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
}
out
.
StreamingConnectionIdleTimeout
=
in
.
StreamingConnectionIdleTimeout
out
.
NodeStatusUpdateFrequency
=
in
.
NodeStatusUpdateFrequency
out
.
NodeStatusReportFrequency
=
in
.
NodeStatusReportFrequency
out
.
ImageMinimumGCAge
=
in
.
ImageMinimumGCAge
if
in
.
ImageGCHighThresholdPercent
!=
nil
{
in
,
out
:=
&
in
.
ImageGCHighThresholdPercent
,
&
out
.
ImageGCHighThresholdPercent
...
...
test/e2e/common/BUILD
View file @
16d09925
...
...
@@ -44,6 +44,7 @@ go_library(
],
importpath = "k8s.io/kubernetes/test/e2e/common",
deps = [
"//pkg/api/v1/node:go_default_library",
"//pkg/api/v1/pod:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
...
...
test/e2e/common/node_lease.go
View file @
16d09925
...
...
@@ -23,7 +23,9 @@ import (
coordv1beta1
"k8s.io/api/coordination/v1beta1"
corev1
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
clientset
"k8s.io/client-go/kubernetes"
v1node
"k8s.io/kubernetes/pkg/api/v1/node"
"k8s.io/kubernetes/test/e2e/framework"
.
"github.com/onsi/ginkgo"
...
...
@@ -31,33 +33,41 @@ import (
)
var
_
=
framework
.
KubeDescribe
(
"[Feature:NodeLease][NodeAlphaFeature:NodeLease]"
,
func
()
{
var
nodeName
string
f
:=
framework
.
NewDefaultFramework
(
"node-lease-test"
)
BeforeEach
(
func
()
{
nodes
:=
framework
.
GetReadySchedulableNodesOrDie
(
f
.
ClientSet
)
Expect
(
len
(
nodes
.
Items
))
.
NotTo
(
BeZero
())
nodeName
=
nodes
.
Items
[
0
]
.
ObjectMeta
.
Name
})
Context
(
"when the NodeLease feature is enabled"
,
func
()
{
It
(
"the
K
ubelet should create and update a lease in the kube-node-lease namespace"
,
func
()
{
It
(
"the
k
ubelet should create and update a lease in the kube-node-lease namespace"
,
func
()
{
leaseClient
:=
f
.
ClientSet
.
CoordinationV1beta1
()
.
Leases
(
corev1
.
NamespaceNodeLease
)
var
(
err
error
lease
*
coordv1beta1
.
Lease
)
// check that lease for this Kubelet exists in the kube-node-lease namespace
By
(
"check that lease for this Kubelet exists in the kube-node-lease namespace"
)
Eventually
(
func
()
error
{
lease
,
err
=
leaseClient
.
Get
(
framework
.
TestContext
.
N
odeName
,
metav1
.
GetOptions
{})
lease
,
err
=
leaseClient
.
Get
(
n
odeName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
err
}
return
nil
},
5
*
time
.
Minute
,
5
*
time
.
Second
)
.
Should
(
BeNil
())
// check basic expectations for the lease
Expect
(
expectLease
(
lease
))
.
To
(
BeNil
())
// ensure that at least one lease renewal happens within the
// lease duration by checking for a change to renew time
Expect
(
expectLease
(
lease
,
nodeName
))
.
To
(
BeNil
())
By
(
"check that node lease is updated at least once within the lease duration"
)
Eventually
(
func
()
error
{
newLease
,
err
:=
leaseClient
.
Get
(
framework
.
TestContext
.
N
odeName
,
metav1
.
GetOptions
{})
newLease
,
err
:=
leaseClient
.
Get
(
n
odeName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
err
}
// check basic expectations for the latest lease
if
err
:=
expectLease
(
newLease
);
err
!=
nil
{
if
err
:=
expectLease
(
newLease
,
nodeName
);
err
!=
nil
{
return
err
}
// check that RenewTime has been updated on the latest lease
...
...
@@ -68,12 +78,76 @@ var _ = framework.KubeDescribe("[Feature:NodeLease][NodeAlphaFeature:NodeLease]"
}
return
nil
},
time
.
Duration
(
*
lease
.
Spec
.
LeaseDurationSeconds
)
*
time
.
Second
,
time
.
Duration
(
*
lease
.
Spec
.
LeaseDurationSeconds
/
3
)
*
time
.
Second
)
time
.
Duration
(
*
lease
.
Spec
.
LeaseDurationSeconds
/
4
)
*
time
.
Second
)
})
It
(
"the kubelet should report node status infrequently"
,
func
()
{
By
(
"wait until node is ready"
)
framework
.
WaitForNodeToBeReady
(
f
.
ClientSet
,
nodeName
,
5
*
time
.
Minute
)
By
(
"wait until there is node lease"
)
var
err
error
var
lease
*
coordv1beta1
.
Lease
Eventually
(
func
()
error
{
lease
,
err
=
f
.
ClientSet
.
CoordinationV1beta1
()
.
Leases
(
corev1
.
NamespaceNodeLease
)
.
Get
(
nodeName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
err
}
return
nil
},
5
*
time
.
Minute
,
5
*
time
.
Second
)
.
Should
(
BeNil
())
// check basic expectations for the lease
Expect
(
expectLease
(
lease
,
nodeName
))
.
To
(
BeNil
())
leaseDuration
:=
time
.
Duration
(
*
lease
.
Spec
.
LeaseDurationSeconds
)
*
time
.
Second
By
(
"verify NodeStatus report period is longer than lease duration"
)
// NodeStatus is reported from node to master when there is some change or
// enough time has passed. So for here, keep checking the time diff
// between 2 NodeStatus report, until it is longer than lease duration (
// the same as nodeMonitorGracePeriod).
heartbeatTime
:=
getNextReadyConditionHeartbeatTime
(
f
.
ClientSet
,
nodeName
,
metav1
.
Time
{})
Eventually
(
func
()
error
{
nextHeartbeatTime
:=
getNextReadyConditionHeartbeatTime
(
f
.
ClientSet
,
nodeName
,
heartbeatTime
)
if
nextHeartbeatTime
.
Time
.
After
(
heartbeatTime
.
Time
.
Add
(
leaseDuration
))
{
return
nil
}
heartbeatTime
=
nextHeartbeatTime
return
fmt
.
Errorf
(
"node status report period is shorter than lease duration"
)
// Enter next round immediately.
},
5
*
time
.
Minute
,
time
.
Nanosecond
)
.
Should
(
BeNil
())
By
(
"verify node is still in ready status even though node status report is infrequent"
)
// This check on node status is only meaningful when this e2e test is
// running as cluster e2e test, because node e2e test does not create and
// run controller manager, i.e., no node lifecycle controller.
node
,
err
:=
f
.
ClientSet
.
CoreV1
()
.
Nodes
()
.
Get
(
nodeName
,
metav1
.
GetOptions
{})
Expect
(
err
)
.
To
(
BeNil
())
_
,
readyCondition
:=
v1node
.
GetNodeCondition
(
&
node
.
Status
,
corev1
.
NodeReady
)
Expect
(
readyCondition
.
Status
)
.
To
(
Equal
(
corev1
.
ConditionTrue
))
})
})
})
func
expectLease
(
lease
*
coordv1beta1
.
Lease
)
error
{
func
getNextReadyConditionHeartbeatTime
(
clientSet
clientset
.
Interface
,
nodeName
string
,
prevHeartbeatTime
metav1
.
Time
)
metav1
.
Time
{
var
newHeartbeatTime
metav1
.
Time
Eventually
(
func
()
error
{
node
,
err
:=
clientSet
.
CoreV1
()
.
Nodes
()
.
Get
(
nodeName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
err
}
_
,
readyCondition
:=
v1node
.
GetNodeCondition
(
&
node
.
Status
,
corev1
.
NodeReady
)
Expect
(
readyCondition
.
Status
)
.
To
(
Equal
(
corev1
.
ConditionTrue
))
newHeartbeatTime
=
readyCondition
.
LastHeartbeatTime
if
prevHeartbeatTime
.
Before
(
&
newHeartbeatTime
)
{
return
nil
}
return
fmt
.
Errorf
(
"heartbeat has not changed yet"
)
},
5
*
time
.
Minute
,
5
*
time
.
Second
)
.
Should
(
BeNil
())
return
newHeartbeatTime
}
func
expectLease
(
lease
*
coordv1beta1
.
Lease
,
nodeName
string
)
error
{
// expect values for HolderIdentity, LeaseDurationSeconds, and RenewTime
if
lease
.
Spec
.
HolderIdentity
==
nil
{
return
fmt
.
Errorf
(
"Spec.HolderIdentity should not be nil"
)
...
...
@@ -85,8 +159,8 @@ func expectLease(lease *coordv1beta1.Lease) error {
return
fmt
.
Errorf
(
"Spec.RenewTime should not be nil"
)
}
// ensure that the HolderIdentity matches the node name
if
*
lease
.
Spec
.
HolderIdentity
!=
framework
.
TestContext
.
N
odeName
{
return
fmt
.
Errorf
(
"Spec.HolderIdentity (%v) should match the node name (%v)"
,
*
lease
.
Spec
.
HolderIdentity
,
framework
.
TestContext
.
N
odeName
)
if
*
lease
.
Spec
.
HolderIdentity
!=
n
odeName
{
return
fmt
.
Errorf
(
"Spec.HolderIdentity (%v) should match the node name (%v)"
,
*
lease
.
Spec
.
HolderIdentity
,
n
odeName
)
}
return
nil
}
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