kubernetes/kops · error

unexpected number of network interfaces for instance %q: %v

Error message

unexpected number of network interfaces for instance %q: %v

What it means

In Reconcile, the controller looks up the network interface(s) attached to the node's EC2 instance via DescribeNetworkInterfaces with an attachment.instance-id filter, and expects exactly one attached ENI. This error is thrown when the API returns zero or more than one interface, meaning the single-ENI assumption behind the IPv6 prefix delegation logic is violated.

Source

Thrown at cmd/kops-controller/controllers/awsipam.go:137

			return ctrl.Result{}, err
		}
		instanceID := strings.Split(providerURL.Path, "/")[2]
		eni, err := r.ec2Client.DescribeNetworkInterfaces(ctx, &ec2.DescribeNetworkInterfacesInput{
			Filters: []ec2types.Filter{
				{
					Name: new("attachment.instance-id"),
					Values: []string{
						instanceID,
					},
				},
			},
		})
		if err != nil {
			return ctrl.Result{}, err
		}

		if len(eni.NetworkInterfaces) != 1 {
			return ctrl.Result{}, fmt.Errorf("unexpected number of network interfaces for instance %q: %v", instanceID, len(eni.NetworkInterfaces))
		}

		if len(eni.NetworkInterfaces[0].Ipv6Prefixes) != 1 {
			return ctrl.Result{}, fmt.Errorf("unexpected amount of ipv6 prefixes on interface %q: %v", *eni.NetworkInterfaces[0].NetworkInterfaceId, len(eni.NetworkInterfaces[0].Ipv6Prefixes))
		}

		ipv6Address := aws.ToString(eni.NetworkInterfaces[0].Ipv6Prefixes[0].Ipv6Prefix)
		podCIDRs := []string{ipv6Address}
		if err := patchNodePodCIDRs(r.coreV1Client, ctx, node, podCIDRs); err != nil {
			return ctrl.Result{}, err
		}
	}

	return ctrl.Result{}, nil
}

func (r *AWSIPAMReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Detach extra network interfaces from the instance so only the primary ENI remains attached.
  2. Verify node.Spec.ProviderID encodes the correct instance ID (format aws:///<zone>/<i-...>) and that the instance still exists in EC2.
  3. If the node legitimately needs multiple ENIs, do not use this IPv6-prefix IPAM controller; assign podCIDRs another way (e.g. cloud-controller-manager or static cluster config).
  4. Re-check after a short delay — transient states during instance launch/termination can briefly return an unexpected interface count; rely on controller-runtime requeue/backoff.

Example fix

// before
if len(eni.NetworkInterfaces) != 1 {
	return ctrl.Result{}, fmt.Errorf("unexpected number of network interfaces for instance %q: %v", instanceID, len(eni.NetworkInterfaces))
}
// after
if len(eni.NetworkInterfaces) == 0 {
	klog.Warningf("no network interfaces yet for instance %q; requeueing", instanceID)
	return ctrl.Result{RequeueAfter: 10 * time.Second}, nil
}
if len(eni.NetworkInterfaces) > 1 {
	return ctrl.Result{}, fmt.Errorf("unexpected number of network interfaces for instance %q: %v", instanceID, len(eni.NetworkInterfaces))
}
Defensive patterns

Strategy: validation

Validate before calling

resp, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{
	InstanceIds: []string{instanceID},
})
if err != nil || len(resp.Reservations) == 0 {
	return fmt.Errorf("instance %s not found or describe failed", instanceID)
}
// only proceed when the instance has exactly one attached ENI

Type guard

func singleENI(eni *ec2.DescribeNetworkInterfacesOutput) bool {
	return eni != nil && len(eni.NetworkInterfaces) == 1
}

Try / catch

result, err := r.Reconcile(ctx, req)
if err != nil && strings.Contains(err.Error(), "unexpected number of network interfaces") {
	// log and alert instead of hot-looping; do not requeue immediately
	klog.Errorf("instance topology not single-ENI: %v", err)
	return ctrl.Result{}, nil
}

Prevention

When it happens

Trigger: DescribeNetworkInterfaces(attachment.instance-id == instanceID) returns len(NetworkInterfaces) != 1: the instance has additional attached ENIs (multi-NI instance, CNI-chained ENIs, load-balancer or EFA attachments), the filter matched the primary ENI of another role, or it matched none because the instance was terminated or the ProviderID-encoded instance ID is wrong.

Common situations: Nodes with extra ENIs attached for storage, monitoring, or EFA workloads; a malformed ProviderID like aws:///zone/<wrong-id> after node replacement; a stale/terminated instance id queried before EC2 state propagates; clusters where the AWS CNI or another controller attaches secondary ENIs to nodes.

Related errors


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