A VM runs nginx, an app server and crond under supervisord; how would you split that when moving to Kubernetes?
answer
- the kubelet is the supervisor now
- one main process per container
- same pod only if coupled
- crond times replicas
- localhost shared, filesystem not
basics
~20 sGive 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.
solid answer
~40 sKubernetes supervises containers, and a container lives as long as its main process. With supervisord as that process, the app can crash while the container looks healthy, and restarts, probes and resource limits cannot tell the daemons apart. So I split by lifecycle. The app server gets its own container. nginx either becomes a second container in the same pod, if it proxies to the app over `localhost` or serves files from a shared volume, or it goes away in favour of the cluster's Ingress or Gateway layer. crond does not move at all: its entries become `CronJob` objects, because cron inside the image would run each job once per replica once the Deployment scales. Anything that scales differently gets its own Deployment.
code
yaml · 30 linesapiVersion: apps/v1
kind: Deployment
metadata:
name: shipment-tracking
spec:
replicas: 3
selector:
matchLabels:
app: shipment-tracking
template:
metadata:
labels:
app: shipment-tracking
spec:
containers:
- name: api
image: registry.example.com/shipment-tracking:3.14.2
volumeMounts:
- name: sock
mountPath: /run/app
- name: nginx
image: registry.example.com/shipment-tracking-nginx:1.4.7
ports:
- containerPort: 8443
volumeMounts:
- name: sock
mountPath: /run/app
volumes:
- name: sock
emptyDir: {}go deeper
Recall that Kubernetes restarts containers, not processes inside them, so each service gets its own container and cron becomes a CronJob.
Explain what containers in one pod share by default (network namespace, declared volumes) and what they do not (root filesystem, process namespace unless enabled).
Point out the operational failures of the supervisor model: hidden crash loops, mixed logs, one resource budget, and scheduled jobs multiplying with replicas.
Decide which pieces the platform should absorb, such as TLS and routing moving from a per-pod nginx to a shared Gateway layer, and who then owns them.
## Why a supervisor fights Kubernetes On a VM, **supervisord** (or systemd) is the thing that keeps processes alive. In Kubernetes, that job belongs to the **kubelet**, and the kubelet only sees **containers**. A container's lifetime is tied to its main process: when that process exits, the container has exited, and the pod's `restartPolicy` decides what happens next. Liveness probes add a second signal. If supervisord is the main process of one container that also runs nginx, the app server and crond, the kubelet is blind to what happens underneath: - The app server can crash and be restarted by supervisord in a loop while the container stays `Running`, unless a probe exposes it. - One container has one set of `resources`, so you cannot give the JVM-heavy app memory without also giving it to nginx. - Restart counts, container logs and events mix all three daemons together. - Scaling the Deployment copies all three, including crond. ## Splitting by lifecycle For a **shipment-tracking API** that ran this way on each VM, the split looks like this: | Process on the VM | Where it goes in Kubernetes | Why | |---|---|---| | App server | main container of the API pod | it is the service; it gets its own probes and resources | | nginx | second container in the same pod, or removed | keep it only if it needs `localhost` or shared files with the app | | crond | one `CronJob` per crontab entry | schedule is a cluster concern, not a replica concern | | supervisord | removed | the kubelet is now the supervisor | ## Same pod or separate Deployment Containers in one pod are scheduled together, start and stop together and scale together. Use that only for processes that are genuinely coupled. A quick test: 1. Do they talk over `localhost` or a Unix socket, or share files? Same pod works, since containers in a pod share the **network namespace** and can mount the same volume. 2. Do they need to scale independently? Separate Deployments. 3. Can one be replaced by something the platform already provides? nginx doing TLS and routing is usually replaced by the cluster's Ingress or Gateway API layer. Containers in one pod do **not** share a filesystem by default (each has its own root filesystem; share data through a volume such as `emptyDir`), and they do not see each other's processes unless the pod sets `shareProcessNamespace: true`. ## The cron trap The most common mistake is leaving `crond` in the image because it worked on the VM. With one replica nothing looks wrong. Scale the Deployment to three and the nightly purge runs **three times**, concurrently, against the same database. There is no leader election between replicas. A `CronJob` creates exactly one Job per schedule point (under its concurrency rules), keeps a history of runs and can be suspended during cutover. One detail that bites on migration: the VM's crontab used the machine's local time zone. A CronJob's schedule is interpreted in the kube-controller-manager's time zone unless the CronJob sets `timeZone`, so a job that ran at 02:00 local can silently shift. ## What a worked split looks like - `Deployment/shipment-tracking`: containers `api` and, only if needed, `nginx`, with a shared `emptyDir` for any socket or static files. - `CronJob/shipment-archive`: runs the same image with a different command. - No supervisord anywhere. If the app forks helper processes, a minimal init process that forwards signals and reaps zombies is fine, because it is not a second service.
- Why not run crond as a DaemonSet instead of converting each entry to a CronJob?A DaemonSet runs one pod per eligible node, so a 12-node cluster would run the job twelve times, and the count changes whenever nodes are added or removed. A CronJob ties the schedule to the cluster, creates one Job per schedule point, keeps run history and can be suspended.
- Is it ever acceptable to keep two processes in one container?Yes, when the second process is not a service in its own right: a minimal init that forwards signals and reaps zombie children, or a short helper the app itself spawns and waits for. What should not share a container is anything that needs its own restart, probe, resources or scaling.
saying these in an interview costs you the question
- Kubernetes forbids more than one container in a pod
- supervisord is fine because Kubernetes restarts the pod when any process dies
- Leaving crond in the image is harmless once the Deployment scales
- Every process must become its own Deployment
- Containers in the same pod share one root filesystem