kubernetes/kops · error

error associating VPC with hosted zone %q: %v

Error message

error associating VPC with hosted zone %q: %v

What it means

kOps' DNSZone task failed to associate a VPC with an existing private Route53 hosted zone while applying AWS changes. kOps calls Route53's AssociateVPCWithHostedZone when a private zone's VPC associations need updating; any AWS API rejection is wrapped in this error. It indicates the zone will not be resolvable from the cluster's VPC as intended.

Source

Thrown at upup/pkg/fi/cloudup/awstasks/dnszone.go:216

		e.ZoneID = response.HostedZone.Id
	} else {
		if changes.PrivateVPC != nil {
			request := &route53.AssociateVPCWithHostedZoneInput{
				HostedZoneId: a.ZoneID,
				VPC: &route53types.VPC{
					VPCId:     e.PrivateVPC.ID,
					VPCRegion: route53types.VPCRegion(t.Cloud.Region()),
				},
			}

			changes.PrivateVPC = nil

			klog.V(2).Infof("Updating DNSZone %q", name)

			_, err := t.Cloud.Route53().AssociateVPCWithHostedZone(ctx, request)
			if err != nil {
				return fmt.Errorf("error associating VPC with hosted zone %q: %v", name, err)
			}
		}

		empty := &DNSZone{}
		if !reflect.DeepEqual(empty, changes) {
			klog.Warningf("cannot apply changes to DNSZone %q: %v", name, changes)
		}
	}

	// We don't tag the zone - we expect it to be shared
	return nil
}

type terraformRoute53ZoneAssociation struct {
	ZoneID    *terraformWriter.Literal `cty:"zone_id"`
	VPCID     *terraformWriter.Literal `cty:"vpc_id"`
	Lifecycle *terraform.Lifecycle     `cty:"lifecycle"`
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the IAM policy grants route53:AssociateVPCWithHostedZone on the zone
  2. Confirm the hosted zone ID in the cluster spec points to a private zone in the same account as the VPC
  3. Check the VPC ID and region in the cluster spec match an existing VPC
  4. Run with klog V(2) to see the underlying AWS error detail and act on it

Example fix

// before (IAM policy missing route53:AssociateVPCWithHostedZone)
{"Effect":"Deny","Action":["route53:ChangeResourceRecordSets"],"Resource":"*"}
// after
{"Effect":"Allow","Action":["route53:AssociateVPCWithHostedZone","route53:ChangeResourceRecordSets"],"Resource":"*"}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check zone and permissions
svc := route53.NewFromClient(cfg)
zone, err := svc.GetHostedZone(ctx, &route53.GetHostedZoneInput{Id: aws.String(zoneID)})
if err != nil { return err }
if zone.HostedZone.Config == nil || !aws.ToBool(zone.HostedZone.Config.PrivateZone) {
    return fmt.Errorf("zone %s is not private", zoneID)
}

Type guard

func isAssociationErr(err error) bool { return err != nil && strings.Contains(err.Error(), "AssociateVPCWithHostedZone") }

Try / catch

_, err := cloud.Route53().AssociateVPCWithHostedZone(ctx, request)
if err != nil {
    var opErr *smithy.OperationError
    if errors.As(err, &opErr) { klog.Errorf("route53 op failed: %v", opErr.Unwrap()) }
    return fmt.Errorf("error associating VPC with hosted zone %q: %w", name, err)
}

Prevention

When it happens

Trigger: RenderAWS on a private DNSZone when changes.PrivateVPC is set and the AssociateVPCWithHostedZone call returns an error — e.g. wrong hosted zone ID, zone not actually private, VPC ID/region mismatch, or IAM permissions missing route53:AssociateVPCWithHostedZone.

Common situations: Creating/updating private clusters where the hosted zone was pre-created externally with a different VPC association; credentials lacking Route53 permissions; zone hosted in a different region account than the VPC.

Related errors


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