Handle NICs without VM associations gracefully#10164
Conversation
|
|
|
Welcome @cgiradkar! |
|
Hi @cgiradkar. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Regular contributors should join the org to skip this step. Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: cgiradkar The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
/easycla |
7b65272 to
f55ea6c
Compare
|
@feiskyer @nilo19 @andyzhangx would you be able to have a look at this PR please? |
|
will check. |
|
@nilo19 can I get a ok-to-test in the meanwhile. This bug is having some impact in my code, so I'd thankful if you review this small PR sooner. Thanks |
marek-veber
left a comment
There was a problem hiding this comment.
The fix is directionally correct and solves a real user-facing issue. I'd want to see:
- Logging added to the VMSS paths for parity with VMSS Flex
- At least one test per new branch (especially the ensureBackendPoolDeleted skip)
- A quick audit of other GetNodeNameByIPConfigurationID callers
Concerns:
- Insufficient test coverage. Only the existing TestGetVMManagementTypeByIPConfigurationID test was updated. The new behavior in these functions lacks test cases:
- GetNodeNameByIPConfigurationID — no test for the ManagedByUnknownVMSet early return
- ensureBackendPoolDeleted — no test for the nodeName == "" skip
- getNodeInformationByIPConfigurationID — no test for the empty vmName path
- Callers of GetNodeNameByIPConfigurationID beyond ensureBackendPoolDeleted. The PR adds an empty-string return for ManagedByUnknownVMSet, and ensureBackendPoolDeleted handles it with a continue. But if there are other callers of GetNodeNameByIPConfigurationID elsewhere in the codebase, they may not expect ("", "", nil) and could misbehave (e.g., passing an empty node name to a downstream function). This should be audited.
- ManagedByUnknownVMSet semantics are overloaded. Before this PR, ManagedByUnknownVMSet with a non-nil error meant "something went wrong." Now it's also used (with nil error) to mean "NIC exists but no VM yet." This dual meaning could confuse future readers. A dedicated constant like ManagedByNoVM or a comment clarifying the nil-error variant would improve clarity.
| continue | ||
| } | ||
| if nodeName == "" { | ||
| continue |
There was a problem hiding this comment.
IMHO: Some logger.Info(...) will be useful here.
| } | ||
|
|
||
| if vmManagementType == ManagedByUnknownVMSet { | ||
| return "", "", nil |
There was a problem hiding this comment.
IMHO: Some logger.Info(...) will be useful here.
f55ea6c to
a9aac12
Compare
|
|
/ok-to-test |
a9aac12 to
0865d71
Compare
This change addresses scenarios where NICs exist but have no attached VM, preventing errors during load balancer operations. The fix returns empty node names instead of errors, allowing calling code to skip these entries. Key changes: - Return empty string from GetVMNameByIPConfigurationName for unattached NICs - Add ManagedByUnknownVMSet handling in GetNodeNameByIPConfigurationID paths - Add logging (V2) when skipping nodes due to missing VM associations - Guard all GetNodeNameByIPConfigurationID callers against empty node names - Add comprehensive test coverage for all new code paths (VMSS, Flex, callers) - Document ManagedByUnknownVMSet dual semantics (error vs orphaned NIC) Fixes issue where backend pool reconciliation would fail when encountering NICs created but not yet attached to VMs during cluster scaling operations. Signed-off-by: Chetan Giradkar <cgiradka@redhat.com>
0865d71 to
c6a74a2
Compare
|
/retest |
| // Return empty when VM association is missing | ||
| if nic.Properties == nil || nic.Properties.VirtualMachine == nil || nic.Properties.VirtualMachine.ID == nil { | ||
| return "", fmt.Errorf("failed to get vm ID of nic %s", ptr.Deref(nic.Name, "")) | ||
| return "", nil |
There was a problem hiding this comment.
Do you manually create the nic? When will the nic has no vm association? If this is a problem we must have been received a lot of tickets, but we haven't. May I know if there is a special use case from your side?
There was a problem hiding this comment.
A customer had reported that when creating a Kubernetes service of type LoadBalancer, the operation fails if any VMs in the node pool are still provisioning or stuck in creation. The expectation is that the load balancer should skip VMs that are not yet ready and add them later once they complete provisioning, rather than failing the entire operation.
SyncLoadBalancerFailed
Error syncing load balancer: failed to ensure load balancer: failed to get vm name by ip config ID /subscriptions/.../xxxx-xxxx-xxxx-nic/ipConfigurations/pipConfig: failed to get vm ID of xxxx-xxxx-xxxx-nic
There was a problem hiding this comment.
Steps to Reproduce
- Create an ARO-HCP cluster
- Create a node pool that requests VMs exceeding existing quota (to simulate delayed/stuck provisioning)
- Wait until node provisioning gets stuck or delayed
- Attempt to provision a service of type LoadBalancer
There was a problem hiding this comment.
A customer had reported that when creating a Kubernetes service of type LoadBalancer, the operation fails if any VMs in the node pool are still provisioning or stuck in creation. The expectation is that the load balancer should skip VMs that are not yet ready and add them later once they complete provisioning, rather than failing the entire operation.
SyncLoadBalancerFailed Error syncing load balancer: failed to ensure load balancer: failed to get vm name by ip config ID /subscriptions/.../xxxx-xxxx-xxxx-nic/ipConfigurations/pipConfig: failed to get vm ID of xxxx-xxxx-xxxx-nic
If this is the case, in the next reconcile when the vm has been ready, it should auto fixed.
There was a problem hiding this comment.
BTW, what is ARO-HCP cluster? Is this issue only in ARO-HCP clusters?
There was a problem hiding this comment.
BTW, what is ARO-HCP cluster? Is this issue only in ARO-HCP clusters?
ARO-HCP: https://github.com/Azure/ARO-HCP : uses standard OpenShift cloud-controller-manager (which is based on cloud-provider-azure)
This issue will occur in any cluster using cloud-provider-azure
There was a problem hiding this comment.
If this is the case, in the next reconcile when the vm has been ready, it should auto fixed.
In this specific case, the whole array of VMS are never gonna get provisioned (due to said constraints), so waiting for next cycle wont do it as the state didnt change so no processing would follow from this file.
This PR makes the process of VM state transiotion (among an array of VMs to be provisioned) more granular even if the re-sync duration is bearable.
There was a problem hiding this comment.
But if there is a genuine issue from the NRP/NIC side, this change will silently hide the error.
There was a problem hiding this comment.
would it be an acceptable solution of we log it and proceed? This use case is an edge case but still encountered in production.
There was a problem hiding this comment.
I think it would be more reasonable to solve the root cause, so the ccm reconcile will be unblocked. This change introduces behavior change to solve an edge case, and I'm not sure if it's worth it, as it may introduce other issues.
What type of PR is this?
/kind bug
What this PR does / why we need it:
Load balancer creation fails completely when any node in the cluster has a NIC that is not yet fully associated with a VM. This occurs during normal cluster operations when:
Impact:
Expected Behavior:
The load balancer should be created with currently-available nodes, and automatically add delayed nodes once their VMs are fully provisioned (on subsequent sync cycles).
Which issue(s) this PR fixes:
Fixes #
Special notes for your reviewer:
The change modifies error handling behavior in several key areas:
GetVMNameByIPConfigurationName- Returns("", nil)instead of an error when a NIC has no VM associationgetVMManagementTypeByIPConfigurationID- Returns newManagedByNoVMtype when vmName is emptyGetNodeNameByIPConfigurationID(VMSS) - Checks forManagedByNoVMand returns("", "", nil)earlygetNodeInformationByIPConfigurationID(Flex) - Checks for empty vmName and returns early with loggingReconcileBackendPools- skips processingGetBackendPrivateIPs- skips IP collectionensureBackendPoolDeleted- Skips nodes with empty nodeNameAdded comprehensive test coverage:
TestGetNodeNameByIPConfigurationIDfor NIC without VMTestEnsureBackendPoolDeletedfor orphaned NIC in backend poolTestGetNodeNameByIPConfigurationIDVmssFlexfor orphaned NICTestGetVMManagementTypeByIPConfigurationIDto expectManagedByNoVMinstead of errorDoes this PR introduce a user-facing change?
Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.: