When you begin with Kubernetes, Deployments seem like the catch-all tool for pretty much everything. You provide a Pod specification, define the number of replicas, and Kubernetes makes certain that the desired number of your Pods are active. It's easy, solid, and powerful.
But there's one thing that commonly catches people out, and that's the concept of binding Persistent Volumes (PVs) to Deployments directly. It makes intuitive sense on the surface: "I require storage, my Pod needs to be run reliably, why not simply mount a PVC into my Deployment?"
The issue is - this introduces subtle but very real problems in production. The hack runs smoothly - until the first failure, when everything collapses like dominoes. Let's break it down step by step.
Why Deployments and Volumes Don't Play Well Together?
- Deployments Assume Statelessness: Deployments are made for workloads with interchangeable Pods. If one of them dies, Kubernetes launches another somewhere in the cluster, and your application doesn't miss a beat.
But the instant you deploy a PVC (Persistent Volume Claim) to a Deployment, you're adding state to something that presumes statelessness. The Pod isn't really replaceable anymore, because the volume can be bound to a particular node or disk. - PVCs and Node Affinity: Most of the PVs, such as cloud disk providers (AWS, Azure, and GCP), are most probably zonal resources without geo-redundancy. In other words, they can only be attached to nodes in a particular zone, and sometimes to a particular node. Frequently, this zone specification is also a demand of the projects.
Accordingly, the system may fail to mount the storage on the new node if the pod having the PVC gets migrated. - When a Single Pod Gets Stuck, It Affects the Entire Deployment: If any pod gets frozen over volume attachment, Kubernetes takes that pod’s deployment as “in progress.”
In the same way, deployment automation tools like Argo CD or Flux presume that the pod is “in progress” and mark the deployment as Progressing, never Synced.
This implies your whole release pipeline can be blocked just because one Pod cannot mount its volume.
An Actual Incident: The Prometheus Pod in Stuck State Due to Volume Attachment
While working on other issues in the Kubernetes workspace, I personally ran into this problem.
The nightmare of every Kubernetes developer and admin,
- Prometheus was set up to use a Persistent Volume Claim (PVC).
- The PVC was a zonal disk that had node affinity (able to mount to a particular node).
- That node frequently went into NotReady state due to resource pressure.
Here’s what happened every time the node went down:
- Kubernetes tried to terminate the Prometheus Pod running on that node.
- A new Pod was going to be replaced on another node.
- As the disk was still attached to the hung Pod in Terminating, PVC could not be attached to the new Pod.
- Along with the following errors, the new Pod remained stuck in ContainerCreating:
Multi-attach error for volume "pvc-xyz": Volume is currently in use by pod prometheus-abc123.
The Impact on the Entire Cluster:
The problem was not only restricted to Prometheus. The consequences had extensive impacts on the cluster:
- The New Relic DaemonSet on that node also started malfunctioning. While the node kept flapping, the agent’s ability to report metrics became delayed, creating monitoring blind spots.
- Argo CD forever displayed the Prometheus release as Progressing instead of Synced. The rollout never reconciled completely, as Kubernetes was unable to cleanly kill the hung Pod.
To sum it all up, we were in the wreckage of the past storms:
- Prometheus monitoring was affected.
- Observability through New Relic was partially broken.
- GitOps workflows within Argo CD hung.
- All due to a volume attached to a Pod within a Deployment, which ideally shouldn't be there in the first place.
What to Do Instead?
If you really do need persistent storage for an application, Kubernetes already has a better construct for that:
Use a StatefulSet rather than a Deployment
StatefulSets target applications needing consistent identifiers and persistent storage.
Each replica receives its own PVC, and Pods are controlled in an ordered, predictable fashion. Prometheus, Elasticsearch, MySQL, Kafka - all of these stateful workloads must be run as StatefulSets.
The Practical Takeaway
- Stateless workloads belong in Deployments.
- PVCs + Deployments = Pod scheduling issues, stuck rollouts, blocked releases.
- In production, these problems don't remain localized - they propagate throughout your ecosystem, impacting monitoring, GitOps, and availability.