kubernetes/kops · error
did not find API endpoint
Error message
did not find API endpoint
What it means
After querying GetApiIngressStatus, findSystemEndpoints builds a list of SystemEndpoint values (kops-controller and kube-apiserver addresses). If the cloud returns an empty ingress list — no hostnames and no IPs — there is nothing to publish and the controller raises 'did not find API endpoint'. This prevents creating a KopsControlPlane whose status has no usable endpoints, which would later break bootstrap-data generation.
Source
Thrown at pkg/controllers/clusterapi/cluster_controller.go:228
target.Endpoint = ingress.Hostname
}
if ingress.IP != "" {
target.Endpoint = ingress.IP
}
target.Type = capikops.SystemEndpointTypeKubeAPIServer
if ingress.InternalEndpoint {
target.Scope = capikops.SystemEndpointScopeInternal
} else {
target.Scope = capikops.SystemEndpointScopeExternal
}
targets = append(targets, target)
}
// TODO: Sort targets
// TODO: Mark targets as atomic list
if len(targets) == 0 {
return nil, fmt.Errorf("did not find API endpoint")
}
return targets, nil
}
func (s *clusterScope) createKopsControlPlane(ctx context.Context, kube client.Client) error {
// This is because of network tags in cloud-provider-gcp
// TODO: cloud-provider-gcp should not assume cluster name is a valid prefix
name := gce.SafeClusterName(s.Cluster.GetName())
status := capikops.KopsControlPlaneStatus{}
systemEndpoints, err := s.findSystemEndpoints(ctx)
if err != nil {
return err
}
status.SystemEndpoints = systemEndpoints
View on GitHub (pinned to 4c8573c808)
Solutions
- Wait for the API load balancer to be assigned an IP/hostname and re-reconcile (controller will retry)
- Verify the load balancer frontend and target pools/backends are configured in the cloud console
- Check the cluster spec networking (subnets, networkID) matches the actual cloud resources
- If using internal-only endpoints, confirm the provider surfaces internal ingress entries
Example fix
// before
if len(targets) == 0 {
return nil, fmt.Errorf("did not find API endpoint")
}
// after: requeue instead of erroring while the LB is still provisioning
if len(targets) == 0 {
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
} Defensive patterns
Strategy: retry
Validate before calling
ingresses, _ := cloud.GetApiIngressStatus(clusterInternal)
if len(ingresses) == 0 {
klog.Warning("API load balancer has no ingress addresses yet")
} Try / catch
endpoints, err := s.findSystemEndpoints(ctx)
if err != nil && err.Error() == "did not find API endpoint" {
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil // LB still provisioning
} Prevention
- Check the load balancer has an assigned IP/hostname in the cloud console
- Confirm subnets/network config in the cluster spec match reality
- Allow time between cluster creation and first reconcile
- For private clusters, verify internal ingress entries are surfaced by the provider
When it happens
Trigger: The API load balancer has no ingress entries yet (LB created but no addresses assigned), the load balancer was deleted, or the cloud provider returns an empty list for a cluster whose networking is not yet wired (e.g. missing subnets/frontend IP).
Common situations: Reconcile fires immediately after cluster creation before the LB gets an external IP/hostname; private-only clusters where only internal endpoints exist and the provider omits them; LB misconfiguration in the cloud console.
Related errors
- error getting ingress status: %v
- error getting ForwardingRule %q: %v
- error loading default AWS config: %v
- error populating configuration: %v
- error populating configuration: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/08907b01313a5fec.
Report an issue: GitHub.