Restrict API access & upgrade often
NodeRestriction, version currency, exposure.
Two of the cheapest, highest-leverage hardening moves are unglamorous: shrink who can reach the control plane, and stay current. Start with NodeRestriction, an admission plugin that limits each kubelet to modifying only its own Node object and the pods bound to it — so a single compromised node cannot relabel other nodes, edit their pods, or read secrets it was never assigned. Turn it on in the API server’s admission plugin list.
- --enable-admission-plugins=NodeRestriction# pair with the Node authorizer (authorization-mode=Node,RBAC) so a kubelet# is authorized only for the objects its own node legitimately needs
Do not expose the API to the world
Reachability is not a security control, but unnecessary reachability is a liability. The API server should sit behind the network boundary — a firewall or security group that allows 6443 only from the networks that need it, no public load balancer in front of it by default. RBAC decides what an authenticated caller may do; the network decides who can even attempt to authenticate, and there is no reason to let the entire internet try.
Upgrade often
Kubernetes ships security fixes in patch releases, and the project supports only the three most recent minor versions — run months behind and you are shipping known, published CVEs in your control plane. Version skew is bounded too: the kubelet may trail the API server by a limited number of minors, never lead it, which dictates the upgrade order — control plane first, then nodes. With kubeadm the sequence is drain, upgrade the control-plane components, then upgrade and uncordon each node.
# control plane first$ sudo kubeadm upgrade plan$ sudo kubeadm upgrade apply v1.30.2# then each worker, one at a time$ kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data$ sudo kubeadm upgrade node && sudo systemctl restart kubelet$ kubectl uncordon node-1