--- apiVersion: v1 kind: ServiceAccount metadata: name: pod-reaper namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pod-reaper rules: # Nodes - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"] # Pods - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch", "delete"] # Controllers (ownerRefs) - apiGroups: ["apps"] resources: - deployments - replicasets - statefulsets - daemonsets verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: pod-reaper roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: pod-reaper subjects: - kind: ServiceAccount name: pod-reaper namespace: kube-system --- apiVersion: apps/v1 kind: DaemonSet metadata: name: pod-reaper namespace: kube-system spec: selector: matchLabels: app: pod-reaper template: metadata: labels: app: pod-reaper spec: serviceAccountName: pod-reaper # 🔒 Do not schedule on NotReady nodes affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: Exists tolerations: # Control-plane nodes - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule # Required so it keeps running while other pods are evicted - key: node.kubernetes.io/not-ready operator: Exists effect: NoExecute - key: node.kubernetes.io/unreachable operator: Exists effect: NoExecute containers: - name: pod-reaper image: allardkrings/pod-reaper:1.0 imagePullPolicy: IfNotPresent env: - name: POD_REAPER_NOT_READY_GRACE value: "300" # seconds - name: POD_REAPER_DRY_RUN value: "false" # set true to simulate resources: requests: cpu: 10m memory: 32Mi limits: cpu: 100m memory: 128Mi securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 allowPrivilegeEscalation: false restartPolicy: Always