Conrad DevOps

Docker and Kubernetes

The container and cluster basics from your Conrad notes — images and containers, a Nuxt multi-stage Dockerfile, what the image contains, .dockerignore, Compose and volumes, Deployment, Service, HPA and Istio VirtualService, probes, rolling updates and Service types.

From the Docker and Kubernetes parts of your Conrad DevOps note.

Know

  • Docker: image (built, immutable, does nothing) versus container (a running instance); a multi-stage build so only .output and Node ship; .dockerignore keeps node_modules and .env out of the build context; Compose runs several containers locally; volumes hold data that outlives a container, which stateless storefront pods do not need.
  • Kubernetes objects: Deployment (image, replicas, resources, probes), Service (a stable address across pods, ClusterIP behind the load balancer), HPA (scales on CPU or memory relative to requests), Istio VirtualService (weighted and host-based routing).
  • The rest of the manifests: ConfigMap for plain settings and Secret for credentials (synced from the cloud's secret manager), both injected as environment variables; StatefulSet with PersistentVolumeClaims for things with identity and data (Redis, Kafka); PodDisruptionBudget for node upgrades; ServiceAccount plus Workload Identity for access to buckets and secret managers.
  • Node and the HPA: a saturated event loop uses one core, so a pod with a two-CPU request never shows more than 50% and a CPU target never fires; request one CPU per pod and scale on event loop utilisation or latency, through custom metrics or KEDA, which drives an HPA from a Prometheus query.
  • Keeping it up: liveness restarts broken containers, readiness gates traffic, rolling updates overlap old and new pods (maxSurge and maxUnavailable, 25% each by default), and scale-down waits five minutes by default.

Fact check of your notes

Gotcha· There is a small node_modules in the image

"The image contains neither node_modules nor source code" is right in spirit: no source and no project node_modules. But .output/server/node_modules holds the runtime dependencies Nitro traced and did not inline, and it ships with the image.

Gotcha· A container is heavier than an isolate

Comparing a container to a running Worker is a useful picture, but a container is an OS-level sandbox with its own filesystem and a long-lived process, while an isolate is a lightweight sandbox inside a shared process with request-scoped I/O. That difference is the reason the storefront can hold connection pools.

Gotcha· Volumes outlive containers

A volume is not only for the same container after a restart: it is storage that exists independently of any container and can be shared between containers.

Gotcha· KEDA feeds the HPA, it does not replace it

A ScaledObject with a Prometheus trigger makes KEDA create and drive an HPA from the query result; the 15-second loop and the min and max replicas are still the HPA's. What KEDA adds is the metric source and scale to zero.

Gotcha· HPA needs resource requests

"At 80% load, create new pods" only works if the containers declare resources.requests, because utilisation is measured against them.

Exercise

Exercise
  • Build your Nuxt app with the multi-stage Dockerfile from the questions and run it with docker run -p 3000:3000, overriding one NUXT_ variable.
  • In a local cluster (kind or minikube), deploy it with a Deployment, a Service and an HPA, add readiness and liveness probes on /api/health, and watch a rolling update with kubectl rollout status.

Be able to say

Be able to say· How is a Nuxt app packaged and run in Kubernetes?

"A multi-stage Dockerfile builds the app with the full dependencies, then copies only .output into a slim Node image that runs node .output/server/index.mjs as a non-root user. The image is pushed with a SHA tag. In the cluster, a Deployment says which image, how many replicas, their CPU and memory requests and the health probes; a Service gives the pods one internal address behind the load balancer; an HPA adds pods when CPU passes the target. Configuration comes in as environment variables and secrets, so the same image runs everywhere."

Be able to say· How does Kubernetes keep the storefront available during deploys and spikes?

"Rolling updates start new pods before removing old ones, and readiness probes keep a pod out of rotation until it can actually serve, so there is no gap. Liveness probes restart a stuck process. The HPA watches utilisation against the requests and adds pods within a minute or so, and removes them slowly to avoid flapping. With Istio on top, a new version can get 10% of traffic first."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on this page and the section overview.