-
Notifications
You must be signed in to change notification settings - Fork 473
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
netpol: Add dual-stack support #1280
Conversation
@@ -56,6 +56,8 @@ Usage of kube-router: | |||
--disable-source-dest-check Disable the source-dest-check attribute for AWS EC2 instances. When this option is false, it must be set some other way. (default true) | |||
--enable-cni Enable CNI plugin. Disable if you want to use kube-router features alongside another CNI plugin. (default true) | |||
--enable-ibgp Enables peering with nodes with the same ASN, if disabled will only peer with external BGP peers (default true) | |||
--enable-ipv4 Enables IPv4 support (default true) | |||
--enable-ipv6 Enables IPv6 support (default true) |
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 enable this by default?
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 can disable it by default, if you want.
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'm just wondering on implications to existing systems that don't use ipv6 currently. Maybe introduce as disabled and enable later?
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.
Alright, changed to false
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.
@vadorovsky it looks like this is still set to enabled by default. Given that it's going to fail to initialize the NPC if IPv6 is enabled and there is not an IPv6 address on the node in the Kubernetes API, I think that enabling IPv6 is too risky as a default.
edc1d4c
to
632d42f
Compare
@vadorovsky Thanks for submitting, will try to look at it tomorrow. |
@vadorovsky apologies for not getting to this on Friday like I wanted to! This is a big PR and so I want to give it the time it deserves to review and test. Had a bunch of work stuff come up last week that is continuing into this week, but I wanted to let you know this is still on my radar and still very much something that I want to get into this week. |
This change allows to define two cluster CIDRs for compatibility with Kubernetes dual-stack, with an assumption that two CIDRs are usually IPv4 and IPv6. Signed-off-by: Michal Rostecki <[email protected]>
632d42f
to
24b7390
Compare
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.
@vadorovsky Again, sorry that it took so long to finish this review. I had to take it in parts because this change is so large.
First off, thanks very much for being willing to work on such a sizable change. Just reviewing your refactor here made my head hurt a bit, so I can imagine it was difficult to put all this together from scratch and keep all the pieces straight.
I think that almost all of my comments are minor things, so try not to get disappointed by the ~30 changes I'm requesting here. On the whole this seems very well done.
So far this review only covers the code changes, I haven't gotten a chance to run this. I intend to do so over the next couple of days and put it through its paces, but in the meantime I wanted to get you feedback as soon as possible.
A request, when you work on updates, please don't squash or amend them to the existing commit, please leave them as a separate commit so that I can compare the original work against the requested changes. It will really help the final approval go much faster.
Again, thanks for your work!
@@ -184,8 +188,39 @@ func (kr *KubeRouter) Run() error { | |||
} | |||
|
|||
if kr.Config.RunFirewall { | |||
iptablesCmdHandlers := make(map[v1core.IPFamily]utils.IPTablesHandler, 2) |
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.
It doesn't seem like there a particular need to move iptables and ipset logic up here into the command handler. If not, it would be better to sink this down into the NPC, into the NewNetworkPolicyController()
initializer.
) | ||
|
||
var hasWait bool | ||
|
||
// Interface based on the IPTables struct from github.com/coreos/go-iptables | ||
// which allows to mock it. | ||
type IPTablesHandler interface { |
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.
Its a pity that the upstream package doesn't provide this interface for us. 😞 Thanks for creating it.
buffer.WriteString(ruleStr) | ||
} | ||
|
||
type IPTablesSaveRestore struct { |
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 see any reason not to make this an interface as well? It would essentially just expose the SaveInto
and Restore
functions, that way we could mock it other places in the NPC as well if needed?
func GetNodeIPDualStack(node *apiv1.Node, enableIPv4, enableIPv6 bool) (net.IP, net.IP, error) { | ||
var ipAddrv4, ipAddrv6 net.IP | ||
addresses := node.Status.Addresses | ||
addressesPerType := make(addressMap) |
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.
It seems like this would be a good opportunity to refactor GetNodeIP()
as well, and consolidate it to use this same logic.
Perhaps the add()
method above could be changed into more of a GetNodeAddressesByType()
method, and then it could do the iteration over addresses and just return the entire map to both GetNodeIP
and GetNodeIPDualStack
?
if _, ok := m[address.Type]; ok { | ||
m[address.Type] = append(m[address.Type], address) | ||
} else { | ||
// There can be at most 2 addresses of the same type. |
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 explain what you mean by this comment and the 2
sizing? Is this something that the Kubernetes API guarantees?
for _, obj := range npc.podLister.List() { | ||
pod := obj.(*api.Pod) | ||
// ignore the pods running on the different node and pods that are not actionable | ||
if strings.Compare(pod.Status.HostIP, nodeIP) != 0 || !isNetPolActionable(pod) { | ||
continue | ||
} | ||
localPods[pod.Status.PodIP] = podInfo{ip: pod.Status.PodIP, | ||
localPods[pod.Status.PodIP] = podInfo{ips: pod.Status.PodIPs, |
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.
See comment above, but it might be beneficial to load both the ip
as well as ips
for the pod object here.
@@ -8,6 +8,8 @@ import ( | |||
|
|||
"github.com/cloudnativelabs/kube-router/pkg/utils" | |||
api "k8s.io/api/core/v1" | |||
"k8s.io/klog/v2" | |||
utilsnet "k8s.io/utils/net" |
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 fix the imports to consistently use either netutils
or utilsnet
across all the imports? It makes it a little easier to understand.
activePolicyChains := make(map[string]bool) | ||
activePolicyIPSets := make(map[string]bool) | ||
|
||
// for ipFamily, ipset := range npc.ipSetHandlers { |
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 can probably be removed.
for _, podIP := range currentPodIPs[ipFamily] { | ||
setEntries = append(setEntries, []string{podIP, utils.OptionTimeout, "0"}) | ||
} | ||
ipset.RefreshSet(targetDestPodIPSetName, setEntries, utils.TypeHashIP) |
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.
Is there a reason not to use createGenericHashIPSet()
here rather than building the entries yourself? It already accepts ipFamily
as a parameter, so you would just pass that and it would end up in the correct set.
for _, podIP := range currentPodIPs[ipFamily] { | ||
setEntries = append(setEntries, []string{podIP, utils.OptionTimeout, "0"}) | ||
} | ||
ipset.RefreshSet(targetSourcePodIPSetName, setEntries, utils.TypeHashIP) |
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.
Same here on using createGenericHashIPSet()
Closed in favor of #1343 |
This change allows to define two cluster CIDRs for compatibility with
Kubernetes dual-stack, with an assumption that two CIDRs are usually
IPv4 and IPv6.
Signed-off-by: Michal Rostecki [email protected]