mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
clean up KubeletConfigOk condition construction
This PR cleans up the construction of the node condition and also fixes a small bug where the last transition time could be updated incorrectly when the sync failure overlay was present.
This commit is contained in:
parent
236fa894df
commit
1d59190d3e
@ -113,8 +113,12 @@ type ConfigOkCondition interface {
|
|||||||
type configOkCondition struct {
|
type configOkCondition struct {
|
||||||
// conditionMux is a mutex on the condition, alternate between setting and syncing the condition
|
// conditionMux is a mutex on the condition, alternate between setting and syncing the condition
|
||||||
conditionMux sync.Mutex
|
conditionMux sync.Mutex
|
||||||
// condition is the current ConfigOk node condition, which will be reported in the Node.status.conditions
|
// message will appear as the condition's message
|
||||||
condition *apiv1.NodeCondition
|
message string
|
||||||
|
// reason will appear as the condition's reason
|
||||||
|
reason string
|
||||||
|
// status will appear as the condition's status
|
||||||
|
status apiv1.ConditionStatus
|
||||||
// failedSyncReason is sent in place of the usual reason when the Kubelet is failing to sync the remote config
|
// failedSyncReason is sent in place of the usual reason when the Kubelet is failing to sync the remote config
|
||||||
failedSyncReason string
|
failedSyncReason string
|
||||||
// pendingCondition; write to this channel to indicate that ConfigOk needs to be synced to the API server
|
// pendingCondition; write to this channel to indicate that ConfigOk needs to be synced to the API server
|
||||||
@ -124,6 +128,9 @@ type configOkCondition struct {
|
|||||||
// NewConfigOkCondition returns a new ConfigOkCondition
|
// NewConfigOkCondition returns a new ConfigOkCondition
|
||||||
func NewConfigOkCondition() ConfigOkCondition {
|
func NewConfigOkCondition() ConfigOkCondition {
|
||||||
return &configOkCondition{
|
return &configOkCondition{
|
||||||
|
message: EmptyMessage,
|
||||||
|
reason: EmptyReason,
|
||||||
|
status: apiv1.ConditionUnknown,
|
||||||
// channels must have capacity at least 1, since we signal with non-blocking writes
|
// channels must have capacity at least 1, since we signal with non-blocking writes
|
||||||
pendingCondition: make(chan bool, 1),
|
pendingCondition: make(chan bool, 1),
|
||||||
}
|
}
|
||||||
@ -135,23 +142,23 @@ func NewConfigOkCondition() ConfigOkCondition {
|
|||||||
func (c *configOkCondition) unsafeSet(message, reason string, status apiv1.ConditionStatus) {
|
func (c *configOkCondition) unsafeSet(message, reason string, status apiv1.ConditionStatus) {
|
||||||
// We avoid an empty Message, Reason, or Status on the condition. Since we use Patch to update conditions, an empty
|
// We avoid an empty Message, Reason, or Status on the condition. Since we use Patch to update conditions, an empty
|
||||||
// field might cause a value from a previous condition to leak through, which can be very confusing.
|
// field might cause a value from a previous condition to leak through, which can be very confusing.
|
||||||
|
|
||||||
|
// message
|
||||||
if len(message) == 0 {
|
if len(message) == 0 {
|
||||||
message = EmptyMessage
|
message = EmptyMessage
|
||||||
}
|
}
|
||||||
|
c.message = message
|
||||||
|
// reason
|
||||||
if len(reason) == 0 {
|
if len(reason) == 0 {
|
||||||
reason = EmptyReason
|
reason = EmptyReason
|
||||||
}
|
}
|
||||||
|
c.reason = reason
|
||||||
|
// status
|
||||||
if len(string(status)) == 0 {
|
if len(string(status)) == 0 {
|
||||||
status = apiv1.ConditionUnknown
|
status = apiv1.ConditionUnknown
|
||||||
}
|
}
|
||||||
|
c.status = status
|
||||||
c.condition = &apiv1.NodeCondition{
|
// always poke worker after update
|
||||||
Message: message,
|
|
||||||
Reason: reason,
|
|
||||||
Status: status,
|
|
||||||
Type: apiv1.NodeKubeletConfigOk,
|
|
||||||
}
|
|
||||||
|
|
||||||
c.pokeSyncWorker()
|
c.pokeSyncWorker()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,11 +218,6 @@ func (c *configOkCondition) Sync(client clientset.Interface, nodeName string) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if c.condition == nil {
|
|
||||||
utillog.Infof("ConfigOk condition is nil, skipping ConfigOk sync")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the Node so we can check the current condition
|
// get the Node so we can check the current condition
|
||||||
node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
|
node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -223,29 +225,32 @@ func (c *configOkCondition) Sync(client clientset.Interface, nodeName string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// construct the node condition
|
||||||
|
condition := &apiv1.NodeCondition{
|
||||||
|
Type: apiv1.NodeKubeletConfigOk,
|
||||||
|
Message: c.message,
|
||||||
|
Reason: c.reason,
|
||||||
|
Status: c.status,
|
||||||
|
}
|
||||||
|
|
||||||
|
// overlay failed sync reason, if necessary
|
||||||
|
if len(c.failedSyncReason) > 0 {
|
||||||
|
condition.Reason = c.failedSyncReason
|
||||||
|
condition.Status = apiv1.ConditionFalse
|
||||||
|
}
|
||||||
|
|
||||||
// set timestamps
|
// set timestamps
|
||||||
syncTime := metav1.NewTime(time.Now())
|
syncTime := metav1.NewTime(time.Now())
|
||||||
c.condition.LastHeartbeatTime = syncTime
|
condition.LastHeartbeatTime = syncTime
|
||||||
if remote := getKubeletConfigOk(node.Status.Conditions); remote == nil || !utilequal.KubeletConfigOkEq(remote, c.condition) {
|
if remote := getKubeletConfigOk(node.Status.Conditions); remote == nil || !utilequal.KubeletConfigOkEq(remote, condition) {
|
||||||
// update transition time the first time we create the condition,
|
// update transition time the first time we create the condition,
|
||||||
// or if we are semantically changing the condition
|
// or if we are semantically changing the condition
|
||||||
c.condition.LastTransitionTime = syncTime
|
condition.LastTransitionTime = syncTime
|
||||||
} else {
|
} else {
|
||||||
// since the conditions are semantically equal, use lastTransitionTime from the condition currently on the Node
|
// since the conditions are semantically equal, use lastTransitionTime from the condition currently on the Node
|
||||||
// we need to do this because the field will always be represented in the patch generated below, and this copy
|
// we need to do this because the field will always be represented in the patch generated below, and this copy
|
||||||
// prevents nullifying the field during the patch operation
|
// prevents nullifying the field during the patch operation
|
||||||
c.condition.LastTransitionTime = remote.LastTransitionTime
|
condition.LastTransitionTime = remote.LastTransitionTime
|
||||||
}
|
|
||||||
|
|
||||||
// overlay the failedSyncReason if necessary
|
|
||||||
var condition *apiv1.NodeCondition
|
|
||||||
if len(c.failedSyncReason) > 0 {
|
|
||||||
// get a copy of the condition before we add the overlay
|
|
||||||
condition = c.condition.DeepCopy()
|
|
||||||
condition.Reason = c.failedSyncReason
|
|
||||||
condition.Status = apiv1.ConditionFalse
|
|
||||||
} else {
|
|
||||||
condition = c.condition
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate the patch
|
// generate the patch
|
||||||
|
Loading…
Reference in New Issue
Block a user