Skip to content
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

🐛 Better checks before creating Floating IPs #2261

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/v1beta1/openstackcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const (
)

// OpenStackClusterSpec defines the desired state of OpenStackCluster.
// +kubebuilder:validation:XValidation:rule="has(self.disableExternalNetwork) && self.disableExternalNetwork ? !has(self.bastion) || !has(self.bastion.floatingIP) : true",message="bastion floating IP cannot be set when disableExternalNetwork is true"
// +kubebuilder:validation:XValidation:rule="has(self.disableExternalNetwork) && self.disableExternalNetwork ? has(self.disableAPIServerFloatingIP) && self.disableAPIServerFloatingIP : true",message="disableAPIServerFloatingIP cannot be false when disableExternalNetwork is true"
type OpenStackClusterSpec struct {
// ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network,
// subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4
Expand Down

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

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

10 changes: 7 additions & 3 deletions controllers/openstackcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,11 @@ func (r *OpenStackClusterReconciler) reconcileBastion(ctx context.Context, scope
return nil, err
}

return bastionAddFloatingIP(openStackCluster, clusterResourceName, port, networkingService)
if !ptr.Deref(openStackCluster.Spec.DisableExternalNetwork, false) {
return bastionAddFloatingIP(openStackCluster, clusterResourceName, port, networkingService)
}

return nil, nil
lentzi90 marked this conversation as resolved.
Show resolved Hide resolved
}

func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string, port *ports.Port, networkingService *networking.Service) (*reconcile.Result, error) {
Expand Down Expand Up @@ -798,9 +802,9 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
host = openStackCluster.Spec.ControlPlaneEndpoint.Host

// API server load balancer is disabled, but floating IP is not. Create
// API server load balancer is disabled, but external netowork and floating IP are not. Create
// a floating IP to be attached directly to a control plane host.
case !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false):
case !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && !ptr.Deref(openStackCluster.Spec.DisableExternalNetwork, false):
fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterResourceName, openStackCluster.Spec.APIServerFloatingIP)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("floating IP cannot be got or created: %w", err), false)
Expand Down
2 changes: 1 addition & 1 deletion controllers/openstackmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.LoadBalancerMemberErrorReason, clusterv1.ConditionSeverityError, "Reconciling load balancer member failed: %v", err)
return fmt.Errorf("reconcile load balancer member: %w", err)
}
} else if !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
} else if !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && !ptr.Deref(openStackCluster.Spec.DisableExternalNetwork, false) {
var floatingIPAddress *string
switch {
case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
Expand Down
4 changes: 4 additions & 0 deletions docs/book/src/clusteropenstack/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ associated to the first controller node and the other controller nodes have no f
to any other controller node. So we recommend to only set one controller node when floating IP is needed,
or please consider using load balancer instead, see [issue #1265](https://github.com/kubernetes-sigs/cluster-api-provider-openstack/issues/1265) for further information.

Note: `spec.disableExternalNetwork` must be unset or set to `false` to allow the API server to have a floating IP.

### Disabling the API server floating IP

It is possible to provision a cluster without a floating IP for the API server by setting
Expand Down Expand Up @@ -717,6 +719,8 @@ spec:
floatingIP: <Floating IP address>
```

Note: A floating IP can only be added if `OpenStackCluster.Spec.DisableExternalNetwork` is not set or set to `false`.

If `managedSecurityGroups` is set to a non-nil value (e.g. `{}`), security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.

### Making changes to the bastion host
Expand Down
5 changes: 5 additions & 0 deletions pkg/cloud/services/networking/floatingip.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackClu
var err error
var fpCreateOpts floatingips.CreateOpts

// This is a safeguard, we shouldn't reach it and if we do, it's something to fix in the caller of the function.
if openStackCluster.Status.ExternalNetwork == nil {
return nil, fmt.Errorf("external network not found")
}

if ptr.Deref(ip, "") != "" {
fp, err = s.GetFloatingIP(*ip)
if err != nil {
Expand Down
23 changes: 23 additions & 0 deletions test/e2e/suites/apivalidations/openstackcluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,29 @@ var _ = Describe("OpenStackCluster API validations", func() {
Expect(createObj(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
})

It("should not allow a bastion floating IP with DisableExternalNetwork set to true", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: ptr.To(true),
Spec: &infrav1.OpenStackMachineSpec{
Flavor: ptr.To("flavor-name"),
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
Name: ptr.To("fake-image"),
},
},
},
FloatingIP: ptr.To("10.0.0.0"),
}
cluster.Spec.DisableExternalNetwork = ptr.To(true)
Expect(createObj(cluster)).ToNot(Succeed(), "OpenStackCluster creation should not succeed")
})

It("should not allow DisableAPIServerFloatingIP to be false with DisableExternalNetwork set to true", func() {
cluster.Spec.DisableAPIServerFloatingIP = ptr.To(false)
cluster.Spec.DisableExternalNetwork = ptr.To(true)
Expect(createObj(cluster)).ToNot(Succeed(), "OpenStackCluster creation should not succeed")
})

// We must use unstructured to set values which can't be marshalled by the Go type
unstructuredClusterWithAPIPort := func(apiServerPort any) *unstructured.Unstructured {
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(cluster)
Expand Down