Utility to detect stale resources in Kubernetes clusters based on local manifests
Go to file
renovate[bot] 06d01045e9 module: update rope to ~1.10.0 2023-09-28 12:09:18 +02:00
.github ci: update actions/checkout action to v4 2023-09-07 08:51:37 +02:00
e2e ci: ignore kube-dns events in default namespace 2021-10-21 14:52:40 +02:00
.editorconfig module: add editorconfig 2020-08-14 11:38:35 +02:00
.gitignore module: adopt Poetry dependency manager 2020-08-08 23:18:09 +02:00
.pylintrc module: add formatting and linting configuration 2019-12-16 12:53:24 +01:00
LICENSE Fiat lux 2019-12-16 09:15:02 +01:00
Makefile ci: add e2e tests using kind + k8s 2020-08-21 16:41:33 +02:00
README.md ci: use github actions for simply CI 2019-12-16 12:54:03 +01:00
kube-stale-resources.py module: add request timeouts to fix lint warning 2022-09-01 12:31:09 +02:00
mypy.ini module: use type hints and validate with mypy 2019-12-19 17:36:35 +01:00
pyproject.toml module: update rope to ~1.10.0 2023-09-28 12:09:18 +02:00



Build Status

This is a utility to detect stale resources in Kubernetes clusters between resources from YAML manifests supplied via local file or stdin (target state) and a Kubernetes cluster (live state). All resources that exist in the live state but not in the target state are considered stale as they deviate from the intended state of the Kubernetes cluster (closed world assumption). It is intended as a complement to kubectl diff.

Using a blacklist you can ignore resources from the live state from the comparison so they are not considered stale even though they do not exist in the given target state. This is useful when those resources are created by Kubernetes itself (e.g. the kubernetes service in the default namespace), managed by the Kubernetes cluster provider or another tool outside the scope.

A use case for kube-stale-resources is using it alongside kubectl diff on locally present YAML manifests so kubectl diff can detect newly created Kubernetes resources and changes to those resources and kube-stale-resources can alert the user on stale resources that should be deleted from the cluster.


  • currently only works on namespaced resources
  • currently requires explicit metadata.namespace field even for resources in default namespace
  • requires unauthenticated HTTP(S) access to Kubernetes apiserver, e.g. via kubectl proxy
  • only accounts for apiVersion deprecations up until Kubernetes 1.16


You need Python 3.8 or higher.

Assuming you have a properly setup .kube/config (e.g. using minikube after a successful minikube start) running:

kubectl proxy &

# ignore minikube resources
cat <<EOF > blacklist.txt

# orderly created resource using YAML manifest in e.g. git
cat <<EOF > version-controlled-resources.yml
apiVersion: v1
kind: Service
  name: foo
  namespace: default
  type: ClusterIP
    - port: 80
      name: http
      targetPort: 80
    app: foo
kubectl apply -f version-controlled-resources.yml

# on-the-fly created resource using imperative command
kubectl create service clusterip bar --tcp='8080:8080'

cat version-controlled-resources.yml | python kube-stale-resources.py -f - --blacklist blacklist.txt

This should yield a similar output to as we ignored what minikube sets up by default (e.g. the whole kubernetes-dashboard namespace):

Reading blacklist file blacklist.txt...
Retrieving target state...
Retrieving live state from http://localhost:8001...
Live dynamic configmaps that are not in target (stale):
.. 0 entries

Live resources w/o dynamic configmaps that are not in target (stale):
.. 1 entries

Run python kube-stale-resources.py -h for full list of options.


Example blacklist file for a cluster on GKE that also uses cert-manager:



In general a blacklist file contains one regular expression per line that are matched against a string of format <namespace-name>:<apiVersion>:<kind>:<resource-name> for each resource.


kube-stale-resources is licensed under the Apache License, Version 2.0. See LICENSE for more information