You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add perNodeExclusions support for IPPool and CIDRPool
Add support for per-node index-based IP exclusions in both IPPool and
CIDRPool resources. This allows administrators to exclude specific IP
address ranges based on their index position within each node's allocated
IP block or prefix, rather than by absolute IP addresses.
API Changes:
- Add ExcludeIndexRange type with startIndex and endIndex fields
- Add perNodeExclusions field to IPPoolSpec and CIDRPoolSpec
- Add kubebuilder validation markers for CRD-level validation
- startIndex and endIndex must be non-negative
- endIndex must be >= startIndex
- Add runtime validation functions:
- validatePerNodeExclusions() for CIDRPool (validates against perNodeNetworkPrefix)
- validatePerNodeExclusionsForBlockSize() for IPPool (validates against perNodeBlockSize)
- Add comprehensive test coverage (24 test cases total)
- 14 tests for CIDRPool (IPv4 and IPv6)
- 10 tests for IPPool (IPv4 and IPv6)
Controller Implementation:
- IPPool controller: Add buildPerNodeExclusions() function
- Converts index-based exclusions to IP addresses for node's IP block
- Merges with pool-wide exclusions before passing to allocator
- 10 unit tests covering all edge cases
- CIDRPool controller: Add buildPerNodeExclusions() function
- Converts index-based exclusions to IP addresses for node's prefix
- Combines with filtered pool-wide exclusions
- 7 unit tests covering all edge cases
Implementation details:
- Each node processes only its own allocation (per-node)
- Index-based ranges are converted to IP-based ExclusionRange objects
- Ranges are clamped to node's allocation boundaries
- Ranges outside node's allocation are skipped
- Reuses existing allocator exclusion mechanism (no allocator changes)
- Memory efficient: large ranges create single ExclusionRange entries
Documentation:
- Update README.md with perNodeExclusions field descriptions
- Update docs/static-ip.md with examples
- Add detailed field explanations for both IPPool and CIDRPool
Example usage:
perNodeExclusions:
- startIndex: 0
endIndex: 10
Node-A (192.168.0.1-192.168.0.100) excludes 192.168.0.1-192.168.0.11
Node-B (192.168.0.101-192.168.0.200) excludes 192.168.0.101-192.168.0.111
Signed-off-by: Fred Rolland <frolland@nvidia.com>
Copy file name to clipboardExpand all lines: README.md
+16Lines changed: 16 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -345,6 +345,9 @@ spec:
345
345
exclusions: # optional
346
346
- startIP: 192.168.0.10
347
347
endIP: 192.168.0.20
348
+
perNodeExclusions: # optional
349
+
- startIndex: 0
350
+
endIndex: 10
348
351
nodeSelector:
349
352
nodeSelectorTerms:
350
353
- matchExpressions:
@@ -385,6 +388,11 @@ spec:
385
388
* `startIP`: start IP of the exclude range (inclusive).
386
389
* `endIP`: end IP of the exclude range (inclusive).
387
390
391
+
* `perNodeExclusions` (optional, list): contains reserved IP address indexes that should not be allocated by nv-ipam node component. The IP address indexes are relative to the per-node IP block allocated to each node, counting from the start of the allocated range. For example, if a node is allocated the IP block 192.168.0.1-192.168.0.100, then index 0 corresponds to 192.168.0.1, index 1 to 192.168.0.2, and so on. Note: For IPPool, indexes count from the range start; for CIDRPool, indexes count from the subnet start (network address).
392
+
393
+
* `startIndex`: start index of the exclude range (inclusive). Must be non-negative.
394
+
* `endIndex`: end index of the exclude range (inclusive). Must be greater than or equal to startIndex and within the perNodeBlockSize range.
395
+
388
396
* `nodeSelector` (optional): A list of node selector terms. The terms are ORed. Each term can have a list of matchExpressions that are ANDed. Only the nodes that match the provided labels will get assigned IP Blocks for the defined pool.
389
397
* `defaultGateway` (optional): Add the pool gateway as default gateway in the pod static routes.
390
398
* `routes` (optional, list): contains CIDR to be added in the pod static routes via the pool gateway.
@@ -419,6 +427,9 @@ spec:
419
427
exclusions: # optional
420
428
- startIP: 192.168.0.10
421
429
endIP: 192.168.0.20
430
+
perNodeExclusions: # optional
431
+
- startIndex: 0
432
+
endIndex: 10
422
433
staticAllocations:
423
434
- nodeName: node-33
424
435
prefix: 192.168.33.0/24
@@ -478,6 +489,11 @@ spec:
478
489
* `startIP`: start IP of the exclude range (inclusive).
479
490
* `endIP`: end IP of the exclude range (inclusive).
480
491
492
+
* `perNodeExclusions` (optional, list): contains reserved IP address indexes that should not be allocated by nv-ipam node component. The IP address indexes are relative to the per-node prefix allocated to each node, counting from the subnet start (network address). For example, if a node is allocated the prefix 192.168.0.0/24, then index 0 corresponds to 192.168.0.0 (network address), index 1 to 192.168.0.1 (which would be the gateway if gatewayIndex is 1), index 2 to 192.168.0.2, and so on. This indexing is consistent with gatewayIndex.
493
+
494
+
* `startIndex`: start index of the exclude range (inclusive). Must be non-negative.
495
+
* `endIndex`: end index of the exclude range (inclusive). Must be greater than or equal to startIndex and within the subnet size defined by perNodeNetworkPrefix.
496
+
481
497
* `staticAllocations` (optional, list): static allocations for the pool.
482
498
483
499
* `nodeName` (optional): name of the node for static allocation, can be empty in case if the prefix should be preallocated without assigning it for a specific node.
0 commit comments