kubernetes/kops · error

DNS ZoneID not set

Error message

DNS ZoneID not set

What it means

PolicyResource.Open builds the Route53 IAM policy for the cluster's DNS zone. It reads the hosted zone ID from the DNSZone task; if both ZoneID and DNSName are empty it cannot construct the Route53 ARN and returns 'DNS ZoneID not set'. The source comment flags this as a dependency-analysis failure: DNSZone.Find should normally populate ZoneID before Open runs.

Source

Thrown at pkg/model/iam/iam_builder.go:789

// Open produces the AWS IAM policy for the given role
func (b *PolicyResource) Open() (io.Reader, error) {
	// Defensive copy before mutation
	pb := *b.Builder

	if b.DNSZone != nil {
		hostedZoneID := fi.ValueOf(b.DNSZone.ZoneID)
		if hostedZoneID == "" {
			// ZoneID is normally populated by DNSZone.Find before this runs. In dry-run modes that
			// skip Find (e.g. `kops get assets`), it may still be empty; fall back to the DNS name
			// so the policy renders. The resulting ARN is not a valid Route53 ARN, but the policy
			// is not applied in that mode.
			hostedZoneID = fi.ValueOf(b.DNSZone.DNSName)
			klog.V(4).Infof("Falling back to DNS name %q for IAM policy because ZoneID is empty", hostedZoneID)
		}
		if hostedZoneID == "" {
			// Dependency analysis failure?
			return nil, fmt.Errorf("DNS ZoneID not set")
		}
		pb.HostedZoneID = hostedZoneID
	}

	policy, err := pb.BuildAWSPolicy()
	if err != nil {
		return nil, fmt.Errorf("error building IAM policy: %v", err)
	}
	if policy == nil {
		return bytes.NewReader([]byte{}), nil
	}
	j, err := policy.AsJSON()
	if err != nil {
		return nil, fmt.Errorf("error building IAM policy: %v", err)
	}
	return bytes.NewReader([]byte(j)), nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the hosted zone still exists: `aws route53 list-hosted-zones` and compare with `kops get cluster -o yaml` (spec.dnsZone / dns name).
  2. Recreate the hosted zone or fix the DNS configuration in the cluster spec, then rerun `kops update cluster` so DNSZone.Find populates ZoneID.
  3. If in dry-run, ensure the DNSName is set on the DNSZone task so the fallback ARN path works.
  4. Upgrade kOps if a recent version changed DNS task dependency ordering; check release notes for PolicyResource/DNSZone fixes.
Defensive patterns

Strategy: fallback

Validate before calling

// Before update, confirm the hosted zone exists and is reachable
zones, err := route53Client.ListHostedZonesByName(&route53.ListHostedZonesByNameInput{DNSName: aws.String(dnsName)})
if err != nil || len(zones.HostedZones) == 0 {
    return fmt.Errorf("no Route53 hosted zone found for %s", dnsName)
}

Try / catch

r, err := policyResource.Open()
if err != nil {
    if strings.Contains(err.Error(), "DNS ZoneID not set") {
        // ensure DNSZone task Find() ran; check hosted zone exists in AWS
    }
    return err
}

Prevention

When it happens

Trigger: `kops update cluster` (with DNS managed via Route53) where PolicyResource.Open executes before the DNSZone task has run Find, or the DNS zone record was deleted from AWS so Find returns nothing and DNSName is also unset.

Common situations: The Route53 hosted zone was deleted out-of-band while kOps state still references it; dry-run/CI modes that skip DNS zone lookup; task dependency graph issue after interrupted updates; kops get assets or similar flows where Find is bypassed and even DNSName is empty.

Related errors


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