Cluster admins or operators often face unplanned node failures or planned maintenance. Kubernetes Eviction API offers a controlled path to terminate Pods while respecting policies. It uses the Eviction subresource to enforce PodDisruptionBudgets and terminationGracePeriodSeconds, ensuring safe, graceful Pod deletion. This article explains the Eviction API end to end, with examples.
TL;DR
- The API uses a subresource at
/pods/{name}/evictionto delete Pods under policy control. - Eviction honors
PodDisruptionBudgetandterminationGracePeriodSecondsto maintain application availability. - CLI and client-go support:
kubectl drainandclient.CoreV1().Evictions(). - Dry-run mode simulates eviction without actual deletion:
kubectl drain --dry-run. - Event-driven eviction enables automated remediation on metrics alerts (e.g., memory pressure) via custom controllers.
Eviction API Overview
The API acts like a policy-controlled delete. Instead of ordinary DELETE /api/v1/pods/{name}, clients POST an Eviction object to /api/v1/namespaces/{ns}/pods/{pod}/eviction. The server evaluates PodDisruptionBudgets, then marks the Pod for graceful termination. The subresource prevents bypassing disruption budgets.
Eviction Object Structure
apiVersion: policy/v1
kind: Eviction
metadata:
name: my-pod
namespace: default
deleteOptions:
gracePeriodSeconds: 30
deleteOptions.gracePeriodSeconds overrides the Pod’s terminationGracePeriodSeconds. If omitted, the default period applies.
Eviction vs. Delete
Eviction blocks if PDB limits would break availability. A normal delete ignores PDB. Eviction returns HTTP 429 if .status.disruptedPods exceeds .spec.maxUnavailable in any PodDisruptionBudget.
PodDisruptionBudget Integration
PDB defines minAvailable or maxUnavailable across matching Pods. Eviction API checks all PDBs that select the Pod. If eviction breaches any, the request fails with 429 Too Many Requests until conditions free up.
kubectl and API Eviction
KUBECTL_PLUGINS_PATH=~/.kube/plugins
kubectl drain node1 \
--ignore-daemonsets \
--delete-emptydir-data \
--timeout=5m
kubectl drain sequentially issues Eviction subresource calls for each Pod. It handles retry logic on 429, waits until PDB permits eviction, then proceeds.
Client-Go Example for API Eviction
import (
"context"
policyv1 "k8s.io/api/policy/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
func evictPod(clientset *kubernetes.Clientset, podName, ns string) error {
eviction := &policyv1.Eviction{
ObjectMeta: metav1.ObjectMeta{
Name: podName,
Namespace: ns,
},
}
return clientset.CoreV1().Pods(ns).
Evict(context.TODO(), eviction)
}
Dry-Run Evictions
Dry-run mode helps test PDB and eviction logic without actual Pod termination:
kubectl drain node1 --ignore-daemonsets --dry-run=client
Server side dry-run can use ?dryRun=All query param on the HTTP request.
Example Eviction Use Case
Operators can build custom controllers to watch for metrics alerts (e.g., disk pressure). On threshold breach, the controller issues Eviction API calls to relocate Pods automatically:
- Monitor Node metrics via Prometheus.
- On disk pressure event, call Eviction API for selected Pods.
- ReplicaSet recreates Pods on healthy nodes.
Security Context and Access Controls
Permission to evict requires create on policy/v1/evictions subresource. RBAC example:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-evictor
rules:
- apiGroups: ["policy"]
resources: ["pods/eviction"]
verbs: ["create"]
Handling Concurrent Evictions
The API server serializes eviction requests per Pod subresource. Parallel eviction attempts for the same Pod result in one success and one HTTP 404 or 409. Clients should handle retries and backoff.
References
Suggested Reading
PostHashID: 0f161d19344492245149b8045d3de330daa0811cac0a5988f5b8b089aa627e07
