# KubeClientCertificateExpiration alert: what it means and how to fix it

What the KubeClientCertificateExpiration Prometheus alert means, its common causes, the PromQL rule and the runbook steps to fix it, with a ready-to-use rule in YAML.

Last reviewed 2026-10-31

Of the client certificates presented to the API server over the last 5 minutes, at least 1% expire within 7 days (warning) or within 24 hours (critical). The rules take the 1st percentile of their remaining lifetime. When they expire, those clients get `401 Unauthorized`. If they belong to a kubelet, a controller or the scheduler, nodes go NotReady or the control plane stops reconciling.

* Part of the [Kubernetes alert rules](https://n9e.github.io/alert-rules/kubernetes.md) (`kubernetes.yml`)

## The rule[​](#the-rule "Direct link to The rule")

The template splits this alert into 2 rules with different thresholds, windows and severities. Load all of them together.

### KubeClientCertificateExpiration-S2[​](#kubeclientcertificateexpiration-s2 "Direct link to KubeClientCertificateExpiration-S2")

Warning (`warning`) · Fires after: —

```
apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 604800
```

### KubeClientCertificateExpiration-S1[​](#kubeclientcertificateexpiration-s1 "Direct link to KubeClientCertificateExpiration-S1")

Critical (`critical`) · Fires after: —

```
apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 86400
```

Alert message: `A client certificate used to authenticate to the apiserver is expiring in less than 7.0 days.`

## Common causes[​](#common-causes "Direct link to Common causes")

* kubeadm issues control-plane certificates for one year and renews them during `kubeadm upgrade`. A cluster that has not been upgraded for a year runs into this.
* Kubelet client certificate rotation is off, or the CSRs it creates are not being approved.
* Long-lived kubeconfig files issued to people or CI systems with client certificates.
* Certificates generated by hand or by an external tool that has no renewal job.

## How to fix it[​](#how-to-fix-it "Direct link to How to fix it")

1. Run kubeadm certs check-expiration (kubeadm clusters) or openssl x509 -noout -dates to confirm the expiry;
2. On kubeadm clusters run kubeadm certs renew all and restart the control plane components;
3. kubelet client certificates usually rotate automatically — if not, check the rotateCertificates setting and CSR approval;
4. After renewal, verify the components loaded the new certificate (restart them) and re-check every node.

## Notes[​](#notes "Direct link to Notes")

* The metric is built from the certificates clients actually present, so it only reflects clients that have connected recently. It does not tell you which client is affected. On kubeadm clusters `kubeadm certs check-expiration` lists the control plane's own certificates.
* The expression selects `job="apiserver"`. If your scrape job or namespace is named differently, change these matchers or the rule never matches.

## Metrics it uses[​](#metrics-it-uses "Direct link to Metrics it uses")

* `apiserver_client_certificate_expiration_seconds_count` (kube-apiserver)
* `apiserver_client_certificate_expiration_seconds_bucket` (kube-apiserver)

## Related alerts[​](#related-alerts "Direct link to Related alerts")

* [KubeletClientCertificateExpiration](https://n9e.github.io/alert-rules/kubernetes.md#kubeletclientcertificateexpiration): Client certificate for Kubelet on node … expires in ….
* [KubeletServerCertificateExpiration](https://n9e.github.io/alert-rules/kubernetes.md#kubeletservercertificateexpiration): Server certificate for Kubelet on node … expires in ….
* [KubeNodeNotReady](https://n9e.github.io/alert-rules/kubernetes/kubenodenotready.md): … has been unready for more than 15 minutes.

## Prometheus rule YAML[​](#prometheus-rule-yaml "Direct link to Prometheus rule YAML")

Add this to a rules file loaded through `rule_files`, or download every Kubernetes rule at once as [`kubernetes.yml`](https://n9e.github.io/alert-rules/kubernetes.yml).

```
- alert: KubeClientCertificateExpiration-S2

  expr: |-

    apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 604800

  labels:

    severity: warning

  annotations:

    summary: "A client certificate used to authenticate to the apiserver is expiring in less than 7.0 days."

    runbook_url: "https://n9e.github.io/alert-rules/kubernetes/kubeclientcertificateexpiration"

- alert: KubeClientCertificateExpiration-S1

  expr: |-

    apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 86400

  labels:

    severity: critical

  annotations:

    summary: "A client certificate used to authenticate to the apiserver is expiring in less than 24.0 hours."

    runbook_url: "https://n9e.github.io/alert-rules/kubernetes/kubeclientcertificateexpiration"
```

**With Nightingale**: this rule ships in the [Kubernetes integration](https://n9e.github.io/integrations/kubernetes.md) template; [import it into a business group](https://n9e.github.io/docs/data/integrations/import.md) and Nightingale attaches the runbook to every alert it sends.

## Sources and license[​](#sources-and-license "Direct link to Sources and license")

The rule expression is adapted from [kubernetes-mixin](https://github.com/kubernetes-monitoring/kubernetes-mixin) (Apache-2.0). The runbook steps come from [Nightingale's integration templates](https://github.com/ccfos/nightingale/tree/main/integrations) (Apache-2.0); the explanation and causes are written for this page.
