✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Workload Design Guidelines

Kubernetes Workload Design Guidelines provide best practices for scalable, reliable, and efficient application management in Kubernetes.

Kubernetes Workload Design Guidelines are the practical conventions for structuring an application's containers, pods, and processes to work well with Kubernetes's own execution model, covering single-responsibility containers, appropriate sidecar and init container usage, alignment with twelve-factor application principles, and common workload anti-patterns worth recognizing and avoiding.


Single Responsibility Per Container

One Process, One Concern

containers:
  - name: web
    image: myapp:1.0
  - name: log-shipper
    image: fluent-bit:latest

Structuring each container around a single, well-defined responsibility, the application process itself, a log-shipping sidecar, a metrics exporter, rather than bundling multiple unrelated processes into one container via a supervisor script, keeps each container independently restartable, independently scalable in its resource footprint, and independently replaceable without touching unrelated logic.

Container = One Responsibility

Appropriate Use of Sidecars and Init Containers

Sidecars for Ongoing, Coupled Auxiliary Behavior

containers:
  - name: app
    image: myapp:1.0
  - name: envoy-proxy
    image: envoyproxy/envoy:v1.28

A sidecar is appropriate for auxiliary behavior that must run continuously alongside the main container for the pod's entire lifetime, a service mesh proxy, a log or metrics forwarder, since the sidecar pattern couples the auxiliary container's lifecycle directly to the pod it accompanies.

Init Containers for Sequential, One-Time Setup

initContainers:
  - name: wait-for-db
    image: busybox
    command: ["sh", "-c", "until nc -z db 5432; do sleep 2; done"]

An init container is appropriate for setup work that must complete before the main container starts and does not need to run afterward, waiting for a dependency, fetching a configuration file, running a one-time migration; using an init container rather than embedding the same logic as a retry loop inside the main application keeps startup dependency logic outside the application's own runtime code.

Sidecar = Concurrent, Ongoing , Init = Sequential, One-Time

Alignment With Twelve-Factor Principles

Statelessness Where Genuinely Possible

Designing an application to keep no locally required state between requests, storing session data in an external cache rather than in-process memory, allows it to run as a simple, horizontally scalable Deployment rather than requiring the additional identity and volume complexity a StatefulSet introduces; reserving stateful workload patterns for the cases that genuinely require them, rather than defaulting to them out of habit, keeps the majority of an application's components simpler to operate.

Configuration Through Environment and Mounted Files

env:
  - name: LOG_LEVEL
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: LOG_LEVEL

Externalizing configuration through environment variables or mounted ConfigMap/Secret volumes, rather than baking environment-specific values directly into a container image, keeps a single built image portable and deployable unchanged across every environment, differing only in the configuration supplied at deploy time.

Logs to stdout/stderr

# application writes logs directly to stdout, no file-based logging

Writing logs directly to standard output and standard error, rather than to a file inside the container, is what makes a container's logs automatically collectible by the container runtime and any log-aggregation pipeline without requiring a sidecar to tail a log file or a volume mount solely for log storage.

Portability = Externalized Config + stdout/stderr Logging

Common Workload Anti-Patterns

The SSH-able, Manually-Managed Pod

A pod designed to be manually logged into and modified in place, installing packages interactively, editing files by hand, defeats the reproducibility and immutability that make containers valuable in the first place; any change needed should be encoded in the image build or the manifest and redeployed, not applied ad hoc inside a running container.

Cron Logic Implemented as a Sleep Loop

# anti-pattern
command: ["sh", "-c", "while true; do do_task.sh; sleep 86400; done"]
apiVersion: batch/v1
kind: CronJob
spec:
  schedule: "0 2 * * *"

Implementing a scheduled task as a long-running container with an internal sleep loop, rather than using a CronJob, forfeits Kubernetes's own scheduling, concurrency policy, retry, and history-tracking mechanisms in favor of a hand-rolled equivalent that must independently reimplement all of the reliability considerations already covered under batch reliability basics.

The Monolithic Pod Doing Everything

A single pod bundling an entire application's disparate concerns, web serving, background processing, scheduled tasks, into one container or one pod specification, prevents each concern from being independently scaled, independently restarted, or independently updated, and generally indicates the workload boundary was drawn around convenience of initial authoring rather than around actual operational and scaling characteristics.

Workload Boundary = f ( Independent Scaling Need )

Relationship to Best Practices Scope and the Broader Knowledge Base

Workload design guidelines are the foundational judgment layer this best practices area is built around: choosing the right container and pod structure, the right primitive type, and alignment with externalized, stateless, log-to-stdout application design is the starting point that determines whether every mechanism covered elsewhere in this knowledge base, reliability probes, autoscaling, packaging templates, extensibility patterns, can actually be applied cleanly, or must instead work around a workload structure that was never designed with Kubernetes's execution model in mind.

Pod app (main) proxy (sidecar)