{"record":{"id":"2b3ecff2701813dd","repo":"kubernetes/kops","slug":"error-excluding-node-from-load-balancer-v","errorCode":null,"errorMessage":"error excluding node from load balancer: %v","messagePattern":"error excluding node from load balancer: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/instancegroups/instancegroups.go","lineNumber":711,"sourceCode":"\t\t// The zero value would retry evictions without any delay\n\t\tEvictErrorRetryDelay: 5 * time.Second,\n\n\t\t// We want to proceed even when pods are using emptyDir volumes\n\t\tDeleteEmptyDirData: true,\n\t}\n\n\tif err := drain.RunCordonOrUncordon(helper, u.Node, true); err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error cordoning node: %v\", err)\n\t}\n\n\tif err := c.patchExcludeFromLB(ctx, u.Node); err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error excluding node from load balancer: %v\", err)\n\t}\n\n\tshouldDeregister := true\n\tif !c.Options.DeregisterControlPlaneNodes {\n\t\tif u.CloudInstanceGroup != nil && u.CloudInstanceGroup.InstanceGroup != nil {\n\t\t\trole := u.CloudInstanceGroup.InstanceGroup.Spec.Role\n\t\t\tswitch role {\n\t\t\tcase api.InstanceGroupRoleAPIServer, api.InstanceGroupRoleControlPlane:\n\t\t\t\tklog.Infof(\"skipping deregistration of instance %q, as part of instancegroup with role %q\", u.ID, role)\n\t\t\t\tshouldDeregister = false\n\t\t\t}\n\t\t}\n\t}\n\n\tif shouldDeregister {\n\t\tif err := c.Cloud.DeregisterInstance(u); err != nil {\n\t\t\treturn &DeregisterError{\n\t\t\t\terr: fmt.Errorf(\"error deregistering instance %q, node %q: %w\", u.ID, u.Node.Name, err),","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/instancegroups/instancegroups.go#L693-L729","documentation":"drainNode calls patchExcludeFromLB to add the kops.k8s.io/exclude-from-external-load-balancers label so the node is taken out of load-balancer pools before draining. A non-NotFound failure is wrapped as 'error excluding node from load balancer'.","triggerScenarios":"The label PATCH on the Node fails with a non-NotFound error: RBAC restrictions, API server timeout, or a modified webhook validating node labels on control-plane/APIServer nodes.","commonSituations":"Admission webhooks or policies (OPA/Gatekeeper) blocking label changes on nodes; API server load balancer itself pointing at the node being patched (control-plane self-hosted LB); permission errors for the acting user.","solutions":["Check webhook/policy controllers that might reject node label PATCHes and add an exemption for kops.k8s.io/* labels","Ensure RBAC allows patching nodes for the user kOps authenticates as","Retry the rolling update after confirming API server health via `kubectl get --raw /readyz`","If the API-server LB still routes to the node, update the target group/backend registration manually then continue"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"_, err := client.CoreV1().Nodes().Patch(ctx, nodeName, types.StrategicMergePatchType, []byte(`{\"metadata\":{\"labels\":{\"kops.k8s.io/exclude-from-external-load-balancers\":\"true\"}}}`), metav1.PatchOptions{})\nif err != nil && !apierrors.IsNotFound(err) {\n    return fmt.Errorf(\"pre-check LB-exclude patch failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := c.drainNode(ctx, u); err != nil {\n    if !apierrors.IsNotFound(errors.Unwrap(err)) {\n        klog.Errorf(\"exclude-from-LB failed: %v; check webhooks/RBAC\", err)\n        return err\n    }\n}","preventionTips":["Exempt kops.k8s.io/* node labels from validating webhooks","Grant node patch RBAC to the kOps identity","Check API server health before rolling updates"],"tags":["kubernetes","load-balancer","labels","rolling-update"],"backgroundTag":"kubernetes-api-request-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}