Kubernetes monitoring

Watch your cluster from the Kubernetes API — not a Prometheus stack.

Bayqus reads your cluster the way kubectl does: it talks directly to the Kubernetes API and reacts to what's actually happening — a pod OOMKilled, a deployment stuck below its desired replicas, a node gone NotReady. One manifest deploys a single read-only agent; its findings ride the same outbound-only channel as the rest of your monitoring. No Prometheus, no scraping, no inbound port.

One kubectl apply · one pod Read-only RBAC Outbound only · no inbound
01 — How it connects

One manifest. One read-only agent. One device.

You deploy a single agent into its own namespace with one kubectl apply. It enrolls the whole cluster as a single device — identified by the UID of the kube-system namespace, so a pod restart never mints a duplicate — and opens one outbound TLS connection back to Bayqus. There is nothing to scrape and nothing to expose: the agent uses a client-go informer to watch the Kubernetes API in real time and pushes findings out the same channel your servers and PCs use.

STATE A

kubectl apply

One manifest creates a Namespace, a read-only ClusterRole, the token Secret and a single-replica Deployment.

STATE B

Enrolls

The agent registers the cluster as one device (kube-system UID = stable ID) and connects outbound over TLS 8884.

STATE C

Watches

A shared informer streams Events, Nodes, Pods and workloads; steady-state conditions are re-checked every 30s.

STATE D

Alerts

Problems are de-duplicated and pushed to your existing alert channels; recovery clears them.

02 — What it watches

The failures that page you, straight from the API.

The agent watches Warning events plus live object state, maps each finding to a severity, and de-duplicates so a flapping pod doesn't spam you. These severities are the defaults — each account can override the severity of any finding, or suppress a kind entirely, under Alerts → Rules → Event Alerts.

BandMeansTypical findings
CriticalWake someone upOOMKilled, CrashLoopBackOff, NodeNotReady, FailedCreatePodSandBox.
HighLook todayImagePullBackOff, a Deployment/StatefulSet/DaemonSet sustained below its desired replicas, Evicted pods, node DiskPressure / MemoryPressure / PIDPressure.
WarnGood to knowUnhealthy (failing probes), FailedMount, pods stuck Pending past the threshold.
InfoContextOther Warning events, plus optional "recovered" notices, kept for history and correlation.
The watch set is core Events, Nodes, Pods and apps workloads (Deployments, StatefulSets, DaemonSets). Scheduling and restart problems are read from live pod state — e.g. a pod Pending past 5 minutes — not from stale etcd events, so you're not re-alerted on issues that already resolved.
03 — Deploy, scope, and be told

One kubectl apply. Scope by namespace. Alerts where you already get them.

Deploy
Copy the command from your Clusters page and run it: one kubectl apply creates the Namespace, ServiceAccount, a read-only ClusterRole and binding, the enrollment-token Secret and a single Deployment (1 replica). Paste the token, apply, done.
Read-only by design
The ClusterRole grants get / list / watch on events, nodes, pods, namespaces and apps workloads, plus node metrics and kubelet stats for CPU, RAM and disk — and nothing else. No exec, no Secret reads, no write access anywhere in the cluster.
Namespace allowlist
By default it watches the whole cluster. Pick specific namespaces from the device's Monitored Namespaces and the agent narrows pod, workload and event signals to them — applied live, no redeploy. Node health and cluster CPU / RAM / disk are always monitored.
Health & inventory
Beyond alerts, the cluster reports CPU, RAM and disk utilisation and basic inventory — Kubernetes version, node count and distro — charted like any other device. CPU/RAM come from metrics-server, disk from each node's kubelet stats.
Alerting & noise control
Findings route through the same channels, policies and silences as the rest of Bayqus — Telegram, email, webhook, Slack. Repeats are de-duplicated per (kind, namespace, object) and only re-sent when the count climbs, so a CrashLoop doesn't flood you.
04 — Questions

The things people ask first.

Q. Do I need Prometheus or a metrics stack?

No. The cluster agent talks directly to the Kubernetes API with a client-go informer — it watches Events, Nodes, Pods and workloads and reacts to what actually happens. There's no Prometheus, no Grafana and no scrape config to maintain. Cluster CPU/RAM come from metrics-server when present, and disk from each node's kubelet stats.

Q. What access does it need?

A least-privilege, read-only ClusterRole: get/list/watch on events, nodes, pods, namespaces and apps workloads, plus node metrics and kubelet stats for CPU, RAM and disk. Nothing else — no write access, no exec into pods, and no reading your Secrets.

Q. Does it open any inbound ports?

No. A single pod opens one outbound TLS connection and pushes findings out over it. Nothing inbound is exposed, so a cluster behind NAT or a firewall is monitored exactly like everything else in Bayqus — the agent reaches out, nothing reaches in.

Q. Will a crash-looping pod flood my alerts?

No. Findings are de-duplicated per (kind, namespace, object): a new problem sends immediately, then only re-sends once per window or when its count climbs. Stale events replayed by the informer are age-gated out, and you get per-account rules to override a finding's severity or suppress a kind entirely.

Q. How is it priced?

A whole cluster enrolls as a single device — it counts as one device against your plan's limit, with no per-node or per-pod charge, so it fits any paid plan (Team at $5.99/mo and up). Larger fleets and long metric retention are covered by the Business tier.

Related reading

More on how it fits together

Point Bayqus at your cluster with one kubectl apply.

A single read-only agent, straight from the Kubernetes API — and the failures that page you land in the alert channels you already use.

Start free Talk to us

Verified against the cluster-agent contract (docs/cluster-agent.md · cluster-agent/collector.go) — 2026-08-01