in controllers/node/node_controller.go [374:464]
func (cnc *CloudNodeController) syncNode(ctx context.Context, nodeName string) error {
curNode, err := cnc.nodeInformer.Lister().Get(nodeName)
if err != nil {
if apierrors.IsNotFound(err) {
return nil
}
return err
}
cloudTaint := getCloudTaint(curNode.Spec.Taints)
if cloudTaint == nil {
// Node object received from event had the cloud taint but was outdated,
// the node has actually already been initialized, so this sync event can be ignored.
return nil
}
klog.Infof("Initializing node %s with cloud provider", nodeName)
copyNode := curNode.DeepCopy()
providerID, err := cnc.getProviderID(ctx, copyNode)
if err != nil {
return fmt.Errorf("failed to get provider ID for node %s at cloudprovider: %v", nodeName, err)
}
instanceMetadata, err := cnc.getInstanceMetadata(ctx, providerID, copyNode)
if err != nil {
return fmt.Errorf("failed to get instance metadata for node %s: %v", nodeName, err)
}
nodeModifiers, err := cnc.getNodeModifiersFromCloudProvider(ctx, providerID, copyNode, instanceMetadata)
if err != nil {
return fmt.Errorf("failed to get node modifiers from cloud provider: %v", err)
}
nodeModifiers = append(nodeModifiers, func(n *v1.Node) {
n.Spec.Taints = excludeCloudTaint(n.Spec.Taints)
})
err = clientretry.RetryOnConflict(UpdateNodeSpecBackoff, func() error {
var curNode *v1.Node
if cnc.cloud.ProviderName() == "gce" {
// TODO(wlan0): Move this logic to the route controller using the node taint instead of condition
// Since there are node taints, do we still need this?
// This condition marks the node as unusable until routes are initialized in the cloud provider
if err := nodeutil.SetNodeCondition(cnc.kubeClient, types.NodeName(nodeName), v1.NodeCondition{
Type: v1.NodeNetworkUnavailable,
Status: v1.ConditionTrue,
Reason: "NoRouteCreated",
Message: "Node created without a route",
LastTransitionTime: metav1.Now(),
}); err != nil {
return err
}
// fetch latest node from API server since GCE-specific condition was set and informer cache may be stale
curNode, err = cnc.kubeClient.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
if err != nil {
return err
}
} else {
curNode, err = cnc.nodeInformer.Lister().Get(nodeName)
if err != nil {
return err
}
}
newNode := curNode.DeepCopy()
for _, modify := range nodeModifiers {
modify(newNode)
}
_, err = cnc.kubeClient.CoreV1().Nodes().Update(context.TODO(), newNode, metav1.UpdateOptions{})
if err != nil {
return err
}
// After adding, call UpdateNodeAddress to set the CloudProvider provided IPAddresses
// So that users do not see any significant delay in IP addresses being filled into the node
cnc.updateNodeAddress(ctx, newNode, instanceMetadata)
klog.Infof("Successfully initialized node %s with cloud provider", nodeName)
return nil
})
if err != nil {
return err
}
cnc.recorder.Event(copyNode, v1.EventTypeNormal, "Synced", "Node synced successfully")
return nil
}