Skip to content

Commit

Permalink
Add support for IP address exclusions to IPPool CRD
Browse files Browse the repository at this point in the history
Signed-off-by: Yury Kulazhenkov <ykulazhenkov@nvidia.com>
  • Loading branch information
ykulazhenkov committed Jun 13, 2024
1 parent 0df7f64 commit 9a60011
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 8 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ spec:
subnet: 192.168.0.0/16
perNodeBlockSize: 100
gateway: 192.168.0.1
exclusions: # optional
- startIP: 192.168.0.10
endIP: 192.168.0.20
nodeSelector:
nodeSelectorTerms:
- matchExpressions:
Expand Down Expand Up @@ -374,6 +377,11 @@ spec:
* `subnet`: IP Subnet of the pool.
* `gateway` (optional): Gateway IP of the subnet.
* `perNodeBlockSize`: the number of IPs of IP Blocks allocated to Nodes.
* `exclusions` (optional, list): contains reserved IP addresses that should not be allocated by nv-ipam node component.

* `startIP`: start IP of the exclude range (inclusive).
* `endIP`: end IP of the exclude range (inclusive).

* `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.

> __Notes:__
Expand Down
26 changes: 24 additions & 2 deletions api/v1alpha1/ippool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ var _ = Describe("Validate", func() {
Spec: v1alpha1.IPPoolSpec{
Subnet: "192.168.0.0/16",
PerNodeBlockSize: 128,
Gateway: "192.168.0.1",
Exclusions: []v1alpha1.ExcludeRange{
{StartIP: "192.168.0.100", EndIP: "192.168.0.110"},
},
Gateway: "192.168.0.1",
NodeSelector: &corev1.NodeSelector{
NodeSelectorTerms: []corev1.NodeSelectorTerm{{
MatchExpressions: []corev1.NodeSelectorRequirement{{
Expand All @@ -49,7 +52,10 @@ var _ = Describe("Validate", func() {
Spec: v1alpha1.IPPoolSpec{
Subnet: "2001:db8:3333:4444::0/64",
PerNodeBlockSize: 1000,
Gateway: "2001:db8:3333:4444::1",
Exclusions: []v1alpha1.ExcludeRange{
{StartIP: "2001:db8:3333:4444::3", EndIP: "2001:db8:3333:4444::4"},
},
Gateway: "2001:db8:3333:4444::1",
},
}
Expect(ipPool.Validate()).To(BeEmpty())
Expand Down Expand Up @@ -98,6 +104,22 @@ var _ = Describe("Validate", func() {
ContainSubstring("spec.perNodeBlockSize"),
)
})
It("Invalid - exclusions not part of the subnet", func() {
ipPool := v1alpha1.IPPool{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: v1alpha1.IPPoolSpec{
Subnet: "192.168.0.0/24",
Exclusions: []v1alpha1.ExcludeRange{
{StartIP: "10.10.10.10", EndIP: "10.10.10.20"},
},
PerNodeBlockSize: 10,
},
}
Expect(ipPool.Validate().ToAggregate().Error()).
To(
ContainSubstring("spec.exclusions"),
)
})
It("Invalid - gateway outside of the subnet", func() {
ipPool := v1alpha1.IPPool{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha1/ippool_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type IPPoolSpec struct {
// amount of IPs to allocate for each node,
// must be less than amount of available IPs in the subnet
PerNodeBlockSize int `json:"perNodeBlockSize"`
// contains reserved IP addresses that should not be allocated by nv-ipam
Exclusions []ExcludeRange `json:"exclusions,omitempty"`
// gateway for the pool
Gateway string `json:"gateway,omitempty"`
// selector for nodes, if empty match all nodes
Expand Down
3 changes: 3 additions & 0 deletions api/v1alpha1/ippool_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ func (r *IPPool) Validate() field.ErrorList {
"is larger then amount of IPs available in the subnet"))
}
}
if network != nil {
errList = append(errList, validateExclusions(network, r.Spec.Exclusions, field.NewPath("spec"))...)
}
var parsedGW net.IP
if r.Spec.Gateway != "" {
parsedGW = net.ParseIP(r.Spec.Gateway)
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions deploy/crds/nv-ipam.nvidia.com_ippools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ spec:
spec:
description: IPPoolSpec contains configuration for IP pool
properties:
exclusions:
description: contains reserved IP addresses that should not be allocated
by nv-ipam
items:
description: ExcludeRange contains range of IP addresses to exclude
from allocation startIP and endIP are part of the ExcludeRange
properties:
endIP:
type: string
startIP:
type: string
required:
- endIP
- startIP
type: object
type: array
gateway:
description: gateway for the pool
type: string
Expand Down
3 changes: 3 additions & 0 deletions examples/ippool-1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ metadata:
spec:
subnet: 192.168.0.0/16
perNodeBlockSize: 128
exclusions: # optional
- startIP: 192.168.0.10
endIP: 192.168.0.20
gateway: 192.168.0.1
nodeSelector:
nodeSelectorTerms:
Expand Down
16 changes: 10 additions & 6 deletions pkg/ipam-node/controllers/ippool/ippool.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,19 @@ func (r *IPPoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
}
reqLog.Info("Notification on IPPool", "name", ipPool.Name)
found := false

for _, alloc := range ipPool.Status.Allocations {
if alloc.NodeName == r.NodeName {
exclusions := make([]pool.ExclusionRange, 0, len(ipPool.Spec.Exclusions))
for _, e := range ipPool.Spec.Exclusions {
exclusions = append(exclusions, pool.ExclusionRange{StartIP: e.StartIP, EndIP: e.EndIP})
}
ipPool := &pool.Pool{
Name: ipPool.Name,
Subnet: ipPool.Spec.Subnet,
Gateway: ipPool.Spec.Gateway,
StartIP: alloc.StartIP,
EndIP: alloc.EndIP,
Name: ipPool.Name,
Subnet: ipPool.Spec.Subnet,
Gateway: ipPool.Spec.Gateway,
StartIP: alloc.StartIP,
EndIP: alloc.EndIP,
Exclusions: exclusions,
}
r.PoolManager.UpdatePool(poolKey, ipPool)
found = true
Expand Down

0 comments on commit 9a60011

Please sign in to comment.