// setNodeDiskPressureCondition for the node. // TODO: this needs to move somewhere centralized... func (kl *Kubelet) setNodeDiskPressureCondition(node *v1.Node) { currentTime := metav1.NewTime(kl.clock.Now()) var condition *v1.NodeCondition // Check if NodeDiskPressure 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.NodeDiskPressure { condition = &node.Status.Conditions[i] } } newCondition := false // If the NodeDiskPressure condition doesn't exist, create one if condition == nil { condition = &v1.NodeCondition{ Type: v1.NodeDiskPressure, 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 NodeDiskPressure 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 disk pressure or not. if kl.evictionManager.IsUnderDiskPressure() { if condition.Status != v1.ConditionTrue { condition.Status = v1.ConditionTrue condition.Reason = "KubeletHasDiskPressure" condition.Message = "kubelet has disk pressure" condition.LastTransitionTime = currentTime kl.recordNodeStatusEvent(v1.EventTypeNormal, "NodeHasDiskPressure") } } else { if condition.Status != v1.ConditionFalse { condition.Status = v1.ConditionFalse condition.Reason = "KubeletHasNoDiskPressure" condition.Message = "kubelet has no disk pressure" condition.LastTransitionTime = currentTime kl.recordNodeStatusEvent(v1.EventTypeNormal, "NodeHasNoDiskPressure") } } if newCondition { node.Status.Conditions = append(node.Status.Conditions, *condition) } }
// Set OODCondition for the node. func (kl *Kubelet) setNodeOODCondition(node *v1.Node) { currentTime := metav1.NewTime(kl.clock.Now()) var nodeOODCondition *v1.NodeCondition // Check if NodeOutOfDisk 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.NodeOutOfDisk { nodeOODCondition = &node.Status.Conditions[i] } } newOODCondition := false // If the NodeOutOfDisk condition doesn't exist, create one. if nodeOODCondition == nil { nodeOODCondition = &v1.NodeCondition{ Type: v1.NodeOutOfDisk, Status: v1.ConditionUnknown, } // nodeOODCondition cannot be appended to node.Status.Conditions here because it gets // copied to the slice. So if we append nodeOODCondition to the slice here none of the // updates we make to nodeOODCondition below are reflected in the slice. newOODCondition = true } // Update the heartbeat time irrespective of all the conditions. nodeOODCondition.LastHeartbeatTime = currentTime // Note: The conditions below take care of the case when a new NodeOutOfDisk 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 // nodeOODCondition.Status != v1.ConditionTrue or // nodeOODCondition.Status != v1.ConditionFalse in the conditions below depending on whether // the kubelet is out of disk or not. if kl.isOutOfDisk() { if nodeOODCondition.Status != v1.ConditionTrue { nodeOODCondition.Status = v1.ConditionTrue nodeOODCondition.Reason = "KubeletOutOfDisk" nodeOODCondition.Message = "out of disk space" nodeOODCondition.LastTransitionTime = currentTime kl.recordNodeStatusEvent(v1.EventTypeNormal, "NodeOutOfDisk") } } else { if nodeOODCondition.Status != v1.ConditionFalse { // Update the out of disk condition when the condition status is unknown even if we // are within the outOfDiskTransitionFrequency duration. We do this to set the // condition status correctly at kubelet startup. if nodeOODCondition.Status == v1.ConditionUnknown || kl.clock.Since(nodeOODCondition.LastTransitionTime.Time) >= kl.outOfDiskTransitionFrequency { nodeOODCondition.Status = v1.ConditionFalse nodeOODCondition.Reason = "KubeletHasSufficientDisk" nodeOODCondition.Message = "kubelet has sufficient disk space available" nodeOODCondition.LastTransitionTime = currentTime kl.recordNodeStatusEvent(v1.EventTypeNormal, "NodeHasSufficientDisk") } else { glog.Infof("Node condition status for OutOfDisk is false, but last transition time is less than %s", kl.outOfDiskTransitionFrequency) } } } if newOODCondition { node.Status.Conditions = append(node.Status.Conditions, *nodeOODCondition) } }
// Set Ready condition for the node. func (kl *Kubelet) setNodeReadyCondition(node *v1.Node) { // 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 currentTime := metav1.NewTime(kl.clock.Now()) var newNodeReadyCondition v1.NodeCondition rs := append(kl.runtimeState.runtimeErrors(), kl.runtimeState.networkErrors()...) if len(rs) == 0 { newNodeReadyCondition = v1.NodeCondition{ Type: v1.NodeReady, Status: v1.ConditionTrue, Reason: "KubeletReady", Message: "kubelet is posting ready status", LastHeartbeatTime: currentTime, } } else { newNodeReadyCondition = v1.NodeCondition{ Type: v1.NodeReady, Status: v1.ConditionFalse, Reason: "KubeletNotReady", Message: strings.Join(rs, ","), LastHeartbeatTime: currentTime, } } // Append AppArmor status if it's enabled. // TODO(timstclair): This is a temporary message until node feature reporting is added. if newNodeReadyCondition.Status == v1.ConditionTrue && kl.appArmorValidator != nil && kl.appArmorValidator.ValidateHost() == nil { newNodeReadyCondition.Message = fmt.Sprintf("%s. AppArmor enabled", newNodeReadyCondition.Message) } // Record any soft requirements that were not met in the container manager. status := kl.containerManager.Status() if status.SoftRequirements != nil { newNodeReadyCondition.Message = fmt.Sprintf("%s. WARNING: %s", newNodeReadyCondition.Message, status.SoftRequirements.Error()) } readyConditionUpdated := false needToRecordEvent := false for i := range node.Status.Conditions { if node.Status.Conditions[i].Type == v1.NodeReady { if node.Status.Conditions[i].Status == newNodeReadyCondition.Status { newNodeReadyCondition.LastTransitionTime = node.Status.Conditions[i].LastTransitionTime } else { newNodeReadyCondition.LastTransitionTime = currentTime needToRecordEvent = true } node.Status.Conditions[i] = newNodeReadyCondition readyConditionUpdated = true break } } if !readyConditionUpdated { newNodeReadyCondition.LastTransitionTime = currentTime node.Status.Conditions = append(node.Status.Conditions, newNodeReadyCondition) } if needToRecordEvent { if newNodeReadyCondition.Status == v1.ConditionTrue { kl.recordNodeStatusEvent(v1.EventTypeNormal, events.NodeReady) } else { kl.recordNodeStatusEvent(v1.EventTypeNormal, events.NodeNotReady) glog.Infof("Node became not ready: %+v", newNodeReadyCondition) } } }