Skip to content

[fix] release the IPv4 node CIDR when IPv6 allocation fails - #657

Open
lbarrosby wants to merge 1 commit into
linode:mainfrom
lbarrosby:fix-nodeipam-release-ipv4-on-ipv6-failure
Open

lbarrosby wants to merge 1 commit into
linode:mainfrom
lbarrosby:fix-nodeipam-release-ipv4-on-ipv6-failure

Conversation

@lbarrosby

Copy link
Copy Markdown
Contributor

Description

cloudAllocator.AllocateOrOccupyCIDR takes an IPv4 CIDR from the cluster CIDR set with AllocateNext() and then calls allocateIPv6CIDR. If the IPv6 lookup fails, it returns the error without releasing the IPv4 CIDR. syncNode then requeues the node with AddRateLimited, and every retry allocates another block.

This is easy to hit: the node informer enqueues every new node, and a kubelet running with --cloud-provider=external registers the node before the cloud node controller sets spec.providerID. Until then parseLinodeIDFromProviderID fails (node ... has no ProviderID set) and each retry leaks one IPv4 block. A transient Linode API error in GetInstance/ListInterfaces/ListInstanceConfigs has the same effect. The leaked blocks only come back when the CCM restarts, so with node churn the cluster CIDR runs out (CIDRNotAvailable).

The fix releases the IPv4 CIDR before returning the IPv6 error, the same way updateCIDRsAllocation already releases it when patching the node fails.

TestAllocateOrOccupyCIDRReleasesIPv4WhenIPv6Fails uses a /28 cluster CIDR with /30 node blocks (four blocks), fails the IPv6 step six times (node without ProviderID, and GetInstance returning an error), and then expects four free blocks. On main:

--- FAIL: TestAllocateOrOccupyCIDRReleasesIPv4WhenIPv6Fails (0.12s)
    cloud_allocator_test.go:1522: IPv4 CIDRs leaked after failed IPv6 allocations, only 0 of 4 left: CIDR allocation failed; there are no remaining CIDRs left to allocate in the accepted range

With the change:

$ go test ./cloud/nodeipam/ipam/
ok  	github.com/linode/linode-cloud-controller-manager/cloud/nodeipam/ipam	4.305s
$ golangci-lint run -c .golangci.yml ./cloud/nodeipam/...
0 issues.

General:

  • Have you removed all sensitive information, including but not limited to access keys and passwords?
  • Have you checked to ensure there aren't other open or closed Pull Requests for the same bug/feature/question?

Pull Request Guidelines:

  1. Does your submission pass tests?
  2. Have you added tests?
  3. Are you addressing a single feature in this PR?
  4. Are your commits atomic, addressing one change per commit?
  5. Are you following the conventions of the language?
  6. Have you saved your large formatting changes for a different PR, so we can focus on your work?
  7. Have you explained your rationale for why this feature is needed?
  8. Have you linked your PR to an open issue

AllocateOrOccupyCIDR takes an IPv4 CIDR from the cluster CIDR set and
then looks up the IPv6 range of the Linode. When that lookup fails, for
example because the node has no ProviderID yet or the Linode API
returned an error, the function returned without giving the IPv4 CIDR
back. The node is requeued and every retry took another block, so the
cluster CIDR ran out until the controller restarted.

Release the IPv4 CIDR before returning the IPv6 error.

Signed-off-by: Lucas Barros <lucasbarros.kam@gmail.com>
@lbarrosby
lbarrosby requested review from a team as code owners November 8, 2026 14:27
@github-actions github-actions Bot added the bugfix for any bug fixes in the changelog. label Nov 8, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix for any bug fixes in the changelog.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant