kubernetes/kops · error

CAPI Machine is missing cluster.x-k8s.io/deployment-name lab

Error message

CAPI Machine is missing cluster.x-k8s.io/deployment-name label

What it means

buildInstanceGroupFromCAPI derives an InstanceGroup from a CAPI Machine. kOps requires the machine to carry the cluster.x-k8s.io/deployment-name label to know which instance group it belongs to; this error is thrown when that label is empty.

Source

Thrown at cmd/kops-controller/pkg/server/node_config.go:125

			}
			if secret != nil && secret.Data != nil {
				nodeConfig.NodeSecrets[id] = secret.Data
			}
		}
	}

	return nodeConfig, nil
}

// buildInstanceGroupFromCAPI builds an InstanceGroup from a CAPI Machine, for building bootstrap data.
// It builds a minimal instanceGroup, because many fields (e.g. image, machineType, minSize, maxSize)
// are not relevant for building the bootstrap data.
func (s *Server) buildInstanceGroupFromCAPI(ctx context.Context, capiMachine *clusterapi.Machine) (*kops.InstanceGroup, error) {
	log := klog.FromContext(ctx)

	capiDeploymentName := capiMachine.GetDeploymentName()
	if capiDeploymentName == "" {
		return nil, fmt.Errorf("CAPI Machine is missing cluster.x-k8s.io/deployment-name label")
	}
	failureDomain := capiMachine.GetFailureDomain()
	if failureDomain == "" {
		return nil, fmt.Errorf("CAPI Machine is missing spec.failureDomain")
	}

	ig := &kops.InstanceGroup{}
	ig.Labels = map[string]string{
		// kops.LabelClusterName: cluster.Name, // Should not matter
	}
	ig.Name = capiDeploymentName

	// "maxSize": 1, // Should not matter
	// "minSize": 1, // Should not matter
	// "machineType": "", // Should not matter
	// "subnets": // Should not matter
	ig.Spec.Zones = []string{failureDomain}
	ig.Spec.Role = "Node" // TODO: Support other roles?

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Add cluster.x-k8s.io/deployment-name label to the CAPI Machine
  2. Fix the MachineTemplate so the label is propagated to Machines
  3. Recreate the Machine via kOps-managed machine deployment
  4. Verify CAPI/kOps version compatibility

Example fix

// before
metadata:
  labels: {}
// after
metadata:
  labels:
    cluster.x-k8s.io/deployment-name: my-master-group
Defensive patterns

Strategy: validation

Validate before calling

if m.Labels["cluster.x-k8s.io/deployment-name"] == "" {
    return fmt.Errorf("machine %s missing deployment-name label", m.Name)
}

Type guard

func hasDeploymentName(m *capi.Machine) bool {
    return m.GetDeploymentName() != ""
}

Prevention

When it happens

Trigger: A bootstrap request arrives from a CAPI Machine whose metadata.labels lack cluster.x-k8s.io/deployment-name, so capiMachine.GetDeploymentName() returns "".

Common situations: Machine template patched by another tool stripping labels; Machine created manually or by an older/foreign controller; kOps managed machinepool templates updated outside kOps.

Related errors


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