kubernetes/kops · critical

error reading certificate %q: %v

Error message

error reading certificate %q: %v

What it means

The kube-apiserver-healthcheck sidecar fails in run() when os.ReadFile cannot read the CA certificate file given by --ca-cert. Without the CA bundle the healthcheck cannot build its x509 root pool to trust the API server. The check aborts before serving health endpoints.

Source

Thrown at cmd/kube-apiserver-healthcheck/main.go:156

	flag.StringVar(&clientCert, "client-cert", clientCert, "path to client certificate")
	flag.StringVar(&clientKey, "client-key", clientKey, "path to client key")
	flag.StringVar(&caCert, "ca-cert", caCert, "path to ca certificate")

	klog.InitFlags(nil)
	// Opt into the new klog behavior so that -stderrthreshold is honored even
	// when -logtostderr=true (the default).
	// Ref: kubernetes/klog#212, kubernetes/klog#432
	flag.Set("legacy_stderr_threshold_behavior", "false") //nolint:errcheck
	flag.Set("stderrthreshold", "INFO")                   //nolint:errcheck

	flag.Parse()

	tlsConfig := &tls.Config{}

	if caCert != "" {
		b, err := os.ReadFile(caCert)
		if err != nil {
			return fmt.Errorf("error reading certificate %q: %v", caCert, err)
		}
		rootCAs := x509.NewCertPool()
		rootCAs.AppendCertsFromPEM(b)
		tlsConfig.RootCAs = rootCAs
	}

	if clientKey != "" {
		keypair, err := tls.LoadX509KeyPair(clientCert, clientKey)
		if err != nil {
			return fmt.Errorf("error reading client keypair: %v", err)
		}

		tlsConfig.Certificates = []tls.Certificate{keypair}
	}

	transport := &http.Transport{
		TLSClientConfig: tlsConfig,
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the CA cert file exists and is readable at the given path (ls -l / cat the file).
  2. Fix the --ca-cert flag or the secret volumeMount in the pod manifest.
  3. Ensure the secret containing the CA exists in the pod's namespace.
  4. Restart the sidecar after the volume is mounted, or add an init wait for the file.

Example fix

// before
run("--ca-cert", "/etc/missing/ca.crt", ...)
// after
run("--ca-cert", "/etc/kubernetes/pki/ca.crt", ...)
Defensive patterns

Strategy: validation

Validate before calling

// before starting the healthcheck
if _, err := os.Stat(caCertPath); err != nil {
    return fmt.Errorf("CA cert unavailable at %s: %w", caCertPath, err)
}
if _, err := os.ReadFile(caCertPath); err != nil {
    return err
}

Try / catch

// Go: wrap and fail fast at startup
if err := run(); err != nil {
    klog.Fatalf("healthcheck terminated: %v", err)
}

Prevention

When it happens

Trigger: The path in --ca-cert does not exist, is unreadable (permissions), is a dangling symlink/misconfigured mount, or the secret volume is not yet mounted when the sidecar starts.

Common situations: Kubernetes secret volume not mounted into the sidecar pod; wrong path flag; file deleted or permissions changed by a security policy; manifest templating error leaving a placeholder path.

Understand the failure class

Related errors


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