Cloud-native means your application runs in a container. Kubernetes-native means your application was written from day one to participate in the Kubernetes control plane — it speaks Kubernetes, schedules with Kubernetes, fails and recovers with Kubernetes, and scales with Kubernetes.
The Distinction
The gap between the two isn’t deployment complexity. It’s whether the application was ever designed to know the platform exists.
Cloud-Native
Runs on Kubernetes
Container → scheduler → running
Containerised, 12-factor, CI/CD-deployed. Kubernetes is just the scheduler. The application has no awareness of the platform managing it. It could run on ECS, Nomad, or a bare VM with the same result.
Kubernetes-Native
Participates in Kubernetes
CRD → operator → primitive → platform
The application consumes operator-managed services through Kubernetes primitives only. It has no concept of infrastructure that isn’t expressed as a Kubernetes resource. Move it off-cluster and it cannot function — because the cluster is the architecture.
The Specification
An application that satisfies all twelve is Kubernetes-native. Satisfying six is cloud-native with cluster awareness. Satisfying none is a container that happens to run on Kubernetes.
Primary endpoint for writes. Replica endpoint for reads. Wired from day one, not retrofitted when performance becomes a problem.
Credentials arrive via projected volumes written by the operator. No static config files. Rotation happens without a restart.
Readiness reflects actual application state — database reachable, caches warm, downstream dependencies healthy. Not just TCP port open.
CPU requests and limits derived from profiling. Memory limits set above the measured working set. Never guessed, never left at defaults.
The application ships its own PodDisruptionBudget. It declares how much disruption it can survive — the cluster operator doesn’t guess.
Replicas never share a node. Topology spread constraints distribute across zones. Defined in the deployment, not the runbook.
Init containers verify operator CRD readiness before the main container starts. No sleep hacks. No race conditions on first boot.
Pool size = (CPU cores × 2) + effective spindle count. Separate pools for read and write paths. Pre-warmed on startup.
Exposes /metrics in Prometheus format natively. Emits structured logs with trace IDs. Publishes Kubernetes Events for significant state changes.
Catches SIGTERM, drains in-flight requests, closes database connections cleanly, exits 0. Readiness probe goes negative before the process stops.
Exposes the metric KEDA needs to scale it. Scale-to-zero cold start is tested and documented. Autoscaling is not an afterthought.
The application knows its own criticality. PriorityClass is defined and assigned. The scheduler knows what to evict first under pressure.
The Standard
If your application can be operated by writing kubectl apply against a CRD and the platform handles the rest — with no manual runbooks, no SSH, no static credentials — that is a Kubernetes-native application.
Cătălin Lichi
Founder, Sugau Pty Ltd — Bare-metal Kubernetes operator & platform engineer
The Go implementation patterns underpinning this work follow the ardanlabs/service architecture introduced by Bill Kennedy. His approach to building production Go services for Kubernetes shaped the application layer described here.
Every application we deliver satisfies all twelve criteria — on bare metal, in a NEXTDC cage, or in an air-gapped data centre. Not as a bonus. As a baseline.