kubernetes/kops · error

unable to resolve Kubernetes cluster API URL dns: %v

Error message

unable to resolve Kubernetes cluster API URL dns: %v

What it means

hasPlaceHolderIP resolves the cluster API hostname via net.LookupHost to see if DNS still returns kOps' placeholder IP (203.0.113.123 / ::1:1:1... style). If the hostname cannot be resolved at all, this error is returned — the API DNS record does not exist or DNS is unreachable. Validation cannot proceed because it cannot determine whether the API endpoint is live.

Source

Thrown at pkg/validation/validate_cluster.go:101

// ValidationNode represents the validation status for a node
type ValidationNode struct {
	Name     string             `json:"name,omitempty"`
	Zone     string             `json:"zone,omitempty"`
	Role     string             `json:"role,omitempty"`
	Hostname string             `json:"hostname,omitempty"`
	Status   v1.ConditionStatus `json:"status,omitempty"`
}

// hasPlaceHolderIP checks if the API DNS has been updated.
func hasPlaceHolderIP(host string) (string, error) {
	apiAddr, err := url.Parse(host)
	if err != nil {
		return "", fmt.Errorf("unable to parse Kubernetes cluster API URL: %v", err)
	}
	hostAddrs, err := net.LookupHost(apiAddr.Hostname())
	if err != nil {
		return "", fmt.Errorf("unable to resolve Kubernetes cluster API URL dns: %v", err)
	}

	sort.Strings(hostAddrs)
	for _, h := range hostAddrs {
		if h == dns.PlaceholderIP || h == dns.PlaceholderIPv6 {
			return h, nil
		}
	}

	return "", nil
}

func NewClusterValidator(cluster *kops.Cluster, cloud fi.Cloud, instanceGroupList *kops.InstanceGroupList, filterInstanceGroups func(ig *kops.InstanceGroup) bool, filterPodsForValidation func(pod *v1.Pod) bool, maxUnreadyNodes int, restConfig *rest.Config, k8sClient kubernetes.Interface) (ClusterValidator, error) {
	var allInstanceGroups []*kops.InstanceGroup

	for i := range instanceGroupList.Items {
		ig := &instanceGroupList.Items[i]
		allInstanceGroups = append(allInstanceGroups, ig)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the DNS record exists: dig/nslookup api.<cluster> and compare against the hosted zone (kops toolbox dns... or your DNS console)
  2. Wait for DNS propagation if the cluster was just created, then re-run kops validate cluster
  3. Run validation from inside the VPC / with a resolver that can see the private zone if the API is internal
  4. Check network egress (UDP/TCP 53) and VPN/route settings if resolution times out

Example fix

// before
$ kops validate cluster
# unable to resolve Kubernetes cluster API URL dns: lookup api.mycluster.example.com: no such host
// after
$ dig api.mycluster.example.com   # confirm the A record exists
$ kops validate cluster           # succeeds once DNS resolves
Defensive patterns

Strategy: retry

Validate before calling

_, err := net.LookupHost(hostFromURL(apiURL))
if err != nil {
    return fmt.Errorf("API host %s not resolvable yet: %v", hostFromURL(apiURL), err)
}

Try / catch

var ph string
err := retry.OnError(wait.Backoff{Steps: 6, Duration: 10 * time.Second},
    func(err error) bool { return isDNSTempFailure(err) },
    func() (err error) { ph, err = hasPlaceHolderIP(apiURL); return err })
if err != nil {
    return fmt.Errorf("API DNS still unresolvable: %w", err)
}

Prevention

When it happens

Trigger: net.LookupHost(apiAddr.Hostname()) returns an error: the API DNS record was never created, was deleted, or DNS servers are unreachable from the machine running validation (NXDOMAIN / no such host / i/o timeout).

Common situations: Running kops validate cluster before DNS propagation after cluster creation; internal (private) API endpoint validated from outside the VPC; Route53/Cloud DNS hosted zone misconfigured; corporate VPN or resolver not forwarding the zone.

Related errors


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