kubernetes/kops · error

unknown CA %q

Error message

unknown CA %q

What it means

The kops-controller server keystore is an in-memory CA store preloaded at startup from a filesystem PKI directory (one <name>.crt / <name>.key pair per configured CA). FindPrimaryKeypair throws "unknown CA %q" when it is asked for a CA name that was never loaded into that map — i.e. the requested CA is not one of the CAs this controller instance was configured to serve.

Source

Thrown at cmd/kops-controller/pkg/server/keystore.go:49

type keystore struct {
	keys    map[string]keystoreEntry
	keySets map[string]*fi.Keyset
}

type keystoreEntry struct {
	certificate *pki.Certificate
	key         *pki.PrivateKey
}

var _ pki.Keystore = &keystore{}
var _ fi.CAStore = &keystore{}

// FindPrimaryKeypair implements pki.Keystore
func (k *keystore) FindPrimaryKeypair(ctx context.Context, name string) (*pki.Certificate, *pki.PrivateKey, error) {
	entry, ok := k.keys[name]
	if !ok {
		return nil, nil, fmt.Errorf("unknown CA %q", name)
	}
	return entry.certificate, entry.key, nil
}

// FindKeyset finds a Keyset.  If the keyset is not found, it returns (nil, nil).
func (k *keystore) FindKeyset(ctx context.Context, name string) (*fi.Keyset, error) {
	keySet, ok := k.keySets[name]
	if !ok {
		return nil, nil
	}
	return keySet, nil
}

// StoreKeyset writes a Keyset to the store.
func (k *keystore) StoreKeyset(ctx context.Context, name string, keyset *fi.Keyset) error {
	return fmt.Errorf("server-side client does not support StoreKeyset")
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check which CAs the controller was started with (the `cas` list passed to newKeystore) and confirm the requested CA name is among them
  2. Verify basePath contains <name>.crt and <name>.key for the requested CA and that newKeystore loaded it (startup would have failed otherwise)
  3. Align the client: ensure the requesting node/feature only requests CAs the controller serves; etcd-manager CAs are deliberately not served server-side
  4. Upgrade kops-controller to match the kOps version of the cluster if a newer feature requests a newly introduced CA

Example fix

// before: client requests a CA the controller does not serve
kp, err := client.FindPrimaryKeypair(ctx, "etcd-clients-ca")

// after: request a served CA, or load the CA server-side
kp, err := client.FindPrimaryKeypair(ctx, "kubernetes-ca")
Defensive patterns

Strategy: validation

Validate before calling

// Before requesting, check the CA is in the controller's configured list
cas, err := serverKeystoreConfiguredCAs() // e.g. from controller config / keypair-ids.yaml
if !slices.Contains(cas, caName) {
	return fmt.Errorf("CA %q is not served by this controller (served: %v)", caName, cas)
}

Type guard

func isUnknownCA(err error) bool {
	return err != nil && strings.Contains(err.Error(), "unknown CA ")
}

Try / catch

cert, key, err := ks.FindPrimaryKeypair(ctx, caName)
if err != nil {
	if isUnknownCA(err) {
		// fall back to cluster keystore or skip this CA
		return fallbackKeystore.FindPrimaryKeypair(ctx, caName)
	}
	return err
}

Prevention

When it happens

Trigger: A request path (e.g. issue-cert / pki.Keystore lookup via FindPrimaryKeypair) names a CA that is absent from k.keys: the CA was not listed in the controller's --ca-values/configured CAs at startup, the <name>.crt/<name>.key files were missing in basePath, or a client (kops-controller client/nodeup) requests a keypair for a CA name the server does not serve (e.g. etcd-manager CAs, which are intentionally not loaded).

Common situations: A node requests a certificate for a CA the controller was not started with (misconfigured controller flags); a new CA type was added in a newer kOps version but the controller still runs an older version with a narrower CA list; files in the PKI basePath were renamed or removed so the CA silently failed to load (actually failing earlier in newKeystore) or was never configured.

Related errors


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