Showing posts with label Interview. Show all posts
Showing posts with label Interview. Show all posts

Tuesday, 4 August 2026

Kubernetes Debugging Scenario: Node.JS CronJob dies with a V8 JavaScript heap OOM

Problem Scenario


A Node.js batch job running as a Kubernetes CronJob aborts with FATAL ERROR: Ineffective mark-compacts near heap limit at ~4 GB. No NODE_OPTIONS, no resources block. Each scheduled run leaves several failed pods behind.


Knowledge required to fix the problem (Q&A)


Detailed Q&A


1. Node.js / V8 memory model

Q: What does --max-old-space-size actually control, and what does it not control? 

It caps V8's old space — the long-lived generation of the JS heap. It does not cap new space (--max-semi-space-size), code space, large object space, or external/off-heap memory such as Buffer and ArrayBuffer allocations, native addon memory, thread-pool stacks, or glibc malloc arenas. So a process with a 6 GB old-space ceiling can easily have an RSS well above 6 GB.

V8 is Google's open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and in Node.js, among others.

--max-old-space-size sets the maximum memory limit (in megabytes) allocated to the Old Generation heap space inside V8, the JavaScript engine powering Node.js.

When V8 allocates memory for your application, it divides the JavaScript heap into distinct regions based on object lifecycle. This flag configures the largest region where long-lived objects reside.

What It Measures & Controls

--max-old-space-size explicitly caps memory allocated for:

  • Old Generation JavaScript Objects: Objects, arrays, functions, closures, and strings that have survived initial garbage collection cycles in the Young Generation space and were promoted to the Old Generation.
  • Old Pointer Space & Old Data Space: Regions holding objects that contain pointers to other objects and raw data (like numbers or unboxed scalars).

What It Does NOT Control

  • A common misconception is that --max-old-space-size caps the entire Resident Set Size (RSS) or system memory footprint of your Node.js process. It does not limit:
  • Node.js Buffers (ArrayBuffers): Since Node.js v8.0+, binary Buffer allocations use off-heap C++ memory backing stores (ArrayBuffer). While the JavaScript wrapper object lives on the V8 heap, the underlying raw bytes do not count toward the old space limit.
  • Native C++ Allocations: Memory used by native C++ add-ons, libuv threads, or external libraries compiled into Node.
  • Other V8 Heap Spaces:
    • New Space (Nursery/Young Generation): Where new allocations land (--max-semi-space-size).
    • Code Space: JIT-compiled bytecode and machine code.
    • Map/Cell Spaces: V8 internal hidden classes and metadata.
  • Call Stack Memory: Memory used by execution contexts and local variables on the stack.

Because of off-heap memory, a Node.js process with --max-old-space-size=2048 (2 GB) can easily consume 3 GB or more of total system RAM (RSS).

What Happens When the Limit Is Reached

  1. Aggressive Garbage Collection: As old space usage approaches the limit, V8 triggers blocking, high-overhead Mark-Sweep-Compact garbage collection cycles to reclaim dead objects.
  2. Process Crash: If V8 cannot free enough memory to fit the next allocation below the configured threshold, Node.js crashes with a fatal error:

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Default Values & Usage

Default Behavior: In modern Node.js versions, V8 dynamically sets the limit based on total available system RAM—typically around 2 GB to 4 GB on 64-bit systems if unspecified.

Command Line Flag:

node --max-old-space-size=4096 app.js

Environment Variable:

export NODE_OPTIONS="--max-old-space-size=4096"

 

Q: Why did the process die at ~4064 MB when nobody configured a heap limit? 

V8 picks a default heap ceiling from the memory it believes is available, and on 64-bit builds that lands at roughly 4 GB. The Mark-Compact 4064.3 MB line in the log is the giveaway that it hit that default ceiling rather than any limit you set.


Q: Why doesn't Node just size its heap to the container's memory limit? 

Historically V8 read host RAM, not the cgroup limit, so a Node process in a 512 Mi container would happily set a multi-gigabyte heap and get OOM-killed. Newer Node versions do consult cgroup constraints, but the behaviour varies by version — which is why the defensive answer is always to set the flag explicitly rather than rely on auto-detection.


Q: The workload starts with npm run start. Does setting NODE_OPTIONS in the container env actually reach the Node process? 

Yes — NODE_OPTIONS is an environment variable, so it's inherited by every child process npm spawns. Two caveats worth naming: it also applies to the npm wrapper process itself (harmless, just an extra reservation), and not every V8 flag is permitted inside NODE_OPTIONS. The alternative is passing the flag in the npm script itself, which is more surgical but easier to lose.



2. Diagnosis: which kind of OOM is this?

Q: How do you tell a V8 heap OOM from a kernel OOMKill from a kubelet eviction?

Signal V8 heap OOM OOMKilled Evicted
Log line FATAL ERROR: Ineffective mark-compacts near heap limit none from the app — killed mid-flight none from the app
Signal / exit SIGABRT, exit 134 SIGKILL, exit 137 pod deleted
Pod status Error OOMKilled in lastState.terminated.reason Failed, reason Evicted
Fix direction raise heap ceiling or reduce allocation raise container limit set requests so you aren't the first target

The ticket's evidence — the mark-compact message plus signal SIGABRT — puts it firmly in column one. That matters because raising the container limit alone would have changed nothing: V8 would still have aborted at 4 GB.


Q: How would you size the flag rather than guessing? 

Instrument before you tune. --trace-gc shows the heap trajectory over the run; process.memoryUsage() sampled periodically distinguishes heapUsed from external; --heapsnapshot-near-heap-limit=1 writes a snapshot right before the abort that you can open in Chrome DevTools to find the retaining structure. That tells you whether the working set is genuinely ~6 GB or whether one unbounded array is the whole problem.

Q: Is raising the heap the right fix at all? 

Usually it's a mitigation, not a fix. A benchmark job whose memory scales with input size will hit any ceiling you pick — the durable fix is streaming, batching, or paginating so peak memory is bounded by chunk size rather than dataset size. Raising the flag is defensible as a stopgap; the honest version says so in the ticket and files the follow-up. Note that in this case the real numbers came out at 10 GB heap with a 5-hour runtime, which is a fairly loud hint that the algorithm is the underlying issue.


3. Kubernetes resource management

Q: What's the difference between a memory request and a memory limit? 

The request is what the scheduler reserves — it decides which node the pod fits on and is the baseline the kubelet uses when deciding who to evict. The limit is enforced at runtime by the cgroup; exceed it and the kernel OOM-kills the container. Memory, unlike CPU, is incompressible: there's no throttling, only killing.

Q: What QoS class does a pod with no resources block get, and why does that matter here? 

BestEffort — the first thing evicted under node memory pressure, and it contributes nothing to the scheduler's accounting so the node can be oversubscribed into pressure in the first place. Setting requests equal to limits gives Guaranteed; requests below limits gives Burstable.

Q: How do you choose the relationship between the heap flag and the container limit? 

Limit strictly above heap ceiling, with headroom for everything --max-old-space-size doesn't cover — off-heap buffers, native memory, the npm and node process overhead, plus GC working room. The ticket proposed 6 GB heap under a 7 Gi limit; what actually shipped was 10 GB heap under a 12 Gi limit. Too tight and you convert a clean SIGABRT into a much harder-to-debug OOMKill.

Q: What's the risk of setting limits.memory well above requests.memory? 

You're overcommitting the node. It schedules against the request but can consume up to the limit, so several such pods on one node can drive it into memory pressure and trigger evictions of unrelated workloads. Matching them costs you scheduling flexibility but makes the blast radius predictable.

Q: You set requests.memory: 8Gi and the pod never starts. What's your first check? 

Whether any node has 8 Gi of allocatable memory free — allocatable is capacity minus kube-reserved, system-reserved, and eviction thresholds. The pod sits Pending with an Insufficient memory scheduling event. Big-request batch jobs are a classic case for a dedicated or autoscaling node pool.


4. CronJobs and Jobs

Q: What produced seven Error pods from one scheduled run? 

backoffLimit retries on failure, and a deterministic OOM fails identically every time — so the Job burned through its retries producing one dead pod each. The fix applied was a podFailurePolicy that fails the Job on the application's exit code instead of retrying, plus ttlSecondsAfterFinished so finished Jobs get garbage-collected rather than accumulating.

Q: What does podFailurePolicy require to work? 

restartPolicy: Never on the pod template, and rules matching on either container exit codes (onExitCodes) or pod conditions (onPodConditions, e.g. DisruptionTarget). Actions are FailJob, Ignore, Count, and FailIndex. The point is distinguishing retryable infrastructure failures from deterministic application failures — retrying a heap OOM six times is pure waste.

Q: Which CronJob fields govern history and overlap? 

successfulJobsHistoryLimit / failedJobsHistoryLimit for retained Job objects, ttlSecondsAfterFinished on the Job for automatic cleanup, concurrencyPolicy (Allow / Forbid / Replace) for overlapping runs, startingDeadlineSeconds for missed schedules, and activeDeadlineSeconds as a wall-clock kill switch. For a job that runs five hours, concurrencyPolicy: Forbid deserves a hard look.

Q: The schedule is 30 10 */14 * *. Does that run every 14 days? 

No — and this is the trap. Step values in day-of-month are evaluated within each month, so it fires on the 1st, 15th, and 29th, then resets. The gap between the 29th and the following 1st is two or three days, not fourteen. Genuine "every N days" needs an external scheduler or a daily run that no-ops based on a stored timestamp.


5. Container memory accounting

Q: When you read a container's memory usage, what are you actually seeing? 

Under cgroup v2 the kubelet reports working set derived from memory.current minus inactive file cache; memory.max is the hard limit. Crucially memory.current includes page cache, so a process doing heavy file I/O can look alarming without any anonymous-memory problem. RSS is anonymous plus mapped pages for the process specifically, and glibc often doesn't return freed memory to the OS — so RSS is sticky and lags real usage downward.

Q: Why is container_memory_rss a poor alerting signal for some workloads? 

Because it only captures what lives in RSS. For a JVM or Node process the heap is anonymous memory and RSS tracks it reasonably; for something like Percona MongoDB, where WiredTiger's cache sits in the OS page cache rather than RSS, the metric is structurally blind to the thing you care about — you want cache fill percentage instead. Matching the metric to the workload's memory architecture is the actual skill.


6. Verification

Q: How do you prove the fix worked? 

Trigger a manual run (kubectl create job --from=cronjob/experience-benchmarks) and confirm the Job reaches Complete with no SIGABRT and no Error pods. Then compare peak usage against the limit — completing at 95% of the ceiling is luck, not a fix. Verification model: live CronJob spec matches main, last three runs all Complete, runtimes recorded, zero Error pods.

Q: How do you confirm what's actually running in prod matches what's in the repo? 

Diff the live object against the manifest — kubectl get cronjob experience-benchmarks -o yaml against deploy/prod.yml. Drift between a merged PR and the running cluster is exactly the kind of gap that lets a "fixed" ticket keep failing, and it's the check that would have surfaced the tickets overlap before any code was written.

Q: What should you have checked before writing a single line for this ticket? 

Whether the problem still existed. The ticket sat in Backlog for four days, a ticket shipped a superset of the fix during that window, and the work that followed would have lowered the heap from 10 GB to 6 GB — reintroducing the OOM. Reading main and the live spec before implementing is the cheapest step in the whole process and the one that was skipped.


Brief Q&A


V8 / Node

Q: What does --max-old-space-size cap? Only V8's old space. Not new space, code space, or off-heap memory (Buffer, ArrayBuffer, native addons). RSS can exceed it substantially.

Q: Why die at ~4 GB with no flag set? That's V8's default ceiling on 64-bit. Node has historically sized it from host RAM, not the cgroup limit — so always set it explicitly.

Q: Does NODE_OPTIONS reach a process started via npm run start? Yes, it's inherited by child processes. It also applies to the npm wrapper itself.

Diagnosis

Q: Distinguish the three OOM flavours. V8 heap OOM → mark-compact message, SIGABRT, exit 134, pod Error. Kernel kill → no app log, SIGKILL, exit 137, OOMKilled. Eviction → pod Failed, reason Evicted. Only the first is fixed by the heap flag.

Q: How do you size the flag instead of guessing? --trace-gc for the trajectory, process.memoryUsage() for heap vs. external, --heapsnapshot-near-heap-limit=1 for a snapshot at the abort.

Q: Is raising the heap the real fix? Usually a stopgap. If memory scales with input size, any ceiling eventually fails — stream or batch so peak is bounded by chunk size.

Kubernetes resources

Q: Request vs. limit? Request drives scheduling and eviction ranking; limit is cgroup-enforced. Memory is incompressible — no throttling, only killing.

Q: No resources block means what QoS? BestEffort — first evicted under node pressure, and invisible to scheduler accounting. Requests == limits gives Guaranteed.

Q: How do heap ceiling and container limit relate? Limit strictly above the heap, with headroom for off-heap and process overhead. Too tight converts a clean SIGABRT into a harder-to-debug OOMKill.

Q: Request set high and the pod won't schedule? Check node allocatable (capacity minus reserved and eviction thresholds). Expect Pending with Insufficient memory.

Jobs / CronJobs

Q: Why several failed pods per run? backoffLimit retries, and a deterministic OOM fails identically each time. Use podFailurePolicy with onExitCodes (requires restartPolicy: Never) to fail fast, plus ttlSecondsAfterFinished for cleanup.

Q: Does 30 10 */14 * * run every 14 days? No. Day-of-month steps reset monthly → the 1st, 15th, and 29th. True "every N days" needs external scheduling.

Verification

Q: How do you prove it's fixed? Trigger a manual run from the CronJob, confirm Complete with no failed pods, and compare peak usage to the limit — finishing at 95% of the ceiling is luck.

Q: What do you check before writing any code? That the problem still exists. Diff the live object against the repo manifest; a stale ticket can lead you to lower limits that a since-merged fix raised.

Friday, 26 June 2026

DevOps Interview Questions - k8s ALB alarm




Post-incident review / technical interview questions.

These questions and answers were generated by Claude, upon it analyzed and fixed one CloudWatch alarm which have been flipping. Prompt I used:

I was following your analysis and resolution of this issue in order to acquire your knowledge. I would like to test my knowledge now. Can you compile a list of questions which cover every aspect of the issue and solution here? Don't be shy of creating a really long list of questions. If I am able to answer them all that means I am able to fix the issue on my own next time. Also prepare the answer key.



A. The alarm itself (CloudWatch / ALB fundamentals)

  1. What does the metric TargetResponseTime actually measure, and from whose perspective (client → ALB → target)?

  2. The alarm name was k8s-api-prod-core-7db0ccf2c3-target-response-time. What do the k8s- prefix and the hash portion tell you about how it was created?

  3. The alarm config was: threshold 0.8, GreaterThanThreshold, period 60s, 2 evaluation periods, statistic Average. In plain English, what condition makes it fire?

  4. Why does the alarm use the LoadBalancer dimension only, and not a TargetGroup dimension? What consequence did that have for our investigation?

  5. What is "flapping," and why does this particular threshold/period combination make flapping likely for a bursty workload?

  6. How do you pull an alarm's state-transition history, and what did 9 OKALARM cycles in 5 hours tell you?

  7. The alarm fires on Average. Why is that distinction (vs Maximum/p99) absolutely central to both the diagnosis and the fix?

  8. What is the "low-traffic statistical artifact" pattern, where a handful of slow requests inflate the average on a near-idle target — and what evidence did we use to rule it out here?

B. Narrowing from ALB to one service

  1. The ALB fronted six target groups. Name the technique we used to find which one was responsible, and the AWS CLI call behind it.

  2. Why can a single ALB serve six different Kubernetes services? What AWS-LB-Controller concept ties them together (hint: group.name)?

  3. Given the target group name k8s-default-dataservice-88e28b4b6c, how do you map it back to a Kubernetes Service and namespace?

  4. During the burst, data-service showed 5.83s avg / 29.7s max while every other service was <0.5s. Why did that immediately exonerate the shared ALB/ingress as the cause?

C. First look at the workload

  1. What does kubectl top pods show, and why is a single snapshot from it dangerous as evidence?

  2. The first snapshot showed one pod at 997m and three near-idle. What two different explanations are consistent with that, and why can't a snapshot distinguish them?

  3. What's the difference between a CPU request and a CPU limit in Kubernetes?

  4. How did we check whether the pod was being CPU-throttled at its limit, and what file did we read inside the container? What did nr_throttled / throttled_usec tell us?

  5. A deploy to v1.14.3-prod had happened ~15 min earlier. Why was it a red herring, and what evidence dated the flapping as pre-existing?

  6. Distinguish the three probe types (liveness, readiness, startup). What does each one control?

  7. The deployment had a startupProbe and livenessProbe but no readinessProbe. Operationally, what can't the system do without a readiness probe?

D. The load-balancing theory (and why it was wrong)

  1. Explain why round-robin load balancing degrades when request durations are highly variable. Use the "request count vs. total work" framing.

  2. What is the feedback-loop difference between round-robin and least-outstanding-requests (LOR)?

  3. What older, well-known algorithm is LOR equivalent to in nginx/HAProxy terms, and what does AWS's own guidance say about when to use LOR vs round-robin?

  4. "Head-of-line blocking" appeared twice in this incident at two different layers. Name both layers and how each one blocks.

  5. Why is a single kubectl top snapshot insufficient to prove round-robin is causing imbalance, and what data would actually prove or refute it?

  6. We initially called round-robin the "smoking gun," then withdrew it. What specifically made that conclusion wrong?

E. Target mode: instance vs IP (the topology that broke the theory)

  1. What's the difference between an ALB target group in instance mode vs ip mode? How can you tell which one you have from the registered targets and the target-group port?

  2. The target group registered 10 EC2 instances on port 31892. What does that tell you about the request path from ALB to pod?

  3. What is a NodePort service, and what is externalTrafficPolicy: Cluster vs Local?

  4. With instance mode + Cluster policy, describe the full path of a request from client to the backend process, including every hop and who load-balances at each hop.

  5. Given that topology, explain precisely why switching the ALB to least_outstanding_requests would not fix per-pod imbalance.

  6. What two changes together would enable load-aware per-pod routing, and why is that a much bigger change than a one-line annotation?

  7. Why were ALB access logs not useful for confirming per-pod distribution in this setup?

F. Getting the proof (Prometheus / time series)

  1. What is kube-prometheus-stack, and where did it live in the cluster?

  2. Why is kubectl port-forward an acceptable read-only way to query Prometheus, and what does it actually do?

  3. Write (conceptually) the PromQL that gives per-pod CPU usage over time. Why rate(container_cpu_usage_seconds_total[...]) rather than the raw counter?

  4. The time series showed all four pods evenly at 0.5–0.95 cores during the burst. Why did that refute the imbalance theory in one stroke?

  5. Each pod plateaued at ~0.9 cores despite a 1.5-core limit. What does that plateau strongly imply about the process model inside the pod?

G. The real root cause (app server / GIL / async)

  1. What is an application server worker (e.g., Gunicorn), and what's the difference between the master process and a worker process?

  2. What is a Global Interpreter Lock (GIL) or similar single-threaded runtime constraint, and why does it mean one worker process ≈ one core of CPU-bound throughput?

  3. The config had workers = 1 and an asynchronous event-loop worker class specified. Explain what each line does.

  4. What is the difference between a synchronous worker and an asynchronous worker in an application server? When does each shine?

  5. Why is an async (event-loop) worker the wrong model for heavy, synchronous CPU-bound data processing? What does "blocking the event loop" mean concretely?

  6. So with one async worker doing CPU-bound work, what is the per-pod concurrency for heavy requests — and how did that produce the fleet-wide ceiling of ~4 concurrent requests?

  7. How did we confirm the worker count and the CPU quota from inside a running pod (what command, what does cpu.max = 150000 100000 mean, what does worker count = 2 mean)?

  8. Why was the 1.5-core CPU limit effectively unusable given workers = 1?

  9. Tie it together: explain the full causal chain from "traffic burst" to "alarm fires," in one paragraph, using the confirmed root cause.

H. Designing the fix

  1. We considered vertical (more workers/CPU per pod), horizontal (more pods via HPA), and both. What's the trade-off, and why did "both" win?

  2. Why couldn't we just change the worker class to synchronous (or offload to a process pool) as part of this immediate infrastructure fix? What kind of change would that be?

  3. We set workers = 2. Why did the CPU limit have to go up to 2000m at the same time? What would happen if we'd set workers = 2 but left the limit at 1500m?

  4. The pods used ~2.5Gi RSS each at one worker. Why did we expect ~5Gi with two workers, and why wouldn't worker-fork preloading save us here? (What did we learn about when the application memory caches are built?)

  5. There's one import-time load we found (e.g., heavy model loading in a utility file). Why is that one shareable-via-fork but the bulk of the runtime memory is not?

  6. The HPA was autoscaling/v1, target 80%, min 4 / max 7. We measured bursts peaking at ~75% of the 1200m request. Explain mechanically why the HPA never scaled.

  7. targetCPUUtilizationPercentage is a percentage of what? Recompute: at the new 1500m request and a pod using ~0.9 cores, what utilization does the HPA see?

  8. Why did we lower the target to 50% and raise max to 10, rather than just one of those?

  9. What does a topologySpreadConstraints with maxSkew: 1, topologyKey: kubernetes.io/hostname, whenUnsatisfiable: ScheduleAnyway do — and why soft (ScheduleAnyway) rather than hard (DoNotSchedule)?

  10. We deliberately did not add a readiness probe. Explain the failure mode that a naive /health readiness probe would cause in this specific app under heavy load. Why is "no readiness probe" temporarily safer than a bad one here?

  11. What was the container port vs Service target port mismatch situation? Why was alignment low-risk, and why didn't it affect routing?

  12. An orphaned HPA manifest file was deleted. Why was it safe to delete, and how did we confirm it was no longer active?

I. Where the config lives & deploy mechanics

  1. How did we determine the workload was not managed by GitOps tool deployments (e.g., Argo CD), despite the tool being installed? What metadata annotation was the fingerprint?

  2. Which repository and file holds the deployment/HPA, and which separate repository/file holds the ingress? Why do they deploy through different mechanisms?

  3. Describe the deployment pipeline flow end to end. What event triggers it, and what are the key build/test/deploy jobs?

  4. The deploy step does a string substitution (sed 's#$TAG#...#') then kubectl apply. What's the role of the $TAG placeholder, and where does the tag value come from?

  5. Why does merging a PR to the main branch not deploy anything, while pushing a specific environment release tag does?

  6. The pipeline runs on private self-hosted runners. Why does that matter for a private-endpoint cluster?

J. Capacity analysis

  1. What instance types/sizes back the general-purpose compute tier, and how much allocatable CPU/memory does each have?

  2. What is Cluster Autoscaler, and how does it differ from node lifecycle managers like Karpenter? Which one is active in this cluster?

  3. There are two node groups feeding the tier (spot instances and on-demand instances). What are their min/max sizes, and what's the combined node ceiling?

  4. Do the packing math: given ~3920m allocatable CPU and ~400m daemonset overhead, how many pods at 1500m request fit per node? Why is CPU, not memory, the binding constraint?

  5. At HPA max (10 pods), how many nodes are needed, and is that within the ceiling? What's left for other tenants?

  6. Why is horizontal scale-out slow relative to instant traffic bursts? List every contributor to a cold pod's total time-to-serve.

  7. Given that scale-out lag, which part of our fix delivers immediate relief, and which acts as the slower "second line of defense"?

  8. Why did we bump the memory request to 5Gi even though it doesn't change node packing density?

K. Staging-first deploy & verification

  1. Why deploy to the staging environment first when the staging manifest file wasn't even changed by the PR?

  2. Precisely what does the staging deploy validate, and what does it not validate?

  3. Staging runs on the same cluster as production. How is it isolated, and what was the risk we flagged about a tiny 0.5-core staging pod suddenly running workers=2?

  4. List the verification steps we ran on staging, and the pass criteria for each.

  5. Why did we test both GET /health and a heavy POST data processing route, rather than just the health check?

  6. The startup probe warms up by hitting an internal pre-cache endpoint. What does that endpoint do, and why is it the most likely place for a deploy to fail (especially on a CPU-starved staging pod)?

L. Production rollout & confirmation

  1. What version did we tag, and why a patch bump (v1.14.4) rather than a minor/major version shift?

  2. During the production rollout, two new pods went Pending, one with no available node. What happened next, and which log event confirmed the cluster autoscaler reacting?

  3. Why did the rollout take ~6 minutes and stay safe (no dropped traffic) the whole time? What deployment configuration controls the surge/unavailable behavior?

  4. Post-deploy, the new pods showed only ~2.6Gi memory usage, not ~5Gi. Why — and why is that expected rather than a contradiction of our sizing?

  5. After deploy, individual requests still hit ~3s max, but the alarm stayed OK. Why is that consistent with a successful fix? (Connect it back to question 7.)

  6. We monitored for 45 minutes and saw no flapping, yet we kept the incident ticket open. What's the honest gap in that evidence, and what would definitively close it?

  7. The HPA stayed at 4 pods during the entire monitoring window. Why is that a good sign rather than a sign the HPA fix did nothing?

M. Operational / process & gotchas

  1. The cluster API is private-only. What's the practical consequence for local engineers using kubectl, and why does aws sts get-caller-identity succeed while kubectl times out? How do you distinguish an auth problem from a network/VPN problem?

  2. Why did the CI/CD deployment job still work even when our local machine's kubectl couldn't reach the cluster?

  3. The standard code security checks failed on automated image-scanning and vulnerability gates. Diagnose how to isolate the root cause. Were they caused by our configuration change? How do we prove that?

  4. The repository management system showed a BLOCKED merge status, but branch protection rules returned a 404. What's the resolution of that apparent contradiction (e.g., legacy branch protection vs. modern repository rulesets)?

  5. What was the only thing actually gating the code merge, and why were the red security check flags irrelevant to it?

  6. Which actions in this whole deployment flow required explicit manual operator confirmation before execution, and why those specifically?

  7. What's the commit-authorship convention in this engineering environment, and what must never appear in a commit message or PR description?

N. Synthesis & transfer (test of true mastery)

  1. If you were paged for this exact alarm tomorrow with zero prior context, list the first five commands/queries you'd run, in order, and what each one would tell you.

  2. Name three plausible-but-wrong hypotheses for a flapping TargetResponseTime alarm, and the single piece of evidence that kills each.

  3. Suppose the per-pod CPU time series had shown one pod pinned at 100% and three idle (the load imbalance pattern we originally expected). Given the instance-mode topology, what would the real fix have been then — and why is it different from the LOR annotation?

  4. The fix here was vertical + HPA scaling. Under what circumstances would the correct long-term fix instead be an application architecture change, and what would that change look like?

  5. Generalize the core lesson: what specific property of an application workload makes "adding more replicas behind a standard round-robin/random balancer" fail to resolve response time spikes, and what is the class of fixes that does help?

  6. If the morning peak traffic burst still trips the alarm after this infrastructure fix, what are your next two remediation levers (in order), and what data would you collect to choose between them?


Thursday, 9 January 2025

ELK Stack Interview Questions




Elasticsearch (ES)





Kibana


  • How to install Kibana on bare metal?
    • How to install Kibana in k8s cluster?
  • What are Dashboards?
  • What are Alerts?
  • How to back up and Elastic objects like dashboards and alerts? How to restore them in another Elastic instance?
  • TBC


Thursday, 11 April 2024

Docker Interview Questions

Here are some Docker Interview Questions with answers and/or links to answers. Good luck! 💪🤞





Kubernetes Interview Questions

Here are some Kubernetes interview questions. Good Luck!




kubectl



Security


Workloads

Cron Jobs

...

Daemon Sets

  • What is a DaemonSet?
  • What is the purpose of DaemonSet?
  • What is the difference between DaemonSet and ReplicaSet?
  • How does a typical DaemonSet manifest look like?

Deployments

  • What is a Deployment?
  • How does typical Deployment manifest look like?
  • What is a replica?
  • How to set a desired number of pods? 
  • Can number of pods be dynamic? How to set this?
  • How to make pods to be equally distributed across multiple AZs?
  • Explain the role of labels in Deployment.
  • How to deploy it?
  • How to find a Deployment?
  • How to monitor it?
  • How to debug it?
  • How to roll it back?
  • What happens if Deployment fails for e.g. AWS Secrets Manager does not have a key in some secret and that key's value is used as a value of env var defined in pod template. Does k8s try to restart the pod? Which part of k8s control plane deals with this?

Jobs

...

Pods

  • What are the IDs in the pod name like in this example: my-app-29361181-apzjq 
  • Explain each pod status type:
    • ContainerCreating
    • Completed
    • Running
    • Container




Replica Sets
...

Replication Controllers
...

Stateful Sets
...

Service


Ingresses

...

Ingress Classes

...

Services


NodePort

  • What is a NodePort service?
  • What is its role and when is it used?
  • Which ports are involved?
  • How does a typical Manifest for NodePort look like?
  • How is it deployed on nodes? How to select nodes on which to deploy it?


Config and Storage


Config Maps


Persistent Volume Claims

  • How to check the total storage allocated for nodes in a cluster?
  • Which kubectl command shows all PVCs?
  • Explain each column that kubectl get pv shows in its output:
    • NAME
    • CAPACITY
    • ACCESS MODES
    • RECLAIM POLICY
    • STATUS
    • CLAIM
    • STORAGECLASS
    • VOLUMEATTRIBUTESCLASS
    • REASON
    • AGE

Secrets

Storage Classes

Cluster


Cluster Role Bindings
Cluster Roles
Events
Namespaces
Network Policies
Nodes
Persistent Volumes
Role Bindings
Roles
Service Accounts

Custom Resource Definitions

...

Debugging

  • Pod stuck in CrashLoopBackOff, no logs, no errors.
    • How do you debug beyond kubectl logs and describe?
  • A StatefulSet pod won’t reattach its PVC after a node crash.
    • How do you recover without recreating storage?
  • Pods are Pending, Cluster Autoscaler won’t scale up.
    • Walk me through your top 3 debugging steps.
  • NetworkPolicy blocks cross-namespace traffic.
    • How do you design least-privilege rules and test them safely?
  • Service must connect to an external DB via VPN inside the cluster.
    • How do you architect it for HA + security?

Security and Architecture

  • Running a multi-tenant EKS cluster.
    • How do you isolate workloads with RBAC, quotas, and network segmentation?
  • Kubelet keeps restarting on one node.
    • Where do you look first – systemd, container runtime, or cgroups?
  • Critical pod got evicted due to node pressure.
    • Explain QoS classes and eviction policies.
  • A rolling update caused downtime.
    • What went wrong in your readiness/startup probe or deployment config?
  • Ingress Controller fails under load.
    • How do you debug and scale routing efficiently?

Performance and Reliability

  • Istio sidecar consumes more CPU than your app.
    • How do you profile and optimise mesh performance?
  • etcd is slowing down control plane ops.
    • Root causes + how do you tune it safely?
  • You must enforce images from a trusted internal registry only.
    • Gatekeeper, Kyverno, or custom Admission Webhook – what’s your move?
  • Pods stuck in ContainerCreating forever.
    • CNI attach delay? OverlayFS corruption? Walk me through your root-cause process.
  • Random DNS failures in Pods.
    • How do you debug CoreDNS, kube-proxy, and conntrack interactions?

To Be Continued...

Git Interview Questions



  • What is Git?
  • Explain git clone command.
  • Explain git checkout command.
  • What is cherry picking?
    • When to use it? (explain how it's used for team collaboration, bug hotfixes, ...)
    • What is the syntax of git cherry pick command?
    • On which branch do we need to be before cherry picking?
    • How does the commit graph look like before and after cherry picking? (draw an example)
    • Explain its options:
      • -edit
      • --no-commit
    • Git Cherry Pick | Atlassian Git Tutorial
  • Explain git log command
  • What is the difference between git revert and reset commands. Which one should be used on public branches?
  • What is rebasing?
    • Difference between rebase and merge strategies
  • To Be Continued...

Python Interview Questions

Here are some Python interview questions. Good luck!



  • What does the following expression do? if __name__ == "__main__"
    • https://stackoverflow.com/questions/419163/what-does-if-name-main-do

More questions:

DevOps Interview Questions

Here are some general DevOps interview questions. Good luck!

image source: What is DevOps?



AWS Interview Questions

Here are some AWS Interview Questions. Good Luck!



AWS IAM

Networking 
  • Draw a diagram which shows the following:
  • VPC - Virtual Private Cloud
  • VPC - Subnets
  • VPC - Routing Tables
    • What does route table contain? What are destinations and what are targets. Name a few possible destinations and targets. 
    • What is a main route table? Can it be modified? Can it be deleted?
    • What are subnet route tables? Can one subnet route table be associated by multiple subnets? How many route tables can subnet be associated with?
  • VPC - Security Groups
    • What are Security Groups?
    • Does every VPC (default and custom) come with a security group? Is that a default security group and what is its name?
    • Which AWS resources can be associated to security group(s)?
    • What is the minimum & maximum number of security groups that AWS Lambda can be associated with?
    • Is it recommended to use the default security group?
    • Do resources have any security group if they are not assigned one during their creation?
    • Can rules of the default security group be changed (edited)?
    • Can default security group be deleted?
    • What are the default inbound and outbound rules of the default security group?
    • Default security groups for your VPCs - Amazon Virtual Private Cloud
    • If security group has no outbound rules, does it mean that it prevents any outbound traffic?
    • How to block all outbound traffic?
    • How to specify deny-all outbound rule?
    • Why are Security groups stateful firewalls?
  • VPC - Peering Connections
    • What are VPC Peering Connections?
    • Where can peering VPCs reside? (account, region)
    • What are requester and accepter?
    • How is peering requested in AWS console and how is it accepted?
    • Is connection fully bi-directional? (Can resources in each VPC initiate a connection?)

  • AWS DNS
    • What is Amazon DNS server?
AWS EC2
  • What are the spot instances?

AWS RDS
  • Describe the difference between 3 types of deployment options (readability of standby instances):
    • Single DB instance
    • Multi-AZ DB instance
    • Multi-AZ DB cluster
  • What does DB subnet group define?
  • What does it mean when public access to RDS instance is enabled? Who can access the instance and how is this controlled?
  • What is the purpose of VPC security groups associated to RDS instance?
  • Is it possible to copy snapshots from one to another region? [Cross-Region Snapshot Copy for Amazon RDS | AWS News Blog]


AWS ECS
  • What is AWS ECS?
  • When to deploy workload to ECS? (instead of EC2 or EKS)


Further reading: