kubernetes/kops · critical

no keypairID for %q

Error message

no keypairID for %q

What it means

GetBootstrapCert looks up the keypair ID for the given signer in NodeupConfig.KeypairIDs; nodeup refuses to request bootstrap certificates from kops-controller when the signer has no keypair ID recorded. This means the nodeup config was generated without the keypair mapping the node needs to bootstrap its certificates.

Source

Thrown at nodeup/pkg/model/context.go:271

	return kubeConfig.GetConfig()
}

// GetBootstrapCert requests a certificate keypair from kops-controller.
func (c *NodeupModelContext) GetBootstrapCert(name string, signer string) (cert, key fi.Resource, err error) {
	if c.IsMaster {
		panic("control plane nodes can't get certs from kops-controller")
	}
	b, ok := c.bootstrapCerts[name]
	if !ok {
		b = &nodetasks.BootstrapCert{
			Cert: &fi.NodeupTaskDependentResource{},
			Key:  &fi.NodeupTaskDependentResource{},
		}
		c.bootstrapCerts[name] = b
	}
	c.bootstrapKeypairIDs[signer] = c.NodeupConfig.KeypairIDs[signer]
	if c.bootstrapKeypairIDs[signer] == "" {
		return nil, nil, fmt.Errorf("no keypairID for %q", signer)
	}
	return b.Cert, b.Key, nil
}

// BuildBootstrapKubeconfig generates a kubeconfig with a client certificate from either kops-controller or the state store.
func (c *NodeupModelContext) BuildBootstrapKubeconfig(name string, ctx *fi.NodeupModelBuilderContext) (fi.Resource, error) {
	cert, key, err := c.GetBootstrapCert(name, fi.CertificateIDCA)
	if err != nil {
		return nil, err
	}

	kubeConfig := &nodetasks.KubeConfig{
		Name: name,
		Cert: cert,
		Key:  key,
		CA:   fi.NewStringResource(c.NodeupConfig.CAs[fi.CertificateIDCA]),
	}
	if c.HasAPIServer {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Regenerate the nodeup config by re-running `kops update cluster` / `kops replace` so KeypairIDs is populated, then re-run nodeup
  2. Upgrade nodeup and kops-controller to matching cluster kOps versions (e.g. `kops upgrade cluster` then rolling-replace) since older versions omitted KeypairIDs
  3. Verify the keyset (e.g. "kubernetes-ca") exists in the state store: `kops get keypairs` and `kops create keypair kubernetes-ca` if missing
  4. Check that the instance group role matches the nodeup config being applied (don't reuse a config from another node role)
Defensive patterns

Strategy: validation

Validate before calling

// before nodeup builds bootstrap certs, check the config map
if signerID := nodeupConfig.KeypairIDs[signer]; signerID == "" {
    return fmt.Errorf("nodeup config missing KeypairIDs entry for %q; regenerate config with kops update cluster", signer)
}

Try / catch

if cert, key, err := ctx.GetBootstrapCert(name, fi.CertificateIDCA); err != nil {
    if strings.Contains(err.Error(), "no keypairID") {
        klog.Fatalf("stale nodeup config (missing KeypairIDs); re-run 'kops update cluster --yes' and restart nodeup: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: NodeupConfig.KeypairIDs lacks an entry for the signer (typically "kubernetes-ca" used via BuildBootstrapKubeconfig, buildKubeletServingCertificate, or buildCiliumEtcdSecrets) on a non-master node, so the map lookup returns "" and GetBootstrapCert fails.

Common situations: Stale or truncated nodeup.conf from an older kOps version that didn't populate KeypairIDs; cluster upgraded across kOps versions where the bootstrap-protocol config changed; node bootstrapping with a config generated for a different role.

Related errors


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