-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IPAM controller implementation #5
Conversation
} | ||
nodeRange := allocatedRange{ | ||
StartIP: startIP, | ||
EndIP: ip.NextIPWithOffset(startIP, int64(pa.cfg.PerNodeBlockSize)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will NextIPWithOffset prevent EndIP to be broadcast IP?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also you can create the allocatedRange object after Line 115
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a check to avoid allocation of broadcast ip
} | ||
} | ||
if len(startIP) == 0 { | ||
startIP = ip.NextIP(ip.Network(pa.cfg.Subnet).IP) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a comment that this to skip the network ip address
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code path changed a bit to cover additional use-cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: firs -> first
return nodeAllocationInfo{}, fmt.Errorf("endIP is incorrect ip") | ||
} | ||
|
||
if !subnet.Contains(nodeAllocStart) || !subnet.Contains(nodeAllocEnd) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't validate that the gateway is in the subnet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
return nodeAllocationInfo{}, fmt.Errorf("invalid allocation allocators: start or end IP is out of the subnet") | ||
} | ||
|
||
if ip.Cmp(nodeAllocEnd, nodeAllocStart) <= 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need this validation. It seem it will fail with the ip.Distance as negative value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true, but I think it is better to keep the check and return more accurate message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets keep this as is.
if err := r.Client.List(ctx, nodeList); err != nil { | ||
return ctrl.Result{}, err | ||
} | ||
for _, n := range nodeList.Items { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will trigger the node controller Reconcile to sync again all nodes right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code is designed to be able to handle each node object individually, and it is able to handle multiple node objects concurrently.
The Node controller currently runs with a single worker to avoid possible concurrency-related issues. We can increase the count of workers later when we will have good enough test coverage.
The anonnotaion is not as defined in the doc |
The offset code is adding addition ip to the block
each node get range of 3 ip I0503 22:16:59.739984 628030 allocator.go:117] "allocator/pool=my-pool: range allocated" controller="node" controllerGroup="" controllerKind="Node" Node="worker-node01" namespace="" name="worker-node01" reconcileID=684b8ca2-d904-47fa-905c-8f735c12872a node="worker-node01" start="192.168.0.1" end="192.168.0.3" |
when the configmap get deleted I see this message [1] in a loop. restart the controller solves it. [1] - |
with this config (blockSize is 4 but I mean 5 see +1 shift issue above) see below [1] "worker-node02" got 192.168.0.15 which is broadcast address (start="192.168.0.11" end="192.168.0.15") [1] |
So when creating again the configmap the error stoped which is good. We can just open issue to see how to handle configmap delete as this is not critical |
we should clean annotation from nodes when configmap is invalid.
|
CNI relies on valid configuration for all CNI calls CMD Add and CMD Del we can keep the "last valid" annotation on node we may need the latter eventually, but not sure if we need it now. |
PR re-based, testing is in progress |
5d56133
to
63c9ff4
Compare
return ctrl.Result{}, err | ||
} | ||
|
||
if err := r.Client.Update(ctx, node); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we use patch here ? to reduce chance of error ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error is not critical. In case of error we will restart the loop for specific node only. But in general maybe it is a good idea to use Patch, I will return back to it when work on test coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool thx, in the past we got folks complaining on errors in controller, if we can avoid them its better.
(will save time in the long term ...)
I updated the controller behavior. Now the controller explicitly handles ConfigMap removal - simply waits for ConfigMap recreation. Current behavior is following: in case if there is no ConfigMap or if it contains invalid configuration then controller will simply keep all existing annotations for nodes and wait for ConfigMap update/creation. I think this is the safest behavior but we can change it later. |
StartIP: startIP, | ||
EndIP: ip.NextIPWithOffset(startIP, int64(pa.cfg.PerNodeBlockSize)-1), | ||
} | ||
if !pa.cfg.Subnet.Contains(nodeRange.EndIP) || ip.IsBroadcast(nodeRange.EndIP, pa.cfg.Subnet) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also add check that start IP is in subnet ?
far fetched scenario where startIP has wrap around to 0 and EndIP is somehow within the subnet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it looks like the code may fail if the next IP become an invalid address. WIll address this in a separate PR
return err | ||
} | ||
// check if r.StartIP or r.EndIP match start or end IP of the "a" | ||
if r.StartIP.Equal(a.StartIP) || r.StartIP.Equal(a.EndIP) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: allocatedRange can have a method "Overlaps(other *allocatedRange) bool"
} | ||
// check if r.StartIP or r.EndIP match start or end IP of the "a" | ||
if r.StartIP.Equal(a.StartIP) || r.StartIP.Equal(a.EndIP) || | ||
r.EndIP.Equal(a.StartIP) || r.EndIP.Equal(a.EndIP) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since block size is the same, then an overlap means the blocks are necessarily equal.
is there a case that this is not correct ?
if so, its enough to just compare StartIP which can technically act as an absolute "block index" in the subnet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right. I changed this logic. Now we check that StartIP has correct offset and simply validate that there is no duplicates registered.
b236eae
to
b7c00ff
Compare
} | ||
allocations := pa.getAllocationsAsSlice() | ||
for _, a := range allocations { | ||
if allocData.allocatedRange.StartIP.Equal(a.StartIP) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a comment here on why this is enough ?
to the naive reader it many not be apparent.
float64(pa.cfg.PerNodeBlockSize)) != 0 { | ||
return fmt.Errorf("invalid start IP offset") | ||
} | ||
if ip.Distance(allocData.StartIP, allocData.EndIP) != int64(pa.cfg.PerNodeBlockSize)-1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like adding a Wrapper of ip.IPsInRange(start, end)
which will just add one to distance result
will save adding -1 in different places. (which later on folks may forget to add )
if !allocData.Gateway.Equal(pa.cfg.Gateway) { | ||
return fmt.Errorf("gateway mismatch") | ||
} | ||
if math.Mod(float64(ip.Distance(ip.Network(pa.cfg.Subnet).IP, allocData.StartIP))-1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 is because we skip the network address ? (e.g for 192.168.0.0/16 , 192.168.0.0 is not allocated)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple example:
network: 0.0.0.0
block size 10
StartIPs wil be: 1, 11, 21, 31, 41 ...
Distance per StartIP from Network IP is same
subsracting 1 will yield 0 in mod 10 (block size)
so it seems to work :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a couple of comments.
mainly nits so up to u if you want to address them :)
feel free to self merge.
Signed-off-by: Yury Kulazhenkov <ykulazhenkov@nvidia.com>
This package is shared by components Signed-off-by: Yury Kulazhenkov <ykulazhenkov@nvidia.com>
Code is not covered by test and is not tested well, but main flows should work.