kubernetes/kops · error

gce cloud provider does not support surging

Error message

gce cloud provider does not support surging

What it means

gceCloudImplementation.DetachInstance is explicitly not implemented for GCE. Detaching an instance (used by rolling-update surging, where a new node is added before the old is removed) is unsupported, so the method unconditionally returns this error after logging at V(8).

Source

Thrown at upup/pkg/fi/cloudup/gce/instancegroups.go:93

	}

	return DeleteInstanceTemplate(c, mig.InstanceTemplate)
}

// DeleteInstance deletes a GCE instance
func (c *gceCloudImplementation) DeleteInstance(i *cloudinstances.CloudInstance) error {
	return recreateCloudInstance(c, i)
}

func (c *gceCloudImplementation) DeregisterInstance(i *cloudinstances.CloudInstance) error {
	klog.V(8).Info("GCE DeregisterInstance not implemented")
	return nil
}

// DetachInstance is not implemented yet. It needs to cause a cloud instance to no longer be counted against the group's size limits.
func (c *gceCloudImplementation) DetachInstance(i *cloudinstances.CloudInstance) error {
	klog.V(8).Info("gce cloud provider DetachInstance not implemented yet")
	return fmt.Errorf("gce cloud provider does not support surging")
}

// recreateCloudInstance recreates the specified instances, managed by an InstanceGroupManager
func recreateCloudInstance(c GCECloud, i *cloudinstances.CloudInstance) error {
	mig := i.CloudInstanceGroup.Raw.(*compute.InstanceGroupManager)

	klog.V(2).Infof("Recreating GCE Instance %s in MIG %s", i.ID, mig.Name)

	migURL, err := ParseGoogleCloudURL(mig.SelfLink)
	if err != nil {
		return err
	}

	op, err := c.Compute().InstanceGroupManagers().RecreateInstances(migURL.Project, migURL.Zone, migURL.Name, i.ID)
	if err != nil {
		if IsNotFound(err) {
			klog.Infof("Instance not found, assuming deleted: %q", i.ID)
			return nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Run rolling updates on GCE without surging: omit --surge (use the default non-surging rolling update).
  2. Use --cloud-aws only if surging is required, or wait for GCE detach support to be implemented.
  3. Alternatively, manually scale the MIG and drain nodes with kubectl drain if you need overlap.

Example fix

// before
kops rolling-update cluster mycluster --yes --surge
// after
kops rolling-update cluster mycluster --yes  # no --surge on GCE
Defensive patterns

Strategy: validation

Validate before calling

// feature-gate surging off for GCE before invoking rolling update
if cloudProvider == "gce" && strings.Contains(strings.Join(args, " "), "--surge") {
	return fmt.Errorf("--surge is not supported on GCE (DetachInstance unimplemented)")
}

Try / catch

err := cloud.DetachInstance(ci)
if err != nil && strings.Contains(err.Error(), "does not support surging") {
	// fall back to non-surging rolling update
	return rollingUpdateWithoutSurge(group)
}

Prevention

When it happens

Trigger: Any call to DetachInstance on a GCE cloud, which happens when running a rolling-update with surge enabled (kops rolling-update cluster --surge) against a cluster backed by GCE instance groups.

Common situations: Operators using the `--surge` flag on `kops rolling-update cluster` in a GCE cluster; surging works on AWS but not GCE, so the update fails once detach is attempted.

Related errors


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