This guide explains how Stellar-K8s uses Kubernetes PodDisruptionBudgets (PDBs) to protect the operator and validator nodes during voluntary disruptions such as node drains, cluster upgrades, and maintenance operations.
A PodDisruptionBudget is a Kubernetes API object that limits the number of pods of a replicated application that can be down simultaneously due to voluntary disruptions. Voluntary disruptions include:
- Node drains (e.g.,
kubectl drain) - Cluster upgrades
- Node pool resizing
- Manual pod evictions
Involuntary disruptions (like node failures, network partitions, or pod crashes) are NOT affected by PDBs.
Stellar validator nodes and the operator itself are critical infrastructure components. During cluster maintenance:
- Validator nodes need to maintain quorum to continue processing transactions
- The operator needs to stay available to manage StellarNode resources
- History archives should remain accessible for node synchronization
Without PDBs, a cluster administrator could accidentally evict too many validators at once, potentially causing:
- Quorum loss - Network cannot reach consensus
- Transaction delays - Reduced capacity to process transactions
- Synchronization issues - Nodes cannot fetch historical data
By default, Stellar-K8s installs a PDB for the operator with:
podDisruptionBudget:
enabled: true
minAvailable: 1This ensures that at least one operator pod remains available during voluntary disruptions.
You can configure PDBs in your values.yaml or via Helm --set flags.
Ensures a minimum number of pods are always available:
podDisruptionBudget:
enabled: true
minAvailable: 1 # At least 1 pod must be runningOr as a percentage:
podDisruptionBudget:
enabled: true
minAvailable: "50%" # At least 50% of pods must be runningAllows a maximum number of pods to be unavailable:
podDisruptionBudget:
enabled: true
minAvailable: null # Clear minAvailable
maxUnavailable: 1 # At most 1 pod can be downFor validator nodes, maxUnavailable: 1 is the recommended default because it:
- Allows maintenance to proceed one node at a time
- Prevents simultaneous eviction of multiple validators
- Maintains network quorum during upgrades
To disable PDB creation (not recommended for production):
podDisruptionBudget:
enabled: falsehelm install stellar-operator charts/stellar-operator \
--namespace stellar-system \
--create-namespacehelm install stellar-operator charts/stellar-operator \
--namespace stellar-system \
--create-namespace \
--set podDisruptionBudget.minAvailable=null \
--set podDisruptionBudget.maxUnavailable=1helm install stellar-operator charts/stellar-operator \
--namespace stellar-system \
--create-namespace \
--set podDisruptionBudget.minAvailable="50%"Create my-values.yaml:
podDisruptionBudget:
enabled: true
maxUnavailable: 1Then install:
helm install stellar-operator charts/stellar-operator \
--namespace stellar-system \
--create-namespace \
-f my-values.yamlkubectl get pdb -n stellar-systemExample output:
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
stellar-operator 1 N/A 0 5m
kubectl describe pdb stellar-operator -n stellar-systemThis shows:
- Current pod count
- Desired minimum available
- How many disruptions are currently allowed
- Recent events
If ALLOWED DISRUPTIONS is 0, voluntary disruptions are blocked:
kubectl get pdb stellar-operator -n stellar-system -o jsonpath='{.status.disruptionsAllowed}'When draining a node for maintenance:
-
Check PDB status first:
kubectl get pdb -n stellar-system kubectl describe pdb stellar-operator -n stellar-system
-
If disruptions are allowed (ALLOWED DISRUPTIONS > 0):
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
-
If disruptions are blocked (ALLOWED DISRUPTIONS = 0):
- Wait for natural pod turnover, OR
- Temporarily increase replica count, OR
- Temporarily disable the PDB (see below)
In emergency situations where you MUST drain a node despite PDB restrictions:
Option A: Temporarily Delete the PDB
# Save PDB configuration for later
kubectl get pdb stellar-operator -n stellar-system -o yaml > pdb-backup.yaml
# Delete the PDB
kubectl delete pdb stellar-operator -n stellar-system
# Perform emergency maintenance
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --force
# Restore the PDB
kubectl apply -f pdb-backup.yamlOption B: Temporarily Modify the PDB
# Set maxUnavailable to a higher value temporarily
kubectl patch pdb stellar-operator -n stellar-system \
--type='json' \
-p='[{"op": "add", "path": "/spec/maxUnavailable", "value": 999}]'
# Perform maintenance
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# Restore original configuration
kubectl patch pdb stellar-operator -n stellar-system \
--type='json' \
-p='[{"op": "remove", "path": "/spec/maxUnavailable"}]'Option C: Force Drain (Use with Extreme Caution)
# This ignores PDBs and can cause service disruption
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --force --pod-selector=""- Validator quorum loss
- Transaction processing interruption
- Network instability
Only use in genuine emergencies.
For rolling cluster upgrades:
-
Ensure operator has appropriate PDB:
kubectl get pdb -n stellar-system
-
Upgrade node pool one node at a time:
# For each node in the pool: kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data # Wait for node to be ready again kubectl uncordon <node-name>
-
Monitor PDB status between nodes:
kubectl get pdb -n stellar-system kubectl get pods -n stellar-system -o wide
- Keep PDBs enabled in production environments
- Use
maxUnavailable: 1for validator workloads - Monitor PDB status before planned maintenance
- Plan maintenance windows with PDB constraints in mind
- Use percentage-based PDBs for large deployments (e.g.,
minAvailable: "75%") - Test PDB behavior in non-production environments first
- Don't disable PDBs in production without a compelling reason
- Don't force drains unless it's a genuine emergency
- Don't set
minAvailableequal to total replicas (blocks all maintenance) - Don't ignore PDB warnings during maintenance
- Don't set both
minAvailableandmaxUnavailablesimultaneously (use one or the other)
Symptom: kubectl drain hangs or reports "Cannot evict pod"
Solution:
- Check PDB status:
kubectl describe pdb <pdb-name> - Wait for pods to become ready naturally, OR
- Temporarily increase replica count, OR
- Follow emergency procedures above
Symptom: Pod remains in Terminating state despite node drain
Possible causes:
- PDB blocking eviction
- Finalizers preventing deletion
- Volume detachment delays
Solution:
# Check what's blocking
kubectl describe pod <pod-name>
# Check PDB status
kubectl get pdb
# If PDB is the issue, follow emergency procedures aboveMeaning: No voluntary disruptions are currently permitted
Common causes:
- Not enough healthy replicas
- Pod readiness issues
- PDB configuration too restrictive
Solution:
- Check pod health:
kubectl get pods -n stellar-system - Fix any unhealthy pods
- Wait for pods to become ready
- Consider adjusting PDB if configuration is too restrictive
Monitor these PDB-related metrics:
# Current disruptions allowed
kube_poddisruptionbudget_status_disruptions_allowed{namespace="stellar-system"}
# Expected disruptions desired
kube_poddisruptionbudget_status_desired_healthy{namespace="stellar-system"}
# Current pod count
kube_poddisruptionbudget_status_current_healthy{namespace="stellar-system"}
# Alert if no disruptions allowed for extended period
kube_poddisruptionbudget_status_disruptions_allowed{namespace="stellar-system"} == 0
# Alert if PDB is blocking all disruptions for more than 1 hour
- alert: PDBBlockingDisruptions
expr: kube_poddisruptionbudget_status_disruptions_allowed{namespace="stellar-system"} == 0
for: 1h
labels:
severity: warning
annotations:
summary: "PDB blocking voluntary disruptions"
description: "PDB {{ $labels.poddisruptionbudget }} has 0 allowed disruptions for more than 1 hour"- Kubernetes PodDisruptionBudget Documentation
- Stellar-K8s Quick Start
- Stellar-K8s Resource Limits
- Stellar-K8s Health Checks
For issues or questions about PDB configuration:
- Open an issue on GitHub
- Check existing documentation in the
docs/directory - Review the FMEA for failure mode analysis
Last verified: 2026-07-27 (cleanup wave #1187/#1189/#1190/#1191).