:eyes: monitor & detect crashes in your Kubernetes(K8s) cluster instantly
๐ New to Kubernetes? No problem.
kwatch watches your cluster 24/7. When something fails, it tells you what broke and why โ with the error reason, diagnostic hints, logs, and events โ straight to your team chat.
โจ 60 seconds to install. No backend. No dashboards. No YAML spaghetti.
๐ง What is kwatch?
kwatch is like a smart friend for your Kubernetes cluster:
- ๐ฅ Something crashes โ you get a message that says why (not just "pod is broken")
- ๐ Smart about noise โ groups related issues into a single notification, ignores flapping
- ๐ง Optional AI that reads the logs and tells you what's likely wrong
- โก Works in under a minute โ just one command and a config file
๐ kwatch vs the scary stuff
| | โจ kwatch | ๐ฐ DIY Prometheus + Alertmanager | ๐ธ Heavy SaaS | |---|---|---|---| | โฑ๏ธ Setup time | ~5 minutes | hours of YAML | agent + backend setup | | ๐ฆ Size | ~20 MB single binary | whole monitoring stack | per-node agents + cloud costs | | ๐ฌ Alerts | Self-explaining ("OOMKilled โ raise memory limit") | Rule-defined message | Depends on configuration | | ๐๏ธ Storage | None (stateless) | Prometheus TSDB | Full retention (costly) | | ๐ Learning curve | One ConfigMap | PromQL + alert rules | Platform-specific DSL |
๐จ Before vs After
| Raw kubectl output ๐คท | kwatch tells you ๐ก | |---|---| | CrashLoopBackOff | ๐จ OOMKilled (memory limit: 512Mi) โ try raising limits.memory ยท here are the logs + events | | Error | ๐จ HTTP probe failing on :8080/healthz (exit 137) โ container ran out of memory |
โก๏ธ 60-second install
๐ฆ Helm (easiest ๐)
helm repo add kwatch https://kwatch.dev/charts
helm install [RELEASE_NAME] kwatch/kwatch --namespace kwatch --create-namespace --version 0.11.0
More details in the chart docs
๐ kubectl
curl -L https://raw.githubusercontent.com/abahmed/kwatch/v0.11.0/deploy/config.yaml -o config.yaml
โ๏ธ Edit config.yaml with your Slack/Discord/email webhook
kubectl apply -f config.yaml
kubectl apply -f https://raw.githubusercontent.com/abahmed/kwatch/v0.11.0/deploy/deploy.yaml
๐ฏ What does it catch?
Every monitor below is on by default โ zero config needed:
| Signal | Default | What you get | |--------|---------|-------------| | ๐ฅ Pod crashes (CrashLoop, OOM, ImagePull, Error) | โ
on | Container state + previous logs + events โ tells you why | | โณ Pending pods (stuck Unschedulable) | โ
on | Alerts after 300s stuck; includes scheduling delay in hint | | ๐ฏ Scheduling delay diagnostics | โ
on | Prepends "unschedulable for XmYs" duration to Unschedulable hints | | ๐ฅ๏ธ Node issues (NotReady, Disk/Memory pressure) | โ
on | Per-condition severity | | ๐พ PVC running out of space | โ
on | Warn at 80%, critical at 90% | | โ Failed Jobs | โ
on | JobFailed / JobSuspended | | ๐ Stuck rollouts | โ
on | ProgressDeadlineExceeded โ deployment didn't finish | | ๐ฆ Deployment unavailable | โ
on | DeploymentUnavailable โ unavailable replicas for rolloutMonitor.sustainedMinutes consecutive minutes | | ๐ก DaemonSet pods not running | โ
on | Unavailable pods detected | | โฐ CronJob suspended or missing runs | โ
on | Not scheduled in 24h? Alert. | | ๐ HPA stuck at max replicas | โ
on | After 20 minutes sustained | | ๐ Service endpoint health | โ
on | Detects endpoints with zero ready addresses | | ๐งฉ Admission webhook backends | โ
on | Alerts when a webhook's backing service has no ready endpoints | | ๐๏ธ Control-plane component health | โ
on | Detects broken control-plane pods (apiserver, scheduler, etc.) | | ๐งฉ StatefulSet unavailable | โ
on | StsUnavailable โ pods not ready for statefulSetMonitor.sustainedMinutes minutes | | ๐ PDB blocking disruptions | โ
on | PdbViolation โ PodDisruptionBudget has disruptionsAllowed=0 and unhealthy pods | | ๐ญ Node overcommit prediction | โ
on | NodeResourceHigh/Critical โ warning at 2ร, critical at 4ร CPU/mem overcommit | | ๐ฅ OOM pattern detection | โ
on | OOMRepeating โ 3+ OOM kills in 60-minute sliding window flags potential memory leak | | ๐ Ingress backend health | โ
on | Alerts when ingress backend services have no ready endpoints | | ๐ง NetworkPolicy over-restriction | โ
on | Detects policies that may block all ingress traffic | | ๐ TLS certs expiring | โ off | Enable if you want cert expiry warnings | | ๐ง Context-aware intelligence (dependency analysis) | โ
on | Links incidents to root causes โ unhealthy nodes, bad rollouts, misconfigured ConfigMaps/Secrets | | ๐ Mass failure detection | โ
on | Detects when 30%+ of dependents sharing a node/configmap/secret fail simultaneously |
โ TLS is the only one off โ everything else just works out of the box.
๐ง Context-aware intelligence
kwatch builds a dependency graph of your cluster from pod informers โ mapping pods to their nodes, owners (Deployments/StatefulSets/DaemonSets), Services, PVCs, and referenced ConfigMaps/Secrets. When an incident fires, the insight engine analyzes it against the graph and answers:
- What likely caused this? โ unhealthy node, failed rollout, or misconfigured resources (ConfigMap, Secret, PVC)
- What's the impact? โ how many pods, services, or dependents are affected
- Recent changes? โ correlated changes on the same resource or namespace
Mass failure detection
The correlation engine periodically scans all active incidents for shared dependencies. If more than 30% of dependents sharing a node, ConfigMap, Secret, or PVC are in failure, a mass failure alert fires. The threshold is dynamic โ computed per dependency based on the current scope. Mass failures automatically resolve when the underlying incidents clear.
๐ค AI-powered troubleshooting (optional, off by default)
kwatch ships with built-in AI (runs inside your cluster โ zero data leaves). It is disabled by default; set enabled: true to use it:
llm:
enabled: false # โ off by default!
When a crash happens, the AI reads the logs and tells you the most likely cause and what to do next. Like having a senior SRE on-call with you.
๐ Architecture note: AI is available for linux/amd64 and linux/arm64 only. It does not supportarm/v6orarm/v7(the main kwatch image supports all four).
โ๏ธ Configuration (simple)
๐ง General
| Parameter | What it does | |:---|---| | maxRecentLogLines | How many log lines to include in alerts (default: 50) | | resyncSeconds | Check for problems periodically (0 = only on events, recommended) | | workers | How many parallel workers (default: 1, raise for big clusters) | | namespaces | ๐ฝ Limit to specific namespaces, or use !kube-system to exclude | | reasons | ๐ฝ Only alert on specific reasons, or exclude some with ! | | ignoreFailedGracefulShutdown | โ
Skip containers killed during graceful shutdown (default: true) | | ignoreDisruptionTerminations | โ
Skip pods evicted during node drains (default: true) | | runbooks | ๐ Add links to your runbooks per error reason | | llm.enabled | ๐ค AI enrichment (default: false) | | containerRestartThreshold | Alert if a container restarts this many times (0 = off) | | reportStartupBaseline | ๐ Send one startup summary of pre-existing issues (default: true) |
๐ฝ Filter by namespace
# Watch only these namespaces
namespaces:
- default
- production
Or exclude some (can't mix both)
namespaces:
- !kube-system
- !monitoring
๐ฝ Filter by reason
# Only these reasons trigger alerts
reasons:
- CrashLoopBackOff
- ImagePullBackOff
Or exclude some
reasons:
- !Started
- !Killing
๐ฑ App settings
| Parameter | What it does | |:---|---| | app.proxyURL | ๐ Proxy for outgoing HTTP requests | | app.clusterName | ๐ท๏ธ Name shown in alerts so you know which cluster | | app.disableStartupMessage | Silence the "kwatch is alive" welcome message | | app.logFormatter | Log format: text (default) or json | | includeEvents | ๐ Include K8s events in alerts (default: true) | | includeLogs | ๐ Include container logs in alerts (default: true) |
๐ Health checks
| Parameter | What it does | |:---|---| | healthCheck.enabled | โ
Health endpoints (default: true) | | healthCheck.port | Port to serve health on (default: 8060) | | healthCheck.pprof | ๐ฌ Go profiling endpoints (default: false) | | healthCheck.diagnostics | ๐ฉบ Extra endpoints: /incidents, /test-alert, /deadletters |
Endpoints:
GET /healthzโ โ LivenessGET /readyzโ โ ReadinessGET /healthโ{"status": "ok"}GET /incidentsโ ๐ All active incidents (requiresdiagnostics: true)POST /test-alertโ ๐ค Send a test alert (requiresdiagnostics: true)GET /deadlettersโ ๐ Recent delivery failures (requiresdiagnostics: true)
๐ Upgrader
| Parameter | What it does | |:---|---| | upgrader.disableUpdateCheck | ๐ Don't check for new kwatch versions |
๐ Monitors
๐พ PVC Monitor โ disk space alerts
| Parameter | What it does | |:---|---| | pvcMonitor.enabled | โ
Monitor disk usage (default: true) | | pvcMonitor.interval | Check every N minutes (default: 5) | | pvcMonitor.threshold | โ ๏ธ Warn at this % (default: 80) | | pvcMonitor.criticalThreshold | ๐จ Critical at this % (default: 90) | | pvcMonitor.clearThreshold | โ
Resolve below this % (default: 75) |
๐ฅ๏ธ Node Monitor
| Parameter | What it does | |:---|---| | nodeMonitor.enabled | โ
Watch for node problems (default: true) |
Catches: NotReady, Unknown, MemoryPressure, DiskPressure, PIDPressure, NetworkUnavailable.
๐ Rollout Monitor
| Parameter | What it does | |:---|---| | rolloutMonitor.enabled | โ
Watch for stuck deployments (default: true) | | rolloutMonitor.sustainedMinutes | โฑ๏ธ Minutes of unavailability before alerting (default: 2) |
๐ก DaemonSet Monitor
| Parameter | What it does | |:---|---| | daemonSetMonitor.enabled | โ
Watch for unavailable DaemonSet pods (default: true) |
๐งโ๐ผ Job Monitor
| Parameter | What it does | |:---|---| | jobMonitor.enabled | โ
Watch for failed/suspended Jobs (default: true) |
โฐ CronJob Monitor
| Parameter | What it does | |:---|---| | cronJobMonitor.enabled | โ
Watch for suspended CronJobs or missed schedules (default: true) |
๐ HPA Monitor
| Parameter | What it does | |:---|---| | hpaMonitor.enabled | โ
Watch HPAs stuck at max replicas (default: true) | | hpaMonitor.sustainedMinutes | โฑ๏ธ How long before alerting (default: 20 min) |
๐ Heartbeat Monitor (dead man's switch)
| Parameter | What it does | |:---|---| | heartbeatMonitor.enabled | Send pings to a health-check URL (default: false) | | heartbeatMonitor.interval | โฑ๏ธ Seconds between pings (default: 300) | | heartbeatMonitor.url | ๐ External URL (e.g. Healthchecks.io) |
If kwatch stops or crashes, the external monitor stops getting pings and pages you. ๐
๐ TLS Certificate Monitor
| Parameter | What it does | |:---|---| | tlsMonitor.enabled | ๐ Watch for expiring certs (default: false) | | tlsMonitor.threshold | ๐
Days before warning (default: 30) | | tlsMonitor.criticalThreshold | ๐จ Days before critical (default: 3) |
๐ Service Endpoint Monitor
| Parameter | What it does | |:---|---| | serviceMonitor.enabled | ๐ Watch for services with zero ready endpoints (default: true) |
Detects when a Service's backing Endpoints object has zero ready addresses, indicating no healthy pods are available to serve traffic. Includes a 60-second debounce to avoid flapping during rolling updates or brief endpoint transitions.
๐งฉ Admission Webhook Monitor
| Parameter | What it does | |:---|---| | admissionWebhookMonitor.enabled | ๐งฉ Watch for webhooks with unreachable backends (default: true) |
Monitors MutatingWebhookConfiguration and ValidatingWebhookConfiguration resources. Alerts when a webhook's backing service has no ready endpoints, meaning admission requests may fail or timeout.
๐๏ธ Control-Plane Monitor
| Parameter | What it does | |:---|---| | controlPlaneMonitor.enabled | ๐๏ธ Watch for broken control-plane components (default: true) |
Detects container issues (CrashLoopBackOff, Error, OOMKilled, etc.) in control-plane pods (kube-apiserver, kube-scheduler, kube-controller-manager, etcd, kube-proxy, coredns). Runs a dedicated sweep at startup to catch pre-existing failures.
๐ Ingress Backend Monitor
| Parameter | What it does | |:---|---| | ingressMonitor.enabled | ๐ Watch for ingress backends with no ready endpoints (default: true) |
Alerts when an Ingress rule references a backend service that has zero ready endpoints, meaning traffic to that host/path would return an error.
๐ง Network Policy Monitor
| Parameter | What it does | |:---|---| | networkPolicyMonitor.enabled | ๐ง Detect overly restrictive network policies (default: true) |
Detects NetworkPolicy resources that deny all ingress traffic (no ingress rules defined). Helps identify policies that may unintentionally block legitimate traffic.
๐งฉ StatefulSet Monitor
| Parameter | What it does | |:---|---| | statefulSetMonitor.enabled | โ
Watch for unavailable StatefulSet pods (default: true) | | statefulSetMonitor.sustainedMinutes | โฑ๏ธ Minutes of unavailability before alerting, plus 15-minute rollout grace (default: 5) |
Monitors StatefulSets where readyReplicas < replicas for a sustained period, with a 15-minute grace window during rollouts to avoid alerting mid-update.
๐ PDB Monitor
| Parameter | What it does | |:---|---| | pdbMonitor.enabled | โ
Watch for PDBs blocking voluntary disruptions (default: true) | | pdbMonitor.sustainedMinutes | โฑ๏ธ Minutes of blocking before alerting (default: 5) |
Alerts when a PodDisruptionBudget has disruptionsAllowed=0 and currentHealthy < desiredHealthy, meaning voluntary disruptions (rollouts, node drains) are blocked.
๐ญ Node Resource Monitor
| Parameter | What it does | |:---|---| | nodeResourceMonitor.enabled | โ
Check node overcommit levels (default: true) | | nodeResourceMonitor.intervalSeconds | โฑ๏ธ How often to check (default: 300) | | nodeResourceMonitor.cpuWarning | โ ๏ธ CPU overcommit ratio for warning (default: 2.0) | | nodeResourceMonitor.cpuCritical | ๐จ CPU overcommit ratio for critical (default: 4.0) | | nodeResourceMonitor.memWarning | โ ๏ธ Memory overcommit ratio for warning (default: 2.0) | | nodeResourceMonitor.memCritical | ๐จ Memory overcommit ratio for critical (default: 4.0) |
Periodically computes the ratio of pod resource requests vs node allocatable for CPU and memory. Data is purely in-memory โ no TSDB or persistent storage needed.
๐ฅ OOM Pattern Monitor
| Parameter | What it does | |:---|---| | oomMonitor.enabled | โ
Track repeating OOMs (default: true) | | oomMonitor.threshold | ๐ข OOM count within window to flag (default: 3) | | oomMonitor.windowMinutes | โฑ๏ธ Sliding window in minutes (default: 60) |
Tracks OOMKilled events per container in a sliding window. When the threshold is exceeded, the reason changes from OOMKilled to OOMRepeating with a hint suggesting a potential memory leak.
๐ฏ Scheduling Delay Diagnostics
| Parameter | What it does | |:---|---| | scheduleMonitor.enabled | โ
Compute unschedulable delay (default: true) |
When a pod is stuck Unschedulable, computes now - PodScheduled.LastTransitionTime and prepends the delay to the hint (e.g., "unschedulable for 5m30s โ ...").
โณ Pending Pod Threshold โ alert after N seconds stuck in Pending (default: 300s)
๐ฏ Severity
| Parameter | What it does | |:---|---| | severityByOwnerKind | Set severity per resource type, e.g. StatefulSet: "high" |
Defaults: StatefulSet โ ๐ด high, everything else โ ๐ก normal
๐ Silences โ stop the noise
silences:
- namespaces: ["kube-system", "monitoring"]
- reasons: ["BackOff"]
- podNamePatterns: ["my-fancy-pod-.*"]
๐ซ Inhibition โ no double alerts
| Parameter | What it does | |:---|---| | inhibition.nodeSuppressesPods | โ
Don't alert on pod issues if the node itself is down (default: true) |
๐ Custom message templates
templates:
CrashLoopBackOff: "{{.Incident.Name}} โ {{.Action}} โ {{.Incident.Hint}}"
๐ง Correlation โ smart incident grouping
| Parameter | What it does | |:---|---| | correlation.window | โฑ๏ธ Keep incidents in memory (default: 10 min) | | correlation.resolveHoldDown | โฑ๏ธ Wait before sending "resolved" (default: 30s) | | correlation.lifecycleInterval | โฑ๏ธ Lifecycle check frequency (default: 1 min) | | correlation.escalation.enabled | โ
Escalate severity on repeated crashes (default: true) | | correlation.escalation.tiers | ๐ Restart thresholds: [3, 10, 50] | | correlation.renotify.maxPerIncident | ๐ Max re-alerts per incident (default: 3) |
๐งน Smart Grouping โ coalesce duplicate notifications
| Parameter | What it does | |:---|---| | smartGrouping.windowSeconds | โฑ Grouping window in seconds (default: 60). Set to 0 to disable. |
kwatch groups related incidents by the dimension that best captures each failure type's root cause. For example, OOMKilled and probe failures group by owner+namespace, node conditions group by node (not pod errors on the same node), image pull errors group by image (or globally for rate limits), and CrashLoopBackOff with a matching log signature bridges across owners. Each group notification shows affected pods, owners, nodes, or images depending on scope, with overflow counting above 1,000 entries. After a group notification is sent, the same condition will not re-notify until the underlying incident is resolved and re-occurs, preventing periodic flooding.
๐ CRD โ live config changes
| Parameter | What it does | |:---|---| | crd.enabled | Watch KwatchConfig CRs for live config updates (default: false) |
apiVersion: kwatch.abahmed.dev/v1alpha1
kind: KwatchConfig
metadata:
name: kwatch-config
namespace: kwatch
spec:
maxRecentLogLines: 100
silences:
- namespaces: ["kube-system"]
๐ Alert providers
๐ฌ Slack
Webhook mode: | Parameter | What it does | |:---|---| | alert.slack.webhook | ๐ Slack webhook URL | | alert.slack.channel | ๐ข Override channel | | alert.slack.title | โ๏ธ Custom title | | alert.slack.text | โ๏ธ Custom text | | alert.slack.compact | ๐ Single-line mode |
Bot Token mode: | Parameter | What it does | |:---|---| | alert.slack.token | ๐ Bot token (xoxb-...) | | alert.slack.channel | ๐ข Channel to post to | | alert.slack.title | โ๏ธ Custom title | | alert.slack.text | โ๏ธ Custom text | | alert.slack.compact | ๐ Single-line mode |
Compact mode:
alert: slack: webhook: "https://hooks.slack.com/..." compact: true
๐ก Pro tip: When using bot token mode, alerts become threaded conversations โ root message on first alert, updates as replies. Clean and organized! ๐งน
๐ฎ Provider Routing & Retry
alert:
slack:
webhook: "<url>"
routes:
- namespaces: ["production"]
severities: ["high", "critical"]
retry:
maxAttempts: 3
delay: 5s
Need a backup? Set a fallback:
alert: slack: webhook: "<url>" fallback: "pagerduty" # ๐ tries PagerDuty if Slack fails retry: maxAttempts: 3
๐ฌ Discord
| Parameter | What it does | |:---|---| | alert.discord.webhook | ๐ Discord webhook URL | | alert.discord.title | โ๏ธ Custom title | | alert.discord.text | โ๏ธ Custom text |
๐ง Email
| Parameter | What it does | |:---|---| | alert.email.from | ๐ค From address | | alert.email.password | ๐ From password | | alert.email.host | ๐ฅ๏ธ SMTP host | | alert.email.port | ๐ SMTP port | | alert.email.to | ๐ฅ Receiver email |
๐จ PagerDuty
| Parameter | What it does | |:---|---| | alert.pagerduty.integrationKey | ๐ PagerDuty integration key |
โ๏ธ Telegram
| Parameter | What it does | |:---|---| | alert.telegram.token | ๐ Bot token | | alert.telegram.chatId | ๐ฌ Chat ID |
๐ผ Microsoft Teams
| Parameter | What it does | |:---|---| | alert.teams.webhook | ๐ Webhook URL | | alert.teams.title | โ๏ธ Custom title | | alert.teams.text | โ๏ธ Custom text |
๐ Rocket Chat
| Parameter | What it does | |:---|---| | alert.rocketchat.webhook | ๐ Webhook URL | | alert.rocketchat.text | โ๏ธ Custom text |
๐ Mattermost
| Parameter | What it does | |:---|---| | alert.mattermost.webhook | ๐ Webhook URL | | alert.mattermost.title | โ๏ธ Custom title | | alert.mattermost.text | โ๏ธ Custom text |
๐ Opsgenie
| Parameter | What it does | |:---|---| | alert.opsgenie.apiKey | ๐ API Key | | alert.opsgenie.title | โ๏ธ Custom title | | alert.opsgenie.text | โ๏ธ Custom text |
๐๏ธ Matrix
| Parameter | What it does | |:---|---| | alert.matrix.homeServer | ๐ฅ๏ธ HomeServer URL | | alert.matrix.accessToken | ๐ Access token | | alert.matrix.internalRoomID | ๐ Room ID | | alert.matrix.title | โ๏ธ Custom title | | alert.matrix.text | โ๏ธ Custom text |
๐ DingTalk
| Parameter | What it does | |:---|---| | alert.dingtalk.accessToken | ๐ Access token | | alert.dingtalk.secret | ๐ Signing secret | | alert.dingtalk.title | โ๏ธ Custom title |
๐ฆ FeiShu
| Parameter | What it does | |:---|---| | alert.feishu.webhook | ๐ Webhook URL | | alert.feishu.title | โ๏ธ Custom title |
๐ก๏ธ Zenduty
| Parameter | What it does | |:---|---| | alert.zenduty.integrationKey | ๐ Integration Key | | alert.zenduty.alertType | ๐ท๏ธ Alert type (default: critical) |
๐ฌ Google Chat
| Parameter | What it does | |:---|---| | alert.googlechat.webhook | ๐ Webhook URL | | alert.googlechat.text | โ๏ธ Custom text |
๐ Custom Webhook
| Parameter | What it does | |:---|---| | alert.webhook.url | ๐ Webhook URL | | alert.webhook.headers | ๐ Custom headers | | alert.webhook.basicAuth | ๐ Username + password |
๐ ๏ธ CLI commands
| Command | What it does | |:---|---| | kwatch | โถ๏ธ Run the main monitor | | kwatch --version | โน๏ธ Print version | | kwatch lint | โ
Validate your config | | kwatch lint --strict | โ
โ
Strict check (catches typos!) | | kwatch lint --check | โ
โ
โ
Validate + test provider credentials | | kwatch replay < events.jsonl | ๐ฌ Replay past events to test |
๐งน Clean up
kubectl delete -f https://raw.githubusercontent.com/abahmed/kwatch/v0.11.0/deploy/config.yaml
kubectl delete -f https://raw.githubusercontent.com/abahmed/kwatch/v0.11.0/deploy/deploy.yaml
๐ Not a monitoring platform โ and proud of it! ๐
kwatch is not a metrics collector, dashboard, or observability backend. No TSDB, no dashboards, no log storage, no query language. kwatch is the alarm โ your existing tools are the archive.
Need full observability? Pair kwatch with Prometheus + Grafana for metrics, or Loki for logs. kwatch handles the one thing a dashboard cannot: telling you something broke right now. โฐ
๐ Contribute & Support
- โญ Give us a star โ it really helps!
- ๐ก Suggest features
- ๐ Report bugs
๐ Who uses kwatch?
kwatch is trusted by:
Want to add your company? Open an issue!
๐ป Contributors
โญ๏ธ Stargazers
๐ Get in touch
Questions? Suggestions? Chat with us on Discord โ we're friendly! ๐
โ ๏ธ License
kwatch is MIT Licensed โ use it, fork it, share it! ๐

