Kubernetes Security Interview Questions
Reviewed by Mark Dickie · Last updated
Kubernetes security is the set of controls and practices that protect a cluster's workloads, data, and network surface from unauthorized access and exploitation. For interviews, you should know RBAC object relationships, how NetworkPolicy enforcement depends on the CNI plugin, the difference between Secrets and ConfigMaps at rest, and the Pod Security Standards that replaced Pod Security Policies in Kubernetes 1.25.
Expect questions that test whether you can wire the pieces together: granting a ServiceAccount the narrowest set of permissions, restricting pod-to-pod traffic with namespace-scoped policies, and explaining why a default-deny network stance still needs the right admission controller to be effective.
What are the core security domains in a Kubernetes interview?
Most security questions cluster around five areas. Here is how they map to the objects and features an interviewer will ask you to name:
| Domain | Key objects / features | What an interviewer probes |
|---|---|---|
| Authorization | Role, ClusterRole, RoleBinding, ClusterRoleBinding | Can you scope permissions to a single namespace and avoid cluster-admin? |
| Network isolation | NetworkPolicy, CNI plugin enforcement | Do you know which CNIs enforce policy and which silently ignore it? |
| Secret management | Secret, encryption-at-rest config, external KMS | How are Secrets stored on etcd and what changes when encryption-at-rest is on? |
| Pod hardening | SecurityContext, Pod Security Admission (PSA) | Can you set runAsNonRoot, readOnlyRootFilesystem, and drop capabilities? |
| Admission control | Admission webhooks, OPA Gatekeeper, Kyverno | What stops a pod from running privileged at create time? |
How should I think about RBAC for the interview?
- Identify the actor: a user, a group, or a ServiceAccount tied to a pod.
- Choose the scope: a Role is namespace-scoped; a ClusterRole spans the whole cluster or can be referenced from a RoleBinding for cross-namespace reuse.
- Bind with the narrowest role: use a RoleBinding for namespace-scoped access, a ClusterRoleBinding only when cluster-wide access is unavoidable.
- Follow least privilege: verbs like
getandlistare safer than*, and resources should be named explicitly rather than left blank.
What replaced Pod Security Policies and why does it matter?
Pod Security Policies were removed in Kubernetes 1.25 and replaced by Pod Security Admission, a built-in controller that applies Pod Security Standards at the namespace label level. Three modes — enforce, audit, and warn — let you block, log, or surface violations for the privileged, baseline, and restricted profiles. An interviewer will often ask you to label a namespace for the restricted profile and explain what that blocks: privileged pods, hostPath volumes, host networking, and containers that run as root without an explicit UID.
Key facts
- Tarmac's Kubernetes interview questions cover 14 questions at difficulty 2–4 of 5.
- Tarmac tracked 3,264 job postings asking for Kubernetes in August 2026.
- Roles asking for Kubernetes advertise a median base salary of US$170,000, across 666 job postings as of August 2026.
- Tarmac last reviewed these Kubernetes interview questions on 31 August 2026.
At a glance
| Questions | 14 |
|---|---|
| Difficulty | 2–4 of 5 |
| Formats | Multiple choice, Flashcard, Multiple answer, True / false, Find the bug, Short answer, Ordering |
What you'll review
- service accounts
- security context
- pod security
Practice questions
Try one before you open the answer. Pick an option and press Check; it's marked on the spot.
A ServiceAccount sets automountServiceAccountToken: false, but a Pod that uses that ServiceAccount sets spec.automountServiceAccountToken: true. Is the token mounted into the Pod's containers?#
Options
Show answer
The Pod-level automountServiceAccountToken setting overrides the ServiceAccount-level one whenever both specify a value, so the token gets mounted here despite the ServiceAccount saying false. Kubernetes resolves the conflict in favor of the more specific, Pod-scoped field — the ServiceAccount's setting only applies as a default when the Pod itself leaves the field unset.
automountServiceAccountToken can be set on the ServiceAccount object (a default for every Pod using it) and independently on the Pod spec. When both specify a value, the Pod-level field wins — it's the more specific setting. So here the token is mounted, despite the ServiceAccount saying false. This lets you set a safe org-wide default on the ServiceAccount while still opting a specific Pod in or out.
What ServiceAccount does a Pod use if spec.serviceAccountName is omitted, and how do you make every Pod using an SA pull from a private registry without editing each Pod?#
Show answer
It uses the default ServiceAccount in its namespace — created automatically, with no permissions beyond default API discovery. To supply registry credentials to every Pod that uses a given ServiceAccount, attach imagePullSecrets to the ServiceAccount object itself; Kubernetes injects those secrets into any Pod referencing that SA, so you don't repeat imagePullSecrets on every Pod spec.
Two related facts trip people up: the default SA is real and auto-created (not 'no ServiceAccount'), and imagePullSecrets can live on the ServiceAccount as a one-time setup rather than being copy-pasted onto every workload that needs the same private registry.
What are the three seccompProfile.type values in a Kubernetes SecurityContext, and what does each do?#
Show answer
RuntimeDefault applies the container runtime's built-in filtered syscall allow-list — the safe default. Unconfined disables seccomp filtering entirely, so the container can make any syscall the kernel permits — the least safe option. Localhost loads a custom seccomp JSON profile from a file on the node, referenced via localhostProfile, for workloads needing a syscall set the runtime default doesn't cover. Pod Security Admission's restricted level requires RuntimeDefault or Localhost — Unconfined (or no profile set) is rejected.
Unconfined sounds like it might mean 'default confinement' but means the opposite — no filtering at all. Knowing restricted rejects it (and rejects an unset profile) explains a common PSA admission failure on images with no seccompProfile configured.
You want a RoleBinding to grant permissions to a specific workload identity — the report-generator ServiceAccount in the batch namespace — rather than to a human user. Which subjects entry is correct?#
Options
Show answer
The correct subject block is kind: ServiceAccount with separate name: report-generator and namespace: batch fields — a RoleBinding references a ServiceAccount by its own kind, not by embedding the identity into a User or Group name string. Using kind: User with the bare name, or folding the namespace into name, never matches the ServiceAccount's actual authenticated identity.
A ServiceAccount subject needs its own kind: ServiceAccount plus separate name and namespace fields — that's how the binding resolves to the exact identity. kind: User with a bare report-generator never matches, because a ServiceAccount's actual authenticated username is the full system:serviceaccount:<namespace>:<name> string, not the bare name. kind: Group with batch:report-generator is malformed too — the real groups a ServiceAccount belongs to are system:serviceaccounts and system:serviceaccounts:<namespace>, not a <namespace>:<name> pair. And cramming the namespace into name (batch/report-generator) doesn't work either — namespace is always its own field on a ServiceAccount subject.
A Pod sets spec.securityContext.runAsUser: 1000 for all its containers. One container additionally sets its own securityContext.runAsUser: 2000. Which UID does that container run as?#
Options
Show answer
The container with its own runAsUser: 2000 runs as UID 2000, because a container-level securityContext field overrides the Pod-level value for the same field. Pod-level settings act as defaults inherited by every container, but any container can override individual fields for itself — nothing about the mismatch causes a conflict or an admission failure.
Pod-level securityContext fields act as defaults inherited by every container; a container's own securityContext overrides individual fields for itself. So this container runs as 2000 while any sibling container without its own runAsUser still runs as 1000. There's no admission-time conflict check for this — it's ordinary override behavior, the same shape as CSS specificity or config layering, not a validation error.
Select all statements that are true about container-level securityContext hardening.#
Options
Pick every one that applies.
Show answer
Two of these are true: dropping all capabilities and adding back only what's needed follows least privilege, and readOnlyRootFilesystem: true mounts the root filesystem read-only, which can break an app that writes outside a mounted volume. seccompProfile.type: Unconfined is the opposite of the runtime's filtered default — it disables syscall filtering entirely — and capability drops take effect regardless of the privileged setting.
Dropping all capabilities and adding back only what's required (capabilities.drop: ["ALL"] followed by adding back only what's needed) and locking the root filesystem read-only (readOnlyRootFilesystem: true) are genuine hardening moves — the second one is also a common source of surprise crashes when an app writes logs, temp files, or a cache to an unmounted path under /. Unconfined is the opposite of the filtered default — it turns syscall filtering off entirely, RuntimeDefault is the one that applies the runtime's filtered set. And capability drops take effect regardless of privileged; in fact privileged: true grants the full capability set back and overrides drops anyway, so the two options are not linked the way the claim that dropping capabilities has no effect unless the container also sets privileged: true claims.
Pod Security Admission (PSA) replaces RBAC as the mechanism for controlling which users can create Pods in a namespace.#
Options
Show answer
False. Pod Security Admission replaced PodSecurityPolicy (removed in Kubernetes 1.25), not RBAC. RBAC governs which users or ServiceAccounts can call which API verbs and resources, while PSA governs what security posture a Pod's spec must have to be admitted into a namespace — a user with full RBAC rights to create Pods can still be blocked by PSA if the Pod doesn't meet the namespace's level. Both mechanisms remain necessary and operate independently.
False. PSA replaced PodSecurityPolicy (removed in Kubernetes 1.25) — it did not replace RBAC. RBAC governs which identities can call which API verbs and resources (can this user or ServiceAccount create a Pod at all?); PSA governs what security posture a Pod's spec must have to be admitted into a namespace, checked regardless of who created it. A user with full RBAC rights to create Pods in a namespace can still be blocked by PSA if the Pod's securityContext doesn't meet the namespace's configured level. Both mechanisms remain necessary and operate independently — treating one as a substitute for the other leaves a real gap.
The payments namespace is labeled pod-security.kubernetes.io/enforce: restricted. Applying this Deployment fails with a PodSecurity admission error. Which part of the Pod template is the problem?#
apiVersion: apps/v1
kind: Deployment
metadata:
name: worker
namespace: payments
spec:
replicas: 2
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
spec:
containers:
- name: worker
image: example/worker:3.1Options
Show answer
The container has no securityContext at all, so it fails restricted's requirements — runAsNonRoot: true, allowPrivilegeEscalation: false, dropped capabilities, and a RuntimeDefault/Localhost seccomp profile all default to unset or permissive
restricted is the strictest Pod Security Standard, and it's checked against the Pod template a Deployment produces. With no securityContext set anywhere, every restricted-only requirement fails at once: runAsNonRoot is unset (defaults to allowing root), allowPrivilegeEscalation is unset (defaults to true), no capabilities are dropped, and no seccomp profile is set. Any one of those alone would be enough to reject the Pod. replicas and namespace placement have nothing to do with PSA, and Deployments are a completely normal, supported workload type under Pod Security Admission — the check runs against the Pods they create.
How do you configure Pod Security Admission for a namespace, and what's the difference between its enforce, audit, and warn modes?#
Show answer
PSA is configured with labels on the Namespace object, not a separate policy resource — for example pod-security.kubernetes.io/enforce: restricted, optionally pinned to a specific standard version with pod-security.kubernetes.io/enforce-version: latest (or an explicit version). Each of the three modes can carry a different level and acts independently: enforce actually blocks Pod creation when a Pod violates the level, returning a Forbidden error; audit allows the Pod through but adds a violation annotation to the audit log; warn allows it through but returns a client-visible warning, e.g. shown by kubectl. A common rollout pattern is setting warn/audit at a stricter level first to see what would break, then flipping to enforce once workloads comply.
PSA has no separate policy CRD — it's entirely namespace labels. The three modes decouple 'what would this reject' from 'what does this actually reject,' which is what makes the audit/warn-first-then-enforce rollout pattern possible without breaking existing workloads blind.
On a current Kubernetes cluster, when a Pod mounts its ServiceAccount token at /var/run/secrets/kubernetes.io/serviceaccount/token, what kind of token is it by default?#
Options
Show answer
A mounted ServiceAccount token on a current cluster is a short-lived, audience-bound token obtained via the TokenRequest API and delivered through a projected volume, which the kubelet automatically rotates before it expires. Kubernetes moved off long-lived static Secret-backed tokens starting in version 1.22, and stopped auto-creating those legacy Secrets by default a few versions later.
Since 1.22, the kubelet obtains this token through the TokenRequest API and mounts it via a projected volume — it's short-lived, scoped to specific audiences, and rotated automatically before it expires. The older behavior, an auto-created long-lived Secret holding a static token, is what this replaced; Kubernetes stopped auto-generating those legacy Secret tokens by default starting around 1.24, reaching GA in 1.27. Treating the mounted token as a permanent credential is exactly the assumption bound tokens were introduced to break — a leaked bound token has a short shelf life.
A container spec sets capabilities.drop: ["ALL"], allowPrivilegeEscalation: false, and seccompProfile.type: RuntimeDefault, but does not set runAsNonRoot, so its image runs as UID 0. Under which Pod Security Admission level does this Pod get admitted?#
Options
Show answer
baseline admits this Pod, but restricted rejects it, because restricted additionally requires runAsNonRoot: true — a check baseline doesn't perform. The Pod already satisfies both levels' capability and seccomp rules by dropping all capabilities and using RuntimeDefault; running as root is the one gap only restricted catches.
This Pod already clears every baseline and restricted rule around capabilities and seccomp: dropping all capabilities and adding none back satisfies both levels' capability rules, and RuntimeDefault satisfies both levels' seccomp requirement. The one rule that's restricted-only is runAsNonRoot: true (with a non-zero runAsUser) — baseline never checks it. So baseline admits this Pod as-is, and restricted is the level that catches the root UID and rejects it. Conflating 'dropped all capabilities' with 'runs as non-root' is a common gap in an otherwise well-hardened spec.
Setting securityContext.allowPrivilegeEscalation: false on a container is enough to prevent privilege escalation even if that same container also sets privileged: true.#
Options
Show answer
False. allowPrivilegeEscalation: false is overridden the moment the same container sets privileged: true (or holds CAP_SYS_ADMIN) — Kubernetes forces privilege escalation back on in that case, and privileged: true already grants far broader host access than escalation alone. The two settings must agree; privileged: true always wins.
False. allowPrivilegeEscalation: false is overridden the instant the same container sets privileged: true (or holds CAP_SYS_ADMIN) — Kubernetes forces privilege escalation back on in that case, because a privileged container already has broader host access than escalation alone would add. The two settings must agree to have any effect; privileged: true always wins over an explicit allowPrivilegeEscalation: false, so pairing them gives you privileged access with a false sense of a mitigating flag.
This Pod is meant to run fully non-root, but files it creates on its mounted volume are still group-owned by GID 0 (root). What's missing?#
securityContext:
runAsUser: 1000
runAsNonRoot: true
containers:
- name: app
image: example/app:1.0Options
Show answer
runAsGroup is not set, so the primary group defaults to GID 0 (root) even though runAsUser is non-root — set runAsGroup explicitly (e.g. 1000)
runAsUser only fixes the process's UID. If runAsGroup is left unset, the primary GID the process runs with defaults to GID 0 — root's group — regardless of how non-root the UID is. That's exactly why new files show up group-owned by root even though runAsNonRoot: true is satisfied (it only checks the UID, not the group). The fix is to set runAsGroup explicitly alongside runAsUser. runAsNonRoot isn't redundant — it's a validation gate the kubelet enforces, refusing to start the container if the resolved UID is 0 — and fsGroup (a Pod-level, volume-ownership setting) has no such equality requirement with runAsUser.
A Pod calls the Kubernetes API using its ServiceAccount identity. Order the steps from container start to the API server serving (or rejecting) the request.#
Put these in order
Show answer
A Pod's ServiceAccount token authenticates to the API server in this order:
- The kubelet mounts the ServiceAccount's token into the Pod via a projected volume at container start
- The application reads the token file and sends it as an
Authorization: Bearer <token>header - The API server authenticates the token, resolving the identity
system:serviceaccount:<namespace>:<name> - The API server checks whether that identity is authorized for the requested verb/resource
- If authorized, the API server processes the request; otherwise it returns 403 Forbidden
Each step depends on the one before it — a request never reaches authorization without first passing authentication.
Every step depends on the one before it: there's no token to send until the kubelet has mounted it, no identity to authorize until authentication has resolved one, and no processing until authorization passes. This is also why a Pod with automountServiceAccountToken: false can't call the API at all — step one never happens, so there's nothing to attach to the request in step two.
Related interview questions
Job market
See kubernetes salaries and hiring demand from live job postings.
Practise these until they stick
That's every question we hold on this topic, and the page marks what you pick. What it can't do is remember. A free account keeps every answer, and what you miss comes back until it's right: after a day, then at longer gaps.
Free · the whole bank · 100 marked answers per 30 days · written feedback on the paid plan