kubernetes/kops · error

failed to associated floating IP to instance %s: %v

Error message

failed to associated floating IP to instance %s: %v

What it means

Thrown by associateFloatingIP when the Neutron L3 floating-IP update (PUT /v2.0/floatingips/{id} setting PortID) fails while associating a floating IP with the new instance's port during RenderOpenstack. The Neutron client (l3floatingip.Update) returns errors such as port not found, IP already associated, or 401/404. The message names the instance to make the failing task identifiable in the kOps apply output.

Source

Thrown at upup/pkg/fi/cloudup/openstacktasks/instance.go:420

		}
	}
	if changes.FloatingIP != nil {
		err := associateFloatingIP(t, e)
		if err != nil {
			return err
		}
	}
	return nil
}

func associateFloatingIP(t *openstack.OpenstackAPITarget, e *Instance) error {
	client := t.Cloud.NetworkingClient()

	_, err := l3floatingip.Update(context.TODO(), client, fi.ValueOf(e.FloatingIP.ID), l3floatingip.UpdateOpts{
		PortID: e.Port.ID,
	}).Extract()
	if err != nil {
		return fmt.Errorf("failed to associated floating IP to instance %s: %v", *e.Name, err)
	}
	return nil
}

func includeBootVolumeOptions(t *openstack.OpenstackAPITarget, e *Instance, opts servers.CreateOpts) (servers.CreateOpts, error) {
	if !bootFromVolume(e.Metadata) {
		return opts, nil
	}

	i, err := t.Cloud.GetImage(fi.ValueOf(e.Image))
	if err != nil {
		return servers.CreateOpts{}, fmt.Errorf("Error getting image information: %v", err)
	}

	blockDevice := servers.BlockDevice{
		BootIndex:           0,
		DeleteOnTermination: true,
		DestinationType:     "volume",

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the floating IP still exists and is unassociated: `openstack floating ip show <id>`; delete/recreate it and rerun `kops update cluster`
  2. Verify the port exists and has a fixed IP in the same subnet as the floating IP: `openstack port show <port-id>`
  3. Confirm Neutron credentials/RBAC allow updating floating IPs for the project
  4. Ensure the cluster spec doesn't reuse one floating IP for multiple instances (concurrent association conflict)
  5. If the cloud lacks the floating IP port-forwarding/l3 extension expected by the gophercloud version, upgrade the cloud side or pin a compatible client

Example fix

// before: stale floating IP left from failed apply
// openstack floating ip delete <stale-ip-id>
// after: recreate then re-apply
// openstack floating ip create --subnet <subnet> <external-network>
// kops update cluster --name <cluster> --yes
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: floating IP must exist, be unassociated, and port must have a fixed IP
func validateFloatingIPAssociation(netClient *gophercloud.ServiceClient, fipID, portID string) error {
	fip, err := l3floatingip.Get(context.TODO(), netClient, fipID).Extract()
	if err != nil {
		return fmt.Errorf("floating IP %q missing: %w", fipID, err)
	}
	if fip.PortID != "" {
		return fmt.Errorf("floating IP %q already associated with port %q", fipID, fip.PortID)
	}
	port, err := ports.Get(context.TODO(), netClient, portID).Extract()
	if err != nil || len(port.FixedIPs) == 0 {
		return fmt.Errorf("port %q missing or has no fixed IP", portID)
	}
	return nil
}

Type guard

func isFloatingIPNotFound(err error) bool {
	var _, nf gophercloud.ErrDefault404
	return errors.As(err, &nf) || strings.Contains(err.Error(), "No address with that ID")
}

Try / catch

_, err := l3floatingip.Update(context.TODO(), client, fi.ValueOf(e.FloatingIP.ID), l3floatingip.UpdateOpts{PortID: e.Port.ID}).Extract()
if err != nil {
	if isFloatingIPNotFound(err) {
		return fmt.Errorf("floating IP %s was deleted; recreate it and re-apply: %w", fi.ValueOf(e.FloatingIP.ID), err)
	}
	return fmt.Errorf("failed to associated floating IP to instance %s: %w", *e.Name, err)
}

Prevention

When it happens

Trigger: l3floatingip.Update returns error during instance creation or when changes.FloatingIP triggers re-association: FloatingIP.ID no longer exists (deleted/released between tasks), e.Port.ID is nil or points to a deleted port, the floating IP belongs to a different project/network than the port, or Neutron rejects the association because the port has no fixed IP in the floating IP's subnet.

Common situations: A leftover floating IP from a prior failed apply was deleted externally; running with insufficient Neutron RBAC to update floating IPs; port and floating IP created in mismatched subnets; concurrent applies racing to associate the same IP; Octavia/Neutron extension `l3-floating-ip` unavailable on older clouds.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/f738a8497c658f13. Report an issue: GitHub.