What you will take away
- Kubernetes is justified by many services and many teams, not by container use.
- Requests and limits set wrongly cause most of the mystery instability.
- Cluster upgrades are the recurring cost people forget to budget for.
When it is the right tool
Kubernetes is worth its complexity when you are running many services, deployed by several teams, that need consistent networking, scheduling, scaling and rollout behaviour. It gives you one operational model rather than a different deployment story per service.
For three containers and one team, a managed container service does the same job with a fraction of the surface area. Choosing Kubernetes there buys you a control plane to learn, upgrade and debug in exchange for capabilities you will not use.
Resource requests and limits, which cause most mysteries
Requests decide where a pod is scheduled; limits decide when it is throttled or killed. Set requests too low and the node becomes overcommitted and everything slows down together. Set limits too low and the process is terminated under load, which surfaces as an intermittent failure nobody can reproduce.
Measure real usage under load, set requests near the steady state and limits with genuine headroom, and revisit after traffic changes. Most of the "Kubernetes is unstable" reports we investigate are this, and nothing else.
Nearly every unexplained restart in a young cluster is a memory limit that was guessed rather than measured.
Scaling that reacts to the right signal
- Horizontal pod autoscaling on a metric that reflects the actual bottleneck - queue depth or request concurrency, often not CPU.
- Cluster autoscaling so nodes follow pods, with a small buffer to absorb bursts while nodes start.
- Pod disruption budgets so scaling and maintenance cannot take the last healthy replica.
- Readiness probes that mean ready - a probe that returns healthy before dependencies are up will send traffic into failures.
Zero-downtime deployment in practice
A rolling update is only zero-downtime if the application cooperates: graceful shutdown that finishes in-flight requests, a readiness probe that reflects real dependency health, and database migrations that are backwards compatible with the version still running.
That last point is where most teams get caught. Deploy schema changes in expand-and-contract phases - add the column, deploy code that writes both, backfill, then remove the old path in a later release.
The recurring cost nobody budgets
Kubernetes releases regularly and support windows are short, so an upgrade is a scheduled event several times a year, along with the add-ons that trail behind it. Teams that treat this as an interruption end up on an unsupported version with a much larger jump to make.
Put upgrades on the roadmap, run them on a non-production cluster first, and keep the add-on list deliberately small. A managed control plane removes a good deal of this work and is almost always the right choice unless you have a specific reason to run your own.