Schedule icon
Commands icon
Docker icon
Script icon
If icon
SlackIncomingWebhook icon
Set icon

QoSWatch - Kubernetes missing requests/limits reporter

A Kestra blueprint that audits Kubernetes pods for missing CPU and memory requests or limits and reports the offenders on Slack, without spamming.

Categories
Infrastructure

How it works

  1. list_pods (io.kestra.plugin.scripts.shell.Commands) dumps the namespace's pods as JSON with kubectl.
  2. find_unlimited (io.kestra.plugin.scripts.python.Script) inspects every container's (and init container's) resources and lists exactly which of the four are missing: cpu request, memory request, cpu limit, memory limit. Pods with nothing set are flagged BestEffort; the rest Burstable. It compares against the KV state so only newly found offenders are reported.
  3. maybe_alert (io.kestra.plugin.core.flow.If) posts the Slack report only when there is someone new to name.
  4. save_state (io.kestra.plugin.core.kv.Set) writes back the current offender list. Fixed pods drop out on their own, so a redeployed-offending pod reports again, and steady-state reruns stay quiet.

What you get

  • A daily audit of which pods run without resource requests or limits, the ones Kubernetes evicts first under pressure.
  • Slack reports naming the pod, its QoS class, and exactly which requests/limits each container lacks.
  • No report spam: the KV-backed memory remembers who was already named.
  • Quiet runs when every pod declares its resources.

Who it's for

Anyone running workloads on Kubernetes who suspects half their pods have no limits set. Pairs with PodSecurityWatch as a prod-readiness series: this one covers resource hygiene, that one covers security posture.

Why orchestrate this with Kestra

kubectl get pods never told you which ones lack limits. As a flow it audits on a schedule, keeps every run's findings where you can audit them, and only bothers you when a new offender appears. Kestra holds the cluster credentials as secrets out of the YAML.

Prerequisites

  • A Kubernetes cluster with pods you can list.
  • A kubeconfig client certificate and key with permission to list pods in the target namespace.
  • Kestra with the Docker task runner available (used for the kubectl and Python steps).
  • A Slack Incoming Webhook URL.

Secrets

Secret What it is
CLIENT_CRT base64-encoded client certificate from your kubeconfig
CLIENT_KEY base64-encoded client key from your kubeconfig
MASTERURL base64-encoded Kubernetes API server URL, reachable from inside the Kestra container
SLACK_WEBHOOK base64-encoded Slack Incoming Webhook URL

In Kestra OSS, secrets come from environment variables prefixed with SECRET_ and must be base64-encoded. If the API URL uses 127.0.0.1 or localhost, replace it with host.docker.internal so the Kestra container can reach it.

Quick start

  1. Start Kestra with the secrets above as SECRET_ environment variables. If minikube restarted since your last run, regenerate SECRET_MASTERURL first: the API port changes on every minikube start.
  2. Import this flow and create two test pods: one bare kubectl run qos-bad --image=nginx, one with limits set. Run the flow: the Slack report names only qos-bad with its missing four.
  3. Run again: quiet, already reported.
  4. Delete qos-bad and run again: quiet, it dropped out of state.

How to extend

  • Fail the run instead of reporting by adding a Fail task when BestEffort pods exist in production namespaces.
  • Exclude system namespaces or specific workloads with a name/label filter in the Python step.
  • Track QoS class distribution over time by storing counts instead of names.
  • Combine with TopPodsWatch to correlate missing limits with actual high usage.

Inputs

Input Type Default What it does
namespace STRING default the namespace whose pods to audit
slack_webhook STRING (required) Incoming webhook URL of the Slack channel for the report

Links

Pitfalls

  • This flow deliberately never sets requests or limits for you. Guessing wrong causes OOMKills or CPU throttling in production; sizing resources is a human judgment call the report informs but does not make.
  • Completed or succeeded pods are skipped. Only Running and Pending pods are audited.
  • The flow is strictly read-only. It lists pods and reports; it never patches anything.
  • Minikube's API server port changes on every minikube start. Regenerate SECRET_MASTERURL and restart the Kestra container, or the kubectl step fails to connect.
See How

New to Kestra?

Use blueprints to kickstart your first workflows.