---
topic: dev-practices
author: Crashtech Editorial
published: Nov 14, 2026 · read: 4 min
---

Ten Kubernetes Design Patterns: Probes, Sidecars, Init Containers and Operators

Foundational, structural, behavioural and higher-level Kubernetes patterns, each with the problem it solves and a manifest snippet you can adapt.

– –

Kubernetes gives you a lot of verbs and very little advice. The patterns below are the advice: ten recurring shapes that the platform was built to support, and what each protects you from.

Foundational: let the platform manage you

  1. 1. Health probes

    Expose endpoints the platform can ask. Liveness decides when to restart a stuck container. Readiness decides whether to send traffic. Startup protects slow-starting apps from being killed too soon.

  2. 2. Predictable demands

    Declare CPU and memory requests and limits, and dependencies like config and volumes. The scheduler cannot place what it cannot size.

  3. 3. Automated placement

    Describe where Pods may or must run (node selectors, affinity, taints and tolerations, topology spread) and let the scheduler do the rest. Spread replicas across zones so one failure does not take them all.

containers:
  - name: api
    image: example/api:1.4.2
    resources:
      requests: { cpu: "250m", memory: "256Mi" }
      limits:   { memory: "512Mi" }
    readinessProbe:
      httpGet: { path: /ready, port: 8080 }
      periodSeconds: 5
    livenessProbe:
      httpGet: { path: /healthz, port: 8080 }
      periodSeconds: 10
      failureThreshold: 3
The probe mistake that causes outages

Pointing liveness at a check that depends on the database. When the database blips, every Pod fails liveness, Kubernetes restarts them all at once, and a small problem becomes a full outage. Keep liveness about the process itself, put dependency checks in readiness.

Structural: organising containers in a Pod

4. Init container do this first, then start
Runs to completion before the app containers start. Use it to wait for a dependency, run a migration, fetch configuration or set file permissions, with its own image and tools that never ship in the app.
5. Sidecar extend without modifying
A helper that lives and dies with the app in the same Pod, sharing network and volumes. Log shippers, service-mesh proxies, config reloaders. Native sidecar support lets it start before the app and stay until the app exits.

The rule of thumb: if the helper must share localhost or a volume with the app and share its lifecycle, it is a sidecar. If it is a separate service with its own scaling, it is a separate Deployment.

Behavioural: matching the workload

6. Batch job run to completion
Jobs and CronJobs for finite, isolated work. Set retry limits and a deadline, and make the work idempotent so a retry is safe.
7. Stateful service identity and storage
StatefulSets give each replica a stable name and its own persistent volume, for databases and queues. Ordered rollout, and slower, because identity matters.
8. Service discovery find without hardcoding
A Service gives a stable name and virtual IP in front of changing Pods, with DNS. Callers use the name, never a Pod address.
Advertisement

Higher-level: encoding operations

  1. 9. Controller

    Kubernetes is a set of control loops. You declare the desired state, a controller watches actual state and acts until they match. This reconcile loop is why a crashed Pod simply comes back. Understanding it explains most “why did it do that” moments.

  2. 10. Operator

    A custom controller plus a custom resource that captures a human operator’s knowledge: how to deploy a database cluster, take a backup, promote a replica, upgrade without data loss. You declare “a three-node Postgres, version 16” and the operator makes and keeps it so.

Operators are powerful and costly to write. Adopt an existing, well-maintained one for stateful software before building your own, and do not build one for a stateless service that a Deployment already handles.

Which pattern for which problem

ProblemPattern
Traffic hits a container that is still startingReadiness probe
A hung process never recoversLiveness probe
One Pod starves its neighboursRequests and limits
All replicas land on one nodeSpread constraints, anti-affinity
App must wait for a database before startingInit container
Need log shipping or a proxy without changing the appSidecar
Nightly reportCronJob
Database needing stable identityStatefulSet, possibly an operator

Do

Give every workload requests, a readiness probe and at least two replicas spread across zones before you reach for anything advanced. Those three cover most production incidents.

Don't

Reach for operators, custom controllers or service meshes before the foundational patterns are in place. Advanced tooling on top of missing probes is complexity without resilience.

Takeaway

The ten patterns are really one idea at four levels: tell the platform enough about your workload (probes, demands, placement), organise containers by lifecycle (init, sidecar), match the controller to the workload type (job, stateful, service), and encode repeated operations as controllers. Start at the first level and move up only when a real problem demands it.

Advertisement

Frequently asked questions

What is the sidecar pattern in Kubernetes?

Running a helper container in the same Pod as your application container so they share network and storage. The helper adds capability, such as log shipping, proxying or certificate refresh, without changing the application image. Recent Kubernetes versions support sidecars that start before and outlive the main container.

What is the difference between a liveness and a readiness probe?

A liveness probe tells Kubernetes whether to restart a container that is stuck. A readiness probe tells it whether the container should receive traffic right now. A container can be alive but not ready, for example while warming a cache, and should be taken out of rotation without being killed.

When should I write an operator?

When running an application needs ongoing operational knowledge that you would otherwise do by hand, such as backups, failover, upgrades or scaling for a database. An operator encodes that knowledge in a controller. For stateless apps, plain Deployments are almost always enough.

Why declare resource requests and limits?

Requests tell the scheduler how much CPU and memory a Pod needs so it can place it well. Limits cap what it may use. Without them, one noisy Pod can starve neighbours, and the cluster cannot make good placement or eviction decisions.

Sources & further reading

/* Comments */