Chapter 1 of 9 · 8 checks · 4 min
Cluster version, upgrades and control plane access
Whether the cluster itself is on a supported release, can be upgraded safely, and keeps its control plane out of reach.
The cluster runs a Kubernetes minor release that still gets patchesMust
Why it matters and how to check
The Kubernetes project maintains the three most recent minor releases, and since 1.19 each minor release gets roughly one year of patch support. A cluster on an unmaintained release gets no security fixes, and managed providers eventually force an upgrade on their schedule instead of yours.
To verify: run
kubectl versionand compare the server version with the release history on kubernetes.io/releases (or your provider's version calendar). Note the end of life date for your minor version and put the next upgrade in the team's plan at least a few months before it.Example
Shell kubectl version kubectl get nodes -o custom-columns=NAME:.metadata.name,KUBELET:.status.nodeInfo.kubeletVersionNode and client versions are within the supported skewShould
Why it matters and how to check
The version skew policy says a kubelet must never be newer than the API server and may be up to three minor versions older;
kubectlis supported one minor version either side of the API server. Nodes left three minor versions behind block the next control plane upgrade.To verify: compare the server version with each node's kubelet version from the command above. Flag any node pool more than one minor behind, since it shrinks the room you have for the next upgrade. Check the
kubectlversion pinned in CI and in runbooks as well.There is an upgrade runbook, and it has been rehearsed on a non-production clusterShould
Why it matters and how to check
Upgrades are where many production clusters break. The project's policy is that the API server must not skip minor versions, the control plane goes first, and a kubelet minor upgrade needs the node drained first because in-place minor upgrades are not supported. Admission webhooks also need to handle the new version's resources before you start.
To verify: find the written upgrade procedure and confirm it covers the order (control plane, then node pools), the drain step, the rollback position and who watches the workloads. Check the last upgrade was rehearsed on staging, and that the workload's PDBs allowed the drains to finish.
Manifests and charts use no deprecated or removed API versionsMust
Why it matters and how to check
Each release removes some deprecated API versions. A manifest or Helm chart that still uses one keeps working until the upgrade that removes it, then fails to apply in the middle of an incident or a deploy.
To verify: ask the API server which deprecated APIs are still being requested; it exposes a metric for exactly this. Run your manifests through a server-side dry run against a cluster on the next minor version as part of the upgrade rehearsal.
Example
Shell kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis kubectl apply --dry-run=server -f k8s/ --recursiveThe API server, kubelet API and etcd are not exposed to the internetMust
Why it matters and how to check
The Kubernetes security checklist lists this directly: the Kubernetes API, the kubelet API and etcd should not be publicly reachable. It also notes that the kubelet's default authentication and authorization are overly permissive when it runs without a config file, and that access to etcd is equivalent to root on the cluster.
To verify: on a managed cluster, check the API endpoint setting (private endpoint, or a public one limited to known CIDR ranges). From a machine outside your network, try to reach the API server and a node's kubelet port and confirm both fail. On self-managed clusters, confirm etcd only accepts connections from the API servers, using mutual TLS.
Nobody uses system:masters for day-to-day accessMust
Why it matters and how to check
Members of
system:mastersbypass RBAC entirely, and a client certificate in that group cannot be revoked short of rotating the cluster CA. The security checklist says that after bootstrapping, neither users nor components should authenticate assystem:masters; it is a break-glass mechanism only.To verify: list how people actually get cluster access (SSO through the provider, OIDC, short-lived credentials) and confirm admin kubeconfigs with
system:masterscertificates are stored offline for emergencies. Ask a regular engineer to runkubectl auth can-i --listand check the result matches their role, not cluster-admin.Cluster access is reviewed and certificates have a known expiryShould
Why it matters and how to check
The security checklist asks for a periodic access review no more than 24 months apart, and for intermediate and leaf certificates that expire no more than 3 years out. People change teams; bindings granted for a migration stay forever unless someone looks.
To verify: export ClusterRoleBindings and RoleBindings and walk through them with the owning team, removing anyone who no longer needs access. On kubeadm clusters,
kubeadm certs check-expirationlists each certificate's expiry; put renewals on the calendar. Record the date of the review.Example
Shell kubectl get clusterrolebindings -o wide kubectl get rolebindings -A -o wideAPI audit logs are enabled, retained and protected from general accessShould
Why it matters and how to check
After a suspected compromise, the audit log is how you learn who read which Secret or created which Pod. The security checklist asks that audit logs, if enabled, are protected from general access, since they reveal a lot about the cluster.
To verify: confirm audit logging is turned on (a provider setting on managed clusters, an audit policy file on self-managed ones), that logs are shipped to your central logging system with a defined retention, and that only the security and platform teams can read them. Look up one recent
kubectlaction of your own in the logs.