skip to content

In a kubeadm-built Kubernetes cluster, why do the control-plane certificates expire after one year, and how do you check when they expire?

level: juniorimportance: should knowfreq 52%

answer

  1. short leaves, long roots
  2. three CAs, not one
  3. ten years versus one year
  4. a kubeadm certs subcommand
  5. the kubelet renews its own

basics

~20 s

kubeadm creates a cluster PKI in /etc/kubernetes/pki: CAs valid for ten years and leaf certificates valid for one year, so a stolen leaf is not useful for long. Running kubeadm certs check-expiration on a control-plane node shows each expiry date.

solid answer

~40 s

`kubeadm init` generates three CAs (the cluster `ca`, the `front-proxy-ca` and the `etcd-ca`) with a ten-year lifetime, and uses them to sign one-year leaf certificates: the API server's serving cert, its client certs towards kubelets and etcd, the etcd server/peer certs, and the client certs embedded in `admin.conf`, `controller-manager.conf` and `scheduler.conf`. Leaves are short-lived so that a leaked one stops being useful and so that renewal is a routine operation rather than a crisis. `kubeadm certs check-expiration` lists every leaf and CA with its expiry, residual time and signing CA. The kubelet's own client certificate is not on that list, because the kubelet rotates it itself.

code

bash · 2 lines
bash
sudo kubeadm certs check-expiration
sudo openssl x509 -noout -enddate -in /etc/kubernetes/pki/apiserver.crt

go deeper

for a junior

Know where kubeadm keeps the PKI, that leaves last a year and CAs ten, and the command that shows expiry dates.

for a middle

Explain why there are three CAs, which certificates each signs, and why the kubelet's client certificate is not in kubeadm's expiry report.

for a senior

Show that you track residual time on every control-plane node, alert on it, and know that yearly upgrades renew leaves as a side effect.

for a principal

Weigh the leaf lifetime against how often you operate the cluster: shorter lifetimes limit a leak's blast radius but need automated renewal you can trust.

## What the cluster PKI is A Kubernetes control plane is a set of processes that talk to each other over **mutual TLS**. The API server presents a **serving certificate** to clients, and clients such as the scheduler present **client certificates** that the API server checks against a trusted **certificate authority (CA)**. A CA is a key pair whose certificate other parties trust; anything it signs is accepted as genuine. When you run `kubeadm init`, kubeadm writes this whole PKI to `/etc/kubernetes/pki` (plus a few kubeconfig files in `/etc/kubernetes`). On a 9-node bare-metal cluster running an IoT telemetry ingest gateway, those files sit on each of the three control-plane nodes. ## CAs versus leaf certificates kubeadm creates three separate CAs, so that trust in one area does not grant trust in another: | CA | Signs | Default lifetime | |---|---|---| | `ca` (cluster CA) | API server serving cert, `apiserver-kubelet-client`, kubeconfig client certs | 10 years | | `front-proxy-ca` | `front-proxy-client`, used by the aggregation layer | 10 years | | `etcd-ca` | `etcd-server`, `etcd-peer`, `etcd-healthcheck-client`, `apiserver-etcd-client` | 10 years | The certificates those CAs sign are **leaf certificates**, and kubeadm gives each of them **one year** (8760h). The same directory also holds `sa.key`/`sa.pub`. That is the key pair used to sign ServiceAccount tokens, a bare key pair with no certificate, so it has no expiry date. Why the split? - **Blast radius**: a leaked leaf key is only useful until its expiry. A leaked CA key lets an attacker mint any identity. - **Routine renewal**: a leaf can be replaced without changing what anyone trusts, because the CA stays the same. - **Rare CA changes**: replacing a CA means updating trust everywhere, so it gets a long lifetime. In the `ClusterConfiguration` of the `kubeadm.k8s.io/v1beta4` config you can change these defaults with `certificateValidityPeriod` and `caCertificateValidityPeriod`. ## Checking expiry Run this on a control-plane node: ```bash sudo kubeadm certs check-expiration ``` It prints two tables. The first lists each leaf certificate and each kubeconfig-embedded certificate, with columns `EXPIRES`, `RESIDUAL TIME`, `CERTIFICATE AUTHORITY` and `EXTERNALLY MANAGED`. The second lists the CAs. A row showing `EXTERNALLY MANAGED` as `yes` means kubeadm does not hold that CA's private key, so it cannot renew that certificate for you. What the output does **not** show: 1. The kubelet's client certificate. `kubelet.conf` points at `/var/lib/kubelet/pki/kubelet-client-current.pem`, and kubeadm leaves that file to the kubelet, which renews it through the CertificateSigningRequest API. 2. Other control-plane nodes. Each node has its own copies, so you run the check on every one. If you only have a certificate file, `openssl x509 -noout -enddate -in <file>` prints its `notAfter` date. ## Why this matters in interviews If nobody renews them, all the one-year leaves expire at about the same moment, roughly a year after `kubeadm init`. The cluster then stops working all at once. `kubectl` fails with `x509: certificate has expired or is not yet valid`, the controller manager and scheduler lose their API connection, and the workloads keep running only until something needs the control plane. Interviewers want to hear that you know about this deadline and check it on a schedule. ## Keeping ahead of it - A `kubeadm upgrade apply` or `kubeadm upgrade node` renews the leaf certificates by default, so a cluster upgraded at least once a year rarely reaches expiry. - Otherwise, run `kubeadm certs renew all` on each control-plane node before the deadline, then restart the control-plane static pods. - Monitor the residual time and alert well ahead (for example at 30 days), rather than finding out from an outage. ## Common misreadings - **"Everything expires after a year."** Only the leaves do. The CAs last ten years, and `sa.key` never expires. - **"One node's output speaks for the cluster."** Each control-plane node has its own files. A node added 5 months after `kubeadm init` has leaves that expire 5 months later than the others. - **"Workers have nothing to check."** Workers have no control-plane leaves, but their kubelet client certificate still has an expiry date. It stays healthy only while rotation keeps working, so check `kubelet-client-current.pem` on nodes that have been offline for a long time. - **"Externally managed means nothing to do."** It means someone outside kubeadm must renew it on time.

  • Why does kubeadm keep a separate etcd CA instead of signing etcd certificates with the cluster CA?
    etcd trusts any client certificate its CA signed, and a client it trusts can read and write the whole cluster state. With a dedicated `etcd-ca`, a certificate signed by the cluster CA, such as a user's kubeconfig cert, is not accepted by etcd. Only `apiserver-etcd-client` and the etcd health-check client can reach the datastore.
  • Does a kubeadm cluster that is upgraded regularly still need manual certificate renewal?
    Usually not. `kubeadm upgrade apply` and `kubeadm upgrade node` renew the leaf certificates by default, controlled by the `--certificate-renewal` flag, so upgrading at least once a year resets the one-year clock. Renewal is still needed if you skip upgrades for a year or disable that flag, and it never covers the CAs.

A company keeps its founding charter for decades but reissues employee badges every year. A lost badge stops working soon, and replacing a badge never means rewriting the charter.

saying these in an interview costs you the question

  • All kubeadm certificates, CAs included, expire after one year
  • kubeadm certs check-expiration also shows the kubelet's client certificate
  • A certificate that expires only matters for kubectl users, not components
  • kubeadm certs renew also renews the cluster CA
  • The sa.key ServiceAccount signing key expires with the other certificates