All resources
Kubernetes · Interview prep

Kubernetes interview questions

Kubernetes interview questions from fresher to 6+ years — pods and services, workloads and scheduling, networking, storage, RBAC, and control-plane architecture, each answer tagged by experience level.

ExperienceAll levelsFresherJuniorMidSenior

Fresher 0–1y · Junior 1–3y · Mid 3–6y · Senior 6+y — every answer is tagged so you can prep for your level.

Fundamentals
What is a Pod?Fresher

The smallest deployable unit — one or more containers sharing a network namespace (same IP and port space) and storage volumes, always scheduled together onto one node.

Create a Pod
# one-off (debugging)
kubectl run web --image=nginx --restart=Never

# real workloads use a manifest
apiVersion: v1
kind: Pod
metadata: { name: web }
spec:
  containers:
    - name: web
      image: nginx:1.27
Deployment vs StatefulSet vs DaemonSet?Fresher

A Deployment runs interchangeable stateless replicas; a StatefulSet gives each replica a stable identity, ordered rollout, and its own PVC (databases); a DaemonSet runs one Pod per node (agents, log shippers).

When to use which
kind: Deployment   # stateless web/api — N identical pods
kind: StatefulSet  # db-0, db-1 … stable name + own volume
kind: DaemonSet    # exactly one pod per node (agent, CNI)
What does a Service do?Fresher

It gives a stable virtual IP and DNS name in front of a changing set of Pods selected by labels and load-balances to the ready ones. ClusterIP is internal, NodePort/LoadBalancer expose externally.

Expose a Deployment
kubectl expose deploy web --port=80 --target-port=8080
# stable DNS: web.default.svc.cluster.local
ConfigMap vs Secret?Fresher

Both inject configuration as env vars or files. Secrets are for sensitive data — base64-encoded at rest (enable etcd encryption for real protection) and guarded with tighter RBAC.

Create config + secret
kubectl create configmap app --from-literal=LOG_LEVEL=info
kubectl create secret generic db --from-literal=PASSWORD=s3cr3t
# base64 is NOT encryption — enable etcd encryption at rest
How do labels and selectors work?Junior

Labels are key/value tags on objects; selectors query them. Services, Deployments, and NetworkPolicies all target Pods by label selector rather than by name, which is what makes the model declarative.

Select by label
kubectl get pods -l app=web,tier=frontend
kubectl label pod web release=canary
ReplicaSet vs Deployment — who owns what?Junior

A ReplicaSet keeps N identical Pods running; a Deployment manages ReplicaSets to give you versioned rollouts and rollback. You almost always create a Deployment, never a bare ReplicaSet.

DeploymentReplicaSetPods

Each rollout creates a new ReplicaSet; the old one is kept (scaled to 0) so undo is instant.

What is a namespace and when do you use one?Junior

A virtual cluster scope for names, quotas, and RBAC. Use namespaces to separate teams/environments and apply ResourceQuota and LimitRange — but they are not a hard security boundary on their own.

Namespaces
kubectl create namespace team-a
kubectl -n team-a get pods
How do you inspect why a resource is unhealthy?Fresher

Work from status to detail to logs: get for a summary, describe for events and conditions, and logs (with --previous) for the app output before a crash.

The three commands you use daily
kubectl get pod web -o wide
kubectl describe pod web        # events are at the bottom
kubectl logs web -c app --previous
Workloads & scheduling
How does a rolling update work?Junior

The Deployment creates a new ReplicaSet and shifts Pods gradually, honoring maxSurge/maxUnavailable so the app stays available. Readiness probes gate traffic to new Pods; `kubectl rollout undo` reverts.

New ReplicaSetSurge extra PodsReadiness gateScale down oldDone

maxSurge/maxUnavailable control how aggressive the swap is.

Rollout + rollback
kubectl set image deploy/web app=web:v2
kubectl rollout status deploy/web
kubectl rollout undo deploy/web     # revert to previous ReplicaSet
Liveness vs readiness vs startup probe?Junior

Liveness restarts a wedged container; readiness removes a Pod from Service endpoints until it can serve (without killing it); startup protects slow-booting apps from premature liveness failures.

Probe config
readinessProbe:              # gate traffic in/out
  httpGet: { path: /healthz, port: 8080 }
  periodSeconds: 5
livenessProbe:               # restart if wedged
  httpGet: { path: /livez, port: 8080 }
  failureThreshold: 3
startupProbe:                # protect slow boots
  httpGet: { path: /healthz, port: 8080 }
  failureThreshold: 30
Requests vs limits?Junior

Requests are what the scheduler reserves and uses for placement; limits cap actual usage. Exceeding a memory limit gets the container OOM-killed; CPU over the limit is throttled, not killed.

Requests also set the QoS class — Guaranteed when requests equal limits, which is the last to be evicted under pressure. Limits are enforced by cgroups: CPU throttles, memory over-limit triggers an OOM kill (exit 137).

Set requests/limits
resources:
  requests: { cpu: "100m", memory: "128Mi" }   # scheduling
  limits:   { cpu: "500m", memory: "256Mi" }   # enforcement
How do taints, tolerations, and affinity steer scheduling?Mid

Taints repel Pods from nodes unless the Pod has a matching toleration; node/pod affinity and anti-affinity attract or separate Pods; topologySpreadConstraints balance replicas across zones/nodes.

A taint is a property of the node that repels; a toleration is the Pod opting in. Affinity/anti-affinity expresses soft (preferred) or hard (required) placement, and topology spread keeps replicas balanced across zones so one failure domain cannot take you down.

Taint a node + tolerate it
kubectl taint nodes gpu-1 gpu=true:NoSchedule

tolerations:
  - key: gpu
    operator: Equal
    value: "true"
    effect: NoSchedule
How does the HPA decide to scale?Mid

It samples a metric (CPU, memory, or custom/external via the metrics API) and adjusts replica count toward a target utilization, within min/max and a stabilization window to avoid flapping. VPA instead right-sizes requests.

Every ~15s it reads the metric and computes desiredReplicas = ceil(currentReplicas × currentValue / targetValue), clamped to min/max with a stabilization window so it does not thrash. It needs the metrics-server (or an adapter for custom/external metrics).

metrics-serverHPA reads utilizationCompute desired replicasScale the Deployment
Autoscale on CPU
kubectl autoscale deploy/web --cpu-percent=70 --min=3 --max=20
kubectl get hpa web --watch
What is a PodDisruptionBudget for?Mid

It caps how many replicas can be voluntarily evicted at once (drains, upgrades), so a rolling node operation cannot take an app below its minimum available — it does not protect against involuntary disruption like a node crash.

A drain (node upgrade, kubectl drain) is a voluntary disruption and must respect the PDB; a kernel panic or preemption is involuntary and ignores it. Set minAvailable/maxUnavailable so an upgrade cannot take an app below quorum.

Guarantee 2 stay up
apiVersion: policy/v1
kind: PodDisruptionBudget
spec:
  minAvailable: 2
  selector: { matchLabels: { app: web } }
Job vs CronJob?Mid

A Job runs one or more Pods to successful completion (batch work, DB migrations); a CronJob creates Jobs on a schedule. Bound them with backoffLimit and activeDeadlineSeconds so a failing Job does not loop forever.

One-off + scheduled
kubectl create job db-migrate --image=migrate:1
kubectl create cronjob nightly --image=report:1 --schedule="0 2 * * *"
How does the scheduler place a Pod?Senior

In two phases — filtering, then scoring — then it binds the Pod to the winning node, which the kubelet then starts.

Filtering drops infeasible nodes (resources do not fit, taints not tolerated, node/affinity selectors, volume zone). Scoring ranks the survivors (least-allocated, affinity, topology spread) and the highest score wins. Scheduling only writes a binding — the kubelet on that node pulls and runs the containers.

Pending PodFilter feasible nodesScore & pick bestBind to nodekubelet runs it
Networking & storage
How does a Service actually route to Pods?Mid

The endpoints controller tracks ready Pods behind the selector into EndpointSlices; kube-proxy (iptables/IPVS) or a CNI programs the node to DNAT the Service ClusterIP to a backend Pod IP.

The Service is only a stable VIP; the data path is programmed on every node by kube-proxy (iptables/IPVS) or by eBPF (Cilium). EndpointSlices list only Ready Pods, so an unready Pod receives no traffic.

Service ClusterIPEndpointSlice (Ready pods)kube-proxy / eBPFDNAT to a Pod IP
See the real backends
kubectl get endpointslices -l kubernetes.io/service-name=web
kubectl describe svc web | grep -i endpoints
Ingress vs Gateway API?Mid

Ingress is the older L7 HTTP router with controller-specific annotations. Gateway API is the successor — role-oriented (GatewayClass/Gateway/HTTPRoute), portable, and supports richer routing and non-HTTP protocols.

Ingress crammed everything into one object with vendor-specific annotations. Gateway API splits roles — infra owns GatewayClass/Gateway, app teams own HTTPRoute — and natively supports header/weight routing and TCP/gRPC.

Weighted (canary) route
# HTTPRoute — 90/10 canary
spec:
  rules:
    - backendRefs:
        - { name: web-v1, port: 80, weight: 90 }
        - { name: web-v2, port: 80, weight: 10 }
What is a NetworkPolicy and its default behavior?Mid

A namespaced rule set restricting Pod traffic by label selector. Pods are non-isolated until a policy selects them; then only explicitly allowed ingress/egress passes — and it only works if the CNI enforces policies.

Policies are additive and become deny-by-default only for Pods they select. The usual pattern is a default-deny-ingress policy per namespace, then explicit allow rules — and it does nothing unless your CNI enforces policy.

Default-deny ingress
kind: NetworkPolicy
spec:
  podSelector: {}            # every pod in the namespace
  policyTypes: [Ingress]     # …with no allow rule = deny all in
Explain PV, PVC, and StorageClass.Mid

A PVC is a request for storage; a PV is the actual volume. A StorageClass enables dynamic provisioning so a PVC creates a PV on demand via a CSI driver, with a reclaim policy (Delete/Retain) controlling cleanup.

A PVC binds to a PV; with a StorageClass the CSI provisioner creates the PV on demand. volumeBindingMode: WaitForFirstConsumer delays that until a Pod is scheduled, so the volume lands in the same zone as the Pod.

PVC (request)StorageClass + CSIPV provisionedMounted into Pod
Inspect storage
kubectl get pvc,pv
kubectl get storageclass
ClusterIP vs NodePort vs LoadBalancer vs ExternalName?Junior

ClusterIP is internal-only (the default); NodePort opens the same port on every node; LoadBalancer provisions a cloud LB in front of that; ExternalName is just a DNS CNAME to a host outside the cluster.

Pick a type
kubectl expose deploy web --type=ClusterIP --port=80      # internal
kubectl expose deploy web --type=LoadBalancer --port=80   # public
How does DNS work inside the cluster?Senior

CoreDNS gives every Service an A record like `svc.ns.svc.cluster.local`; Pods resolve short names via the search domains in /etc/resolv.conf. Headless Services return Pod IPs directly for StatefulSet discovery.

CoreDNS runs as a Deployment behind a Service. Pod resolv.conf sets ndots:5 and search domains, which is why short names try namespace-scoped suffixes first (and can cause surprise extra lookups). Headless Services (clusterIP: None) return each Pod IP for StatefulSet discovery.

Resolve a Service
nslookup web.default.svc.cluster.local
kubectl -n kube-system get pods -l k8s-app=kube-dns
Security
How does RBAC work?Mid

Roles/ClusterRoles list allowed verbs on resources; RoleBindings/ClusterRoleBindings grant them to users, groups, or ServiceAccounts. Access is deny-by-default and additive — there are no deny rules.

A RoleBinding ties a subject (user, group, or ServiceAccount) to a Role (namespaced) or ClusterRole (cluster-wide). It is purely additive and deny-by-default — there are no deny rules — so you scope tightly and verify with kubectl auth can-i.

SubjectRoleBindingRole (verbs × resources)Allow (else denied)
Grant + test least privilege
kubectl create role dev --verb=get,list --resource=pods
kubectl create rolebinding dev --role=dev --serviceaccount=team-a:builder
kubectl auth can-i list pods --as=system:serviceaccount:team-a:builder
What does Pod Security Admission enforce?Mid

Built-in admission applying the Pod Security Standards (privileged/baseline/restricted) per namespace via labels — blocking or warning on privileged containers, host namespaces, and dangerous capabilities.

Three standards (privileged / baseline / restricted) × three modes (enforce / audit / warn), set by namespace label. Roll out with warn+audit first to surface violations, then flip to enforce.

Enforce restricted
kubectl label ns team-a pod-security.kubernetes.io/enforce=restricted
kubectl label ns team-a pod-security.kubernetes.io/warn=restricted
How do you protect Secrets at rest?Mid

Base64 is encoding, not encryption. Turn on etcd encryption-at-rest (ideally KMS-backed), tighten RBAC on secrets, and push high-value secrets to an external manager (Vault / External Secrets Operator).

Without an EncryptionConfiguration, anyone who reads the etcd data or a backup reads every secret in plaintext. A KMS provider keeps the key outside the cluster, so an etcd snapshot alone is useless to an attacker.

apiserver EncryptionConfiguration
resources:
  - resources: ["secrets"]
    providers:
      - kms: { name: cloudkms, endpoint: unix:///tmp/kms.sock }
      - identity: {}      # reads old plaintext during migration
How should workloads authenticate to the API or cloud?Senior

Use a dedicated ServiceAccount with a short-lived projected token (bound to the Pod), and federate to cloud IAM via OIDC/workload identity instead of long-lived static keys mounted as Secrets.

Mount a projected ServiceAccount token — audience-bound and short-lived — and exchange it with the cloud IdP for temporary credentials (IRSA on EKS, Workload Identity on GKE). No static cloud key ever lives in a Secret.

Pod SA tokenOIDC federationCloud STSShort-lived cloud creds
Name key securityContext hardening settings.Senior

runAsNonRoot, a non-zero runAsUser, readOnlyRootFilesystem, allowPrivilegeEscalation:false, drop ALL capabilities (add back only what is needed), and a seccompProfile of RuntimeDefault.

Hardened securityContext
securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities: { drop: ["ALL"] }
  seccompProfile: { type: RuntimeDefault }
How do admission controllers extend cluster policy?Senior

Validating/Mutating webhooks intercept API requests after authn/authz — mutating can inject sidecars or defaults, validating can reject non-compliant objects. Gatekeeper and Kyverno build policy engines on this.

A request flows through mutating webhooks (inject sidecars, defaults) then validating webhooks (reject non-compliant) before it is written. Kyverno/Gatekeeper plug in here — but a broken webhook can block the whole API, so set failurePolicy, timeouts, and namespace exclusions carefully.

API requestAuthn / AuthzMutating webhooksValidating webhooksPersisted to etcd
Architecture & troubleshooting
What are the control-plane components?Mid

kube-apiserver (the front door and only thing that talks to etcd), etcd (the store), kube-scheduler (placement), kube-controller-manager (reconcile loops), and cloud-controller-manager; nodes run kubelet and kube-proxy.

Only the apiserver talks to etcd; everything else watches the apiserver. The scheduler and controllers are level-driven reconcilers comparing desired vs actual — which is exactly why the system self-heals.

clients / kubectlkube-apiserveretcdcontrollers + schedulerkubelet on nodes
Why does etcd matter and how do you protect it?Senior

etcd is the single source of truth for all cluster state — lose it and you lose the cluster. Protect it with TLS + peer auth, encryption at rest, strict firewalling, and regular snapshots.

It is a Raft quorum store: run an odd number of members (3 or 5), never even, and keep it on low-latency disks because every write is fsynced across the quorum.

Snapshot + verify
ETCDCTL_API=3 etcdctl snapshot save snap.db
etcdctl snapshot status snap.db -w table
Walk through what happens on `kubectl apply`.Senior

kubectl sends the object to the apiserver, which authenticates, authorizes (RBAC), runs admission, validates, and persists to etcd. Controllers notice the new desired state and reconcile it; the scheduler binds Pods to nodes and kubelets start them.

apply does a three-way merge (last-applied vs live vs your file) so it is declarative and non-destructive. The object is authenticated, authorized, admitted, validated, and stored; then controllers reconcile toward it and the scheduler binds any new Pods.

kubectl applyapiserver admits & validatespersist to etcdcontrollers reconcilescheduler bindskubelet runs
Preview before applying
kubectl diff -f app.yaml       # what will change
kubectl apply -f app.yaml --server-side
A Pod is CrashLoopBackOff — how do you debug?Mid

kubectl describe for events and last state, kubectl logs --previous for the crashed process, check the exit code, probes, resource limits (OOM), config/secret mounts, and image entrypoint. Reproduce with an ephemeral debug container if needed.

CrashLoop means the container keeps exiting and the kubelet backs off (10s → 20s → 40s …). The exit code points the way: 137 = OOM/killed, 143 = SIGTERM, 1 = app error.

describe: events + lastStatelogs --previouscheck exit code / OOM / configfix & redeploy
Triage commands
kubectl describe pod web
kubectl logs web --previous
kubectl debug web -it --image=busybox --target=app
A Service returns no endpoints — how do you fix it?Mid

Almost always a selector/label mismatch or Pods failing readiness — only Ready Pods whose labels match the Service selector appear in the EndpointSlice.

Service selectorPod labels match?Pods Ready?EndpointSlice populated
Find the mismatch
kubectl get endpoints web            # empty?
kubectl get pods --show-labels
kubectl describe svc web | grep Selector
A node goes NotReady — what happens and how do you investigate?Senior

The node stops heartbeating; after the eviction timeout the controller reschedules controller-owned Pods elsewhere (bare Pods are lost). Check kubelet status, disk/memory pressure, container runtime, and network to the apiserver.

The kubelet stops posting status; after node-monitor-grace-period the node is marked NotReady and, after the eviction timeout, controller-owned Pods are rescheduled. Usual causes: kubelet/CRI down, disk or memory pressure, or lost apiserver connectivity.

kubelet stops heartbeatingNode → NotReadyeviction timeoutPods rescheduled elsewhere
Investigate
kubectl describe node n1 | grep -A6 Conditions
kubectl get pods -A -o wide --field-selector spec.nodeName=n1
How do you design multi-tenancy on a shared cluster?Senior

Namespace-per-tenant with ResourceQuota/LimitRange, RBAC scoped per namespace, NetworkPolicies for isolation, Pod Security/admission policy, and separate node pools or virtual clusters for hard isolation — soft multi-tenancy alone is not a trust boundary.

Soft multi-tenancy (namespace + RBAC + quota + NetworkPolicy + PSA) is fine for trusted teams. Hostile tenants need hard isolation — separate node pools, virtual clusters (vCluster), or separate clusters — because they still share one kernel and one apiserver.

Quota per tenant
kubectl create resourcequota team-a --hard=cpu=20,memory=40Gi,pods=50 -n team-a
Go deeper
Full, hands-on DevSecOps courses
Browse courses