kubernetes/kops · error

multiple floating ips associated to port: %s

Error message

multiple floating ips associated to port: %s

What it means

findFipByPortID in floatingip.go:193 refuses to pick a floating IP when more than one l3 floating IP is associated with the same Neutron port, since the task cannot determine which one is managed by kops. It is a state-drift guard, not an API failure.

Source

Thrown at upup/pkg/fi/cloudup/openstacktasks/floatingip.go:193

			return actual, nil
		}
	}

	return nil, nil
}

func findFipByPortID(cloud openstack.OpenstackCloud, id string) (fip *l3floatingip.FloatingIP, err error) {
	fips, err := cloud.ListL3FloatingIPs(l3floatingip.ListOpts{
		PortID: id,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to list layer 3 floating ips for port ID %s: %v", id, err)
	}
	if len(fips) == 0 {
		return nil, nil
	}
	if len(fips) > 1 {
		return nil, fmt.Errorf("multiple floating ips associated to port: %s", id)
	}
	return &fips[0], nil
}

func (e *FloatingIP) Run(c *fi.CloudupContext) error {
	return fi.CloudupDefaultDeltaRunMethod(e, c)
}

func (_ *FloatingIP) CheckChanges(a, e, changes *FloatingIP) error {
	if a == nil {
		if e.Name == nil {
			return fi.RequiredField("Name")
		}
	} else {
		if changes.ID != nil {
			return fi.CannotChangeField("ID")
		}
		if changes.Name != nil && fi.ValueOf(a.Name) != "" {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. List the FIPs on the port: `openstack floating ip list --port <port-id>` and disassociate/delete all but the intended one.
  2. Prefer deleting the FIP whose Description does not match the kops task name.
  3. Rerun `kops update cluster` after cleanup so reconciliation sees a single FIP.
  4. Going forward, avoid manually assigning floating IPs to ports managed by kops.

Example fix

// before: two FIPs on one port
openstack floating ip list --port <lb-port-id>   # shows 2 rows
// after
openstack floating ip unset --port <duplicate-fip-id>
openstack floating ip delete <duplicate-fip-id>
Defensive patterns

Strategy: validation

Validate before calling

// fail early with a clear message if the port has more than one FIP
fips, _ := cloud.ListL3FloatingIPs(l3floatingip.ListOpts{PortID: portID})
if len(fips) > 1 {
    return fmt.Errorf("port %s has %d floating IPs; delete extras before update", portID, len(fips))
}

Type guard

func hasSingleFIP(fips []l3floatingip.FloatingIP) bool {
    return len(fips) <= 1
}

Try / catch

fip, err := findFipByPortID(cloud, portID)
if err != nil && strings.Contains(err.Error(), "multiple floating ips") {
    // operator cleanup required: disassociate/delete duplicate FIPs
    return nil, err
}

Prevention

When it happens

Trigger: Two or more entries returned by ListL3FloatingIPs with PortID == the LB port — e.g. a FIP was created manually in addition to the kops-managed one, or a previous partially-failed kops run left a duplicate.

Common situations: Manual operator intervention adding FIPs; a prior kops run crashed after creating a FIP but before recording it, then re-created one; shared cluster where multiple tooling (e.g. cloud provider LB controller and kops) both allocate FIPs.

Related errors


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