kubernetes/kops · critical
no keypairID for
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.
Solutions
- Regenerate the nodeup config by re-running `kops update cluster` / `kops replace` so KeypairIDs is populated, then re-run nodeup
- Upgrade nodeup and kops-controller to matching cluster kOps versions (e.g. `kops upgrade cluster` then rolling-replace) since older versions omitted KeypairIDs
- Verify the keyset (e.g. "kubernetes-ca") exists in the state store: `kops get keypairs` and `kops create keypair kubernetes-ca` if missing
- 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
- Keep nodeup binary and kops-controller on the same version as the cluster
- Regenerate nodeup config on every cluster spec change before node bootstrapping
- Verify `kops get keypairs` shows the CA keyset before provisioning nodes
- Roll nodes via `kops rolling-update cluster` so configs are refreshed
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
- building nodeConfig for instanceGroup
- ConfigBase or ConfigServer is required
- decoding pem public key
- did not find keypair
- no keypair ID for
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/31a0537b8f517fe3.
Report an issue: GitHub.
Appendix: 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)