skip to content

Adoption & Migration

Judgment calls rather than object mechanics: what workloads justify a cluster, what a lift-and-shift actually costs, and which assumptions - local disk, fixed IPs, in-memory session state - an application has to give up first. It is the platform design round.

part ofKubernetesoverview, primer and where to startread it →
on this pageshow

questions

16

Before moving a ticket-booking checkout service onto Kubernetes, what must the application itself change to run well as a container?

level: juniorimportance: must knowfreq 70%

answer

  1. same image, different inputs
  2. where does kubectl logs read
  3. ready means able to serve
  4. signal, drain, exit in time
  5. cgroup, not the node

basics

~20 s

The app must read configuration from environment variables or mounted files, log to stdout and stderr, expose a readiness signal that reflects real ability to serve, shut down cleanly on SIGTERM, and size itself from its container limits.

solid answer

~50 s

Kubernetes assumes a process it can start, stop and replace anywhere, so the app has to give up host assumptions. **Config** comes from environment variables or mounted files, so the same image runs in every environment. **Logs** go to stdout/stderr, where the container runtime captures them and `kubectl logs` or a log agent picks them up; files inside the container vanish with it. A **readiness endpoint** reports whether this instance can actually take a checkout right now, so the Service only routes to ready pods. On **SIGTERM** the app stops taking new work, finishes in-flight requests and exits before the grace period (30 seconds by default) ends, or it is killed. Finally the **runtime** must size thread pools and memory from the container's cgroup limits, not from the node, and anything it writes should go to a declared volume, not the image filesystem.

code

yaml · 23 lines
yaml
apiVersion: v1
kind: Pod
metadata:
  name: checkout
spec:
  terminationGracePeriodSeconds: 45
  containers:
    - name: checkout
      image: registry.example.com/booking/checkout:4.12.3
      env:
        - name: PAYMENT_GATEWAY_URL
          value: https://pay.internal.example.com
        - name: LOG_FORMAT
          value: json
      readinessProbe:
        httpGet:
          path: /ready
          port: 8443
          scheme: HTTPS
      resources:
        limits:
          cpu: 1500m
          memory: 3Gi

go deeper

for a junior

Recall the five items by name: config from the environment, logs to stdout, honest readiness, clean SIGTERM handling, sizing from limits. Give one concrete example of each from a real app.

for a middle

Explain the mechanism behind each item: where kubectl logs reads from, what happens after the grace period, why Services only route to Ready pods, and why a runtime can misread its CPU count.

for a senior

Show how you would verify readiness before a migration: run the image with limits and a read-only root filesystem, send SIGTERM under load, and check logs, readiness and exit timing.

for a principal

Frame the checklist as a platform contract: which items the platform can enforce by policy or templates, which only code review catches, and how to keep legacy apps moving without waiving the rules.

## Why an application needs a pre-flight check A Kubernetes **Pod** is disposable. The scheduler can place it on any node, the Deployment controller can replace it during a rollout, and a node drain can evict it at any time. A ticket-booking checkout that ran for years on one VM usually carries assumptions that break under that model: a config file edited by hand, a log file rotated by the host, a process that dies abruptly, a runtime that thinks the whole machine is its own. Application readiness is the list of assumptions to remove **before** the first deploy, not after the first incident. ## The five items | Item | VM habit | Container-ready form | |---|---|---| | Configuration | `/etc/checkout/app.conf` edited per host | environment variables or files mounted into the pod | | Logging | `/var/log/checkout.log` plus host rotation | one event per line on stdout/stderr | | Readiness | "the port is open" | an endpoint that answers "can I take a booking now?" | | Shutdown | killed with the VM | handles SIGTERM, drains, exits in time | | Sizing | reads the host's CPUs and RAM | reads the container's cgroup limits | ### 1. Configuration from the environment The image should be **identical** in every environment; only its inputs differ. Kubernetes can inject values as environment variables (`env`, `envFrom`) or as files in a mounted volume. The application's job is simply to read them at startup, and to fail fast with a clear message when a required value is missing. Secrets such as the payment gateway key follow the same rule and are never baked into the image. ### 2. Logs on stdout and stderr The container runtime captures a container's standard streams, the kubelet exposes them, and `kubectl logs` reads them. Cluster log agents usually collect the same files from each node. A log written to a file inside the container is invisible to all of that and disappears when the container is replaced. Practical rules: - write one structured event per line, so a multi-line stack trace does not become many records; - do not rotate or compress logs in the app; - keep the request ID in every line, because a request may cross several pods. ### 3. A readiness signal that tells the truth Kubernetes routes Service traffic only to pods that report **Ready**. The application must expose an endpoint that turns healthy only once caches are warm and the connection pool is open, and that turns unhealthy when this instance genuinely cannot take bookings. "The HTTP port answers" is not the same statement. How the probe itself is configured is a separate topic; the application's duty is to make the answer honest. ### 4. A clean SIGTERM path When a pod is deleted, the kubelet sends the container's main process **SIGTERM**, waits up to `terminationGracePeriodSeconds` (30 seconds unless the pod sets another value), then sends SIGKILL. A checkout that ignores SIGTERM loses every in-flight payment when the kill arrives. A ready application: 1. stops accepting new requests (or starts failing readiness); 2. finishes or hands back work already in progress; 3. closes connections and flushes buffers; 4. exits with status 0 well inside the grace period. The process must also actually **receive** the signal, which means it runs as the container's main process or behind an init that forwards signals. A `preStop` hook can add a short pause before SIGTERM; its detailed timing belongs to the graceful-shutdown topic. ### 5. A runtime that reads its cgroup limits Container limits are enforced by Linux cgroups, but a process that asks "how many CPUs are there?" may be told the node's count. A JVM or Go program that sizes thread pools, GC threads or heap from the node's 32 cores and 128 GiB will overrun a 2-CPU, 3 GiB container. Modern runtimes read the cgroup limits; older ones need explicit settings. ## Two items people forget - **Writes**: anything the app writes (temp files, upload buffers, caches) should land on a declared volume such as `emptyDir`, so the root filesystem can later be made read-only. - **No local identity**: session state, scheduled jobs and fixed IPs belong elsewhere; the app must tolerate running as several interchangeable replicas. ## Putting it together A useful habit is to run the checkout locally in a container with a memory limit, a read-only root filesystem and a `docker stop` timeout, and watch what breaks. Every failure there is a failure you would otherwise have met in the cluster during a rollout.

  • Why is logging to a file inside the container a problem even if the app rotates it?
    The file lives in the container's writable layer, so it disappears when the container is replaced, and `kubectl logs` and node log agents never see it because they read the captured stdout/stderr. It also consumes node ephemeral storage, which can get the pod evicted. Writing to stdout lets the platform own collection, rotation and retention.
  • What happens to in-flight checkouts if the app ignores SIGTERM?
    Nothing changes when SIGTERM arrives, so the app keeps working until `terminationGracePeriodSeconds` (30 seconds by default) expires. The kubelet then sends SIGKILL, which cannot be caught, and every request still running is cut off mid-flight. Clients see reset connections or half-finished bookings, and each rollout also takes the full grace period per pod.
  • Why must a readiness endpoint differ from simply checking that the port is open?
    An open port only proves the listener exists. The checkout may still be warming caches, missing its database pool, or overloaded. Readiness decides whether the Service sends it traffic, so it should report whether this instance can complete a booking now; otherwise users hit a pod that accepts connections and then fails.

It is like moving from a home kitchen to a shared commercial one: you bring labelled ingredients, clean up when the shift bell rings, and cook to the size of your station, not the whole building.

saying these in an interview costs you the question

  • Bakes per-environment config files into separate images for dev and prod
  • Keeps logging to a local file because the container has a writable layer
  • Says Kubernetes waits for the app to finish before stopping it, however long
  • Treats an open TCP port as proof the service is ready for traffic
  • Assumes the JVM or runtime automatically sees only the container's resources, whatever its version
open as a page

On a Kubernetes platform run by a platform team, what is a golden-path template, and why use it instead of hand-written manifests?

level: juniorimportance: must knowfreq 58%

basics

~20 s

A golden-path template is a platform-maintained, pre-approved way to deploy a service: developers fill in a few values and the template produces the Deployment, Service, probes and resources, so every team gets safe defaults without writing raw Kubernetes manifests.

open as a page

When PostgreSQL runs in a Kubernetes StatefulSet with per-replica PersistentVolumeClaims, what does Kubernetes actually provide, and what is still left for you to build?

level: middleimportance: must knowfreq 64%

basics

~20 s

A StatefulSet gives each PostgreSQL pod a stable name, its own volume and ordered rollout. It knows nothing about which pod is primary, replication, failover, backups or safe upgrades, so all of that is still yours.

open as a page

When moving a service from VMs into Kubernetes pods, which host-level assumptions usually break, and what replaces each one?

level: middleimportance: must knowfreq 64%

basics

~20 s

Pods are disposable and restart anywhere with a new IP and an empty filesystem, so local disk, fixed IPs, in-memory sessions, host cron and log files break. They move to object storage or a PVC, a Service name, a shared session store, a CronJob and stdout.

open as a page

A team wants to run PostgreSQL and Kafka inside its Kubernetes cluster rather than use managed services. How do you decide, and what would make you say no?

level: principalimportance: must knowfreq 52%

basics

~20 s

Decide by ownership and risk, not by preference. In-cluster operators suit teams that can run databases, need portability or have no managed option. Otherwise a managed service is usually cheaper overall. Say no when nobody can own recovery.

open as a page

A VM runs nginx, an app server and crond under supervisord; how would you split that when moving to Kubernetes?

level: juniorimportance: should knowfreq 47%

basics

~20 s

Give each long-running process its own container so Kubernetes can restart and probe it separately: the app and nginx as containers (together in one pod only if they must share localhost or files), and crond replaced by a CronJob.

open as a page

In Kubernetes, why must a JVM or Go runtime size itself from its container's cgroup limits rather than the node's totals, and how does each do it?

level: middleimportance: should knowfreq 52%

basics

~20 s

Container CPU and memory limits are enforced by cgroups, but a runtime that reads the node's core count or RAM oversizes threads and heap. Current JVMs read cgroup limits by default; Go 1.25+ caps GOMAXPROCS at the CPU limit.

open as a page

A Kubernetes golden-path template deploys a fraud-rules engine as a 7-replica Deployment; on a developer's single-node laptop cluster six pods stay Pending. What leaked, and how should the platform respond?

level: seniorimportance: should knowfreq 40%

basics

~20 s

The template's production scheduling default leaked: required pod anti-affinity on kubernetes.io/hostname allows one replica per node, so one node runs one pod. The platform should make such defaults environment-aware, explain them, and keep failures debuggable.

open as a page

A three-broker Kafka cluster on Kubernetes rejects acks=all writes during routine node drains, although a PodDisruptionBudget allows only one unavailable broker. How can that happen, and what do you change?

level: seniorimportance: should knowfreq 41%

basics

~20 s

A PodDisruptionBudget counts Ready pods, not in-sync replicas. A restarted broker can be Ready while still catching up, so a second eviction is allowed. Slow volume reattachment stretches that window. Gate restarts on replica health and serialise drains.

open as a page

What do Kubernetes data-service operators such as CloudNativePG and Strimzi add on top of plain pods and volumes before a failover, drain or rolling restart is safe?

level: seniorimportance: should knowfreq 44%

basics

~20 s

They add knowledge of the database's own state. CloudNativePG tracks and labels the primary, moves Services, switches over before a drain and creates PodDisruptionBudgets. Strimzi restarts brokers one at a time and only when in-sync replicas allow it.

open as a page

After a shipment-tracking API moves from VMs into Kubernetes, a carrier firewall that allowlisted the VM's fixed IP rejects its outbound calls; why, and what are your options?

level: seniorimportance: should knowfreq 43%

basics

~20 s

Outbound calls now leave from pod or node addresses that change whenever pods reschedule or nodes are replaced, not from the old fixed IP. Route egress through a NAT or egress gateway with a reserved address, or replace IP trust with authentication such as mTLS.

open as a page

You run a Kubernetes developer platform: how do you draw the line between platform-owned and workload-owned configuration, and which escape hatches do you allow?

level: principalimportance: should knowfreq 35%

basics

~20 s

Draw the line at a versioned contract: the platform owns the cluster, shared services and non-negotiable guardrails; teams own their images, sizing, scaling and service behaviour. Escape hatches are graded, stay under admission policy, and every use is tracked.

open as a page

You own moving a shipment-tracking API from six VMs onto a shared Kubernetes cluster; how would you phase the cutover so every step stays reversible?

level: principalimportance: should knowfreq 37%

basics

~20 s

Run the same build on both platforms with state kept outside both, shift traffic in weighted steps from a layer above them while the VMs stay warm for rollback, hand over singletons like scheduled jobs exactly once, and decommission the VMs only after a soak.

open as a page

How does a platform controller provision Kubernetes namespaces on request, from a developer's custom resource to a ready namespace?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

A developer creates a small request object; a platform controller watches it and repeatedly reconciles a Namespace plus its standard RoleBindings and guardrails, owned by the request and reported through status conditions, so no developer needs cluster-wide rights to create namespaces.

open as a page

For a database on Kubernetes, what do you give up and gain by using local NVMe PersistentVolumes instead of network-attached block storage?

level: middleimportance: nice to knowfreq 31%

basics

~20 s

Local NVMe gives much lower, steadier I/O latency, but the volume is tied to one node. If that node is lost, the replica's data goes with it, and the pod cannot move. Database replication has to provide the durability.

open as a page

After a 210-node multi-tenant Kubernetes cluster starts requiring readOnlyRootFilesystem: true in container securityContext, a ticket-booking checkout crashes at startup. How do you make the app ready for it?

level: seniorimportance: nice to knowfreq 32%

basics

~10 s

Find every path the app writes, redirect those writes to explicitly mounted emptyDir volumes (disk-backed by default, memory-backed only when small and justified), set sizeLimit, and point the runtime's temp and cache directories there.

open as a page