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
- 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: %w
- decoding pem public key
- unsupported cloud provider for authenticator %q
- no keypair ID for %q
- did not find keypair %s for %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/31a0537b8f517fe3.
Report an issue: GitHub.