-
Notifications
You must be signed in to change notification settings - Fork 252
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
🐛 Expose NodePorts on cluster network instead of 0.0.0.0/0 #2128
base: main
Are you sure you want to change the base?
Conversation
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
✅ Deploy Preview for kubernetes-sigs-cluster-api-openstack ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
if openStackCluster.Spec.ManagedSubnets != nil && len(openStackCluster.Spec.ManagedSubnets) > 0 { | ||
SubnetCIDR = openStackCluster.Spec.ManagedSubnets[0].CIDR | ||
} else { | ||
SubnetCIDR = "0.0.0.0/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.
Can we not use remote group for this? This won't work on deployments which aren't using managed subnets.
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 just changed the behaviour to make use of status.Network.Subnet instead to support use cases where bring your own network/subnet is used.
I do not think we could use remote group due to load balancers talking over nodeports?
Load Balancers are created under the "service" project in default openstack meaning it is not added to any security groups inside the project where the cluster is running.
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 also left a question in the code that may be good to bring up here.
If no IPv4 subnet is found the code currently defaults to 0.0.0.0/0
to preserve current behaviour.
We could however return an error if no IPv4 subnet is found or potentially fallback to just allowing nodes by using remote groups (this will however break octavia load balancers created using the cloud provider which feels kinda bad).
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.
In other places we just add the rule twice with 2 remote groups, one for the control plane and one for workers. This covers machines even when they aren't using the default cluster network. Is there a reason we can't do that here?
I'd like to reduce our reliance on the cluster's status.Network over time. There are new, interesting deployments that it doesn't play nicely with, e.g. external control planes and spine/leaf.
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.
In other places we just add the rule twice with 2 remote groups, one for the control plane and one for workers. This covers machines even when they aren't using the default cluster network. Is there a reason we can't do that here?
I'd like to reduce our reliance on the cluster's status.Network over time. There are new, interesting deployments that it doesn't play nicely with, e.g. external control planes and spine/leaf.
It would break load balancers deployed using the cloud provider (octavia) since they are not in any security group we control (know the ID of). I think it is a really common use case and support out of the box would be nice
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.
Just wanted to follow up on this.
We could add security groups meaning all cluster nodes can contact each other and it will make the conformance test pass. However it would cause LBs created with the cloud provider to fail. I'm not at this point of any way of allowing LBs outside allowing IPs directly towards nodes.
I also think having a default where LBs "work" is preferable to have a default that works "out of the box".
/test pull-cluster-api-provider-openstack-test |
…roups and update comments
/test pull-cluster-api-provider-openstack-test |
@@ -169,6 +170,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl | |||
var secControlPlaneGroupID string | |||
var secWorkerGroupID string | |||
var secBastionGroupID string | |||
var SubnetCIDR string |
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.
var SubnetCIDR string | |
var subnetCIDR string |
} | ||
} | ||
|
||
// Allow all traffic, including from outside the cluster, to access node port services. |
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.
// Allow all traffic, including from outside the cluster, to access node port services. | |
// Allow all traffic from a specific CIDR to access node port services. |
} | ||
|
||
// Allow all traffic, including from outside the cluster, to access node port services. | ||
func getSGWorkerNodePortCidr(cidr string) []resolvedSecurityGroupRuleSpec { |
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.
func getSGWorkerNodePortCidr(cidr string) []resolvedSecurityGroupRuleSpec { | |
func getSGWorkerNodePortCIDR(cidr string) []resolvedSecurityGroupRuleSpec { |
workerRules = append(workerRules, getSGWorkerNodePort()...) | ||
|
||
// Fetch subnet to use for worker node port rules | ||
// In the future IPv6 support need to be added here |
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.
IPv4-only is icky, but everything else is still IPv4 only and it's not worth fixing it piecemeal so this is fine.
|
||
// Fetch subnet to use for worker node port rules | ||
// In the future IPv6 support need to be added here | ||
if openStackCluster.Status.Network != nil && len(openStackCluster.Status.Network.Subnets) > 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.
Iterating over a nil or empty list is safe and idiomatic. The loop below performs this check implicitly anyway.
if openStackCluster.Status.Network != nil && len(openStackCluster.Status.Network.Subnets) > 0 { | |
if openStackCluster.Status.Network != nil { |
// In the future IPv6 support need to be added here | ||
if openStackCluster.Status.Network != nil && len(openStackCluster.Status.Network.Subnets) > 0 { | ||
for _, subnet := range openStackCluster.Status.Network.Subnets { | ||
// Check uf subnet.CIDR is ipv4 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.
// Check uf subnet.CIDR is ipv4 subnet | |
// Check if subnet.CIDR is ipv4 subnet |
_, ipnet, err := net.ParseCIDR(subnet.CIDR) | ||
if err != nil { | ||
return nil, fmt.Errorf("invalid subnet found during security groups reconcile: %v", err) | ||
} | ||
if ipnet.IP.To4() != nil { | ||
SubnetCIDR = subnet.CIDR | ||
break | ||
} |
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 whole block can be replaced with netutils.IsIPv4CIDRString(subnet.CIDR)
} | ||
if SubnetCIDR != "" { | ||
// If SubnetCIDR is found we allow tcp and udp traffic from said SubnetCIDR, this in order to allow octavia Loadbalancers created by CCM to function properly | ||
workerRules = append(workerRules, getSGWorkerNodePortCidr(SubnetCIDR)...) |
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 could move this inside the block above and also remove the break so you simply add any listed IPv4 subnet. Any other restrictions we have on subnets aren't relevant here, so might as well make it handle whatever's there.
Please can you also add a code comment in there about why we're explicitly adding this subnet? Namely because this is the default subnet used by CPO as the origin of traffic from Octavia load balancers to load balancer members? Otherwise it risks being deleted by somebody because it looks redundant, even me in 6 months when I've forgotten this discussion again 🙄 |
What this PR does / why we need it:
This PR changes NodePorts to only be open from cluster network.
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #2127
Special notes for your reviewer:
I assume this is something that would be in 0.11 or 1.0? If so where do we put the changelog?
I also need to make sure what IP ranged we potentially want to use since there is multiple ways of specifying them depending on of they are operator managed or not.
TODOs:
/hold