Kubernetes security
The 4Cs of cloud native security, the API request path (authentication, authorization, admission), RBAC and ServiceAccounts, Pod Security Standards, Secrets, and image and supply chain security for KCNA.
Exam tasks: 2.2 (security)
The decision: for a given risk (a stolen kubeconfig, an over-privileged Pod, a leaked password, a vulnerable image), which layer of the stack and which Kubernetes control addresses it?
The 4Cs
- Cloud (or data center): IAM for the provider account, firewalling the control plane, hardening nodes.
- Cluster: who can call the API, what they may do, what Pods may run, how etcd is protected.
- Container: trusted images, non-root users, no privileged mode, minimal capabilities.
- Code: your application and its libraries.
- Each layer depends on the one outside it. Perfect code doesn't help if anyone can reach an unprotected API server.
The API request path
Every request to the API server, from kubectl or a Pod, passes three gates in order:
| Gate | Question | Mechanisms |
|---|---|---|
| Authentication | Who is calling? | X.509 client certificates, bearer tokens, OIDC (corporate identity providers), ServiceAccount tokens |
| Authorization | Is this identity allowed this verb on this resource? | RBAC (the standard), Node authorizer (for kubelets), Webhook, ABAC (rarely used) |
| Admission | Is this object acceptable, and should it be changed? | Built-in admission plugins, Pod Security Admission, ValidatingAdmissionPolicy (CEL), admission webhooks such as OPA Gatekeeper or Kyverno |
- Kubernetes has no User object. Human users exist only as names in certificates or tokens from an external identity source. ServiceAccounts are the in-cluster identities for workloads.
- Admission runs mutating controllers first (they can change the object, for example add defaults), then validating ones (accept or reject).
Exam signal
"Reject Pods that use images from unapproved registries" or "require a team label on every Deployment" is an admission job (a policy engine such as Gatekeeper or Kyverno, or a ValidatingAdmissionPolicy). "Let this group read Pods in one namespace" is authorization (RBAC). "Log in with the company's SSO" is authentication (OIDC).
RBAC and ServiceAccounts
- A Role lists allowed verbs (
get,list,watch,create,update,delete...) on resources in one namespace. A ClusterRole does the same cluster-wide or for cluster-scoped resources such as nodes. - A RoleBinding or ClusterRoleBinding grants a role to subjects: users, groups or ServiceAccounts.
- RBAC is allow-only. There are no deny rules; anything not granted is refused.
- Every namespace has a
defaultServiceAccount, and Pods use it unless you setserviceAccountName. - Pods get a short-lived, automatically rotated projected token for their ServiceAccount. Set
automountServiceAccountToken: falsefor Pods that never call the API. - Check permissions with
kubectl auth can-i list secrets --as=system:serviceaccount:billing:invoice-worker -n billing.
Legacy: use bound, projected ServiceAccount tokens instead
Older clusters stored a non-expiring token for every ServiceAccount in an auto-created Secret. Since v1.24 these Secrets are no longer generated; Pods get time-bound tokens through the TokenRequest API instead.
Bind cluster-admin to fix a permission error
When a Pod gets 403 Forbidden, the tempting answer is a ClusterRoleBinding to cluster-admin. The exam wants
least privilege: a Role with just the needed verbs and resources, bound in the right namespace to the Pod's
own ServiceAccount.
Pod Security Standards
The Pod Security Standards define three profiles, and the built-in Pod Security Admission controller applies them per namespace through labels.
| Profile | What it allows | Use for |
|---|---|---|
| Privileged | Everything | System and infrastructure components (CNI, storage drivers) |
| Baseline | Blocks known privilege escalations: privileged containers, host namespaces, hostPath, most added capabilities | Most applications, as a default |
| Restricted | Baseline plus hardening: must run as non-root, drop all capabilities, no privilege escalation, a seccomp profile | Security-sensitive workloads |
Each namespace can set a profile per mode: enforce (reject violating Pods), audit (record in the audit
log) and warn (show a warning to the user).
apiVersion: v1
kind: Namespace
metadata:
name: reports
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/warn: restricted- Inside the Pod, the securityContext sets the actual values:
runAsNonRoot,readOnlyRootFilesystem,allowPrivilegeEscalation: false,capabilities.drop: ["ALL"],seccompProfile.
Legacy: use Pod Security Admission instead
PodSecurityPolicy was deprecated in v1.21 and removed in v1.25. Answers that create a PodSecurityPolicy are wrong for current Kubernetes.
Secrets
- A Secret holds small sensitive values (passwords, tokens, TLS keys) and is mounted as files or exposed as environment variables.
- Values are base64-encoded, not encrypted. Anyone who can read the Secret object can decode it.
- Protect them by:
- enabling encryption at rest in etcd (an
EncryptionConfigurationon the API server, ideally with a KMS provider), - limiting
getandliston Secrets with RBAC, - or keeping values in an external store (HashiCorp Vault, a cloud secret manager) synced by the External Secrets Operator or the Secrets Store CSI driver.
- enabling encryption at rest in etcd (an
- Mark Secrets
immutable: truewhen they don't change, to prevent accidental edits.
base64 is encryption
"The Secret is safe because it's encoded" is wrong. Encoding is reversible by anyone. Real protection is encryption at rest plus tight RBAC, or an external secrets manager.
Images and supply chain
| Practice | What it means | Tools |
|---|---|---|
| Minimal images | Distroless, Alpine or scratch base images: fewer packages, fewer CVEs | Multi-stage builds |
| Scanning | Check images for known vulnerabilities in CI and in the registry | Trivy, Grype, registry scanners |
| Signing and verification | Sign images at build, verify signatures at admission | Sigstore cosign, Notary Project |
| SBOM | A software bill of materials lists every component in an image | Syft, SPDX, CycloneDX |
| Pin by digest | Reference image@sha256:... instead of a mutable tag like latest | Admission policies |
| Trusted registries | Allow only approved registries | Gatekeeper or Kyverno policies |
Protecting the cluster
- API server: TLS everywhere, no anonymous access, RBAC, audit logging, private endpoint where possible.
- etcd: holds all cluster state including Secrets. Restrict access to the API server only, use TLS, encrypt at rest, protect backups.
- Nodes: patched OS, minimal packages, kubelet authentication and authorization enabled.
- Runtime detection: Falco (CNCF graduated) watches system calls and alerts on suspicious behaviour, such as a shell started inside a container.
- Network: default-deny NetworkPolicies, and mTLS from a service mesh for encryption in transit.
For RBAC hands-on, see the CKA page RBAC.
Scenarios
Pod Security Admission is built in, and the Baseline profile blocks privileged containers and host namespaces while allowing typical apps. PodSecurityPolicy was removed in v1.25. NetworkPolicies control traffic between Pods and can't stop a Pod from using the host network. ServiceAccounts control API access, not Pod privileges.
Secrets are base64-encoded, which anyone can decode, and are stored in etcd. Encryption at rest protects the etcd copy, and RBAC limits who can read them through the API. The cluster CA signs certificates and doesn't encrypt Secrets. Mounting as files is a good habit but doesn't stop someone with API read access.
The API server must know who is calling before it can check permissions, so authentication comes first, then authorization (RBAC), then admission. The scheduler only acts later on the Pods that the Deployment controller creates.
Further reading
Service mesh
What a service mesh adds to Kubernetes networking, data plane vs control plane, sidecar vs Istio ambient mode, mTLS and workload identity, traffic management, Istio and Linkerd, and the Gateway API GAMMA initiative.
Troubleshooting Pods
Pod phases, container states and their reasons, events, kubectl describe and logs, and how to map Pending, ImagePullBackOff, CrashLoopBackOff and OOMKilled to their usual causes for KCNA.