mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-13 11:25:19 +00:00
kubelet: report NodeReady last in status list
Addresses a version skew issue where the last condition status is always evaluated as the NodeReady status. As a workaround force the NodeReady condition to be the last in the list of node conditions. ref: https://github.com/kubernetes/kubernetes/issues/16961
This commit is contained in:
@@ -2773,52 +2773,6 @@ func (kl *Kubelet) setNodeStatus(node *api.Node) error {
|
||||
node.Status.DaemonEndpoints = *kl.daemonEndpoints
|
||||
|
||||
currentTime := unversioned.Now()
|
||||
var newNodeReadyCondition api.NodeCondition
|
||||
var oldNodeReadyConditionStatus api.ConditionStatus
|
||||
if rs := kl.runtimeState.errors(); len(rs) == 0 {
|
||||
newNodeReadyCondition = api.NodeCondition{
|
||||
Type: api.NodeReady,
|
||||
Status: api.ConditionTrue,
|
||||
Reason: "KubeletReady",
|
||||
Message: "kubelet is posting ready status",
|
||||
LastHeartbeatTime: currentTime,
|
||||
}
|
||||
} else {
|
||||
newNodeReadyCondition = api.NodeCondition{
|
||||
Type: api.NodeReady,
|
||||
Status: api.ConditionFalse,
|
||||
Reason: "KubeletNotReady",
|
||||
Message: strings.Join(rs, ","),
|
||||
LastHeartbeatTime: currentTime,
|
||||
}
|
||||
}
|
||||
|
||||
updated := false
|
||||
for i := range node.Status.Conditions {
|
||||
if node.Status.Conditions[i].Type == api.NodeReady {
|
||||
oldNodeReadyConditionStatus = node.Status.Conditions[i].Status
|
||||
if oldNodeReadyConditionStatus == newNodeReadyCondition.Status {
|
||||
newNodeReadyCondition.LastTransitionTime = node.Status.Conditions[i].LastTransitionTime
|
||||
} else {
|
||||
newNodeReadyCondition.LastTransitionTime = currentTime
|
||||
}
|
||||
node.Status.Conditions[i] = newNodeReadyCondition
|
||||
updated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !updated {
|
||||
newNodeReadyCondition.LastTransitionTime = currentTime
|
||||
node.Status.Conditions = append(node.Status.Conditions, newNodeReadyCondition)
|
||||
}
|
||||
if !updated || oldNodeReadyConditionStatus != newNodeReadyCondition.Status {
|
||||
if newNodeReadyCondition.Status == api.ConditionTrue {
|
||||
kl.recordNodeStatusEvent(api.EventTypeNormal, kubecontainer.NodeReady)
|
||||
} else {
|
||||
kl.recordNodeStatusEvent(api.EventTypeNormal, kubecontainer.NodeNotReady)
|
||||
}
|
||||
}
|
||||
|
||||
var nodeOODCondition *api.NodeCondition
|
||||
|
||||
// Check if NodeOutOfDisk condition already exists and if it does, just pick it up for update.
|
||||
@@ -2873,6 +2827,55 @@ func (kl *Kubelet) setNodeStatus(node *api.Node) error {
|
||||
node.Status.Conditions = append(node.Status.Conditions, *nodeOODCondition)
|
||||
}
|
||||
|
||||
// NOTE(aaronlevy): NodeReady condition needs to be the last in the list of node conditions.
|
||||
// This is due to an issue with version skewed kubelet and master components.
|
||||
// ref: https://github.com/kubernetes/kubernetes/issues/16961
|
||||
var newNodeReadyCondition api.NodeCondition
|
||||
var oldNodeReadyConditionStatus api.ConditionStatus
|
||||
if rs := kl.runtimeState.errors(); len(rs) == 0 {
|
||||
newNodeReadyCondition = api.NodeCondition{
|
||||
Type: api.NodeReady,
|
||||
Status: api.ConditionTrue,
|
||||
Reason: "KubeletReady",
|
||||
Message: "kubelet is posting ready status",
|
||||
LastHeartbeatTime: currentTime,
|
||||
}
|
||||
} else {
|
||||
newNodeReadyCondition = api.NodeCondition{
|
||||
Type: api.NodeReady,
|
||||
Status: api.ConditionFalse,
|
||||
Reason: "KubeletNotReady",
|
||||
Message: strings.Join(rs, ","),
|
||||
LastHeartbeatTime: currentTime,
|
||||
}
|
||||
}
|
||||
|
||||
updated := false
|
||||
for i := range node.Status.Conditions {
|
||||
if node.Status.Conditions[i].Type == api.NodeReady {
|
||||
oldNodeReadyConditionStatus = node.Status.Conditions[i].Status
|
||||
if oldNodeReadyConditionStatus == newNodeReadyCondition.Status {
|
||||
newNodeReadyCondition.LastTransitionTime = node.Status.Conditions[i].LastTransitionTime
|
||||
} else {
|
||||
newNodeReadyCondition.LastTransitionTime = currentTime
|
||||
}
|
||||
node.Status.Conditions[i] = newNodeReadyCondition
|
||||
updated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !updated {
|
||||
newNodeReadyCondition.LastTransitionTime = currentTime
|
||||
node.Status.Conditions = append(node.Status.Conditions, newNodeReadyCondition)
|
||||
}
|
||||
if !updated || oldNodeReadyConditionStatus != newNodeReadyCondition.Status {
|
||||
if newNodeReadyCondition.Status == api.ConditionTrue {
|
||||
kl.recordNodeStatusEvent(api.EventTypeNormal, kubecontainer.NodeReady)
|
||||
} else {
|
||||
kl.recordNodeStatusEvent(api.EventTypeNormal, kubecontainer.NodeNotReady)
|
||||
}
|
||||
}
|
||||
|
||||
if oldNodeUnschedulable != node.Spec.Unschedulable {
|
||||
if node.Spec.Unschedulable {
|
||||
kl.recordNodeStatusEvent(api.EventTypeNormal, kubecontainer.NodeNotSchedulable)
|
||||
|
||||
Reference in New Issue
Block a user