# kubewatch: Kubernetes event notifications to Slack and eight other channels, minus the secret values

> kubewatch is a Go watcher that runs in a cluster, watches resources of the types you list, and posts the changes to Slack, Teams, Mattermost, SMTP, CloudEvents or a generic webhook. It is the official project, originally by Bitnami and now maintained by Robusta, and it redacts Secret values before any notification is built.

**robusta-dev/kubewatch** — Watch k8s events and trigger Handlers

- Repository: https://github.com/robusta-dev/kubewatch
- Stars: 801 · Forks: 106
- Language: Go
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/robusta-dev-kubewatch

## What the watcher does and who maintains it

kubewatch is a Kubernetes watcher that publishes notifications to collaboration hubs and notification channels. Run it in your cluster and you get event notifications through webhooks, and it watches the cluster for resource changes and notifies them through those webhooks.

The project is the official Kubewatch, originally by Bitnami, and is now maintained by Robusta.dev. The GoDoc badge and the module path still point at the Bitnami Labs repository, github.com/bitnami-labs/kubewatch, while the repository itself lives under robusta-dev.

The supported webhooks are listed in the usage output: slack, slackwebhook, msteams, hipchat, mattermost, flock, webhook, cloudevent and smtp. That list is a record of the project's history. HipChat and Flock are dead products and remain in the code, while cloudevent and smtp are the two that show the project has moved past chat and towards event buses and email.

The command line is small. The available commands are config, which modifies the kubewatch configuration, resource, which manages the resources to be watched, and version, which prints the version. The binary takes flags and subcommands in the usual cobra arrangement, and the help output is what the README reproduces.

The project is Apache-2.0 licensed, written in Go, with releases v2.16.1 in August 2026, v2.16.0 the day before and v2.15.0 in June 2026, and the last push to the repository was on 2026-10-06.

## Installing with Helm, and the values file that decides your noise level

The Helm route is a repository add followed by an install:

```console
helm repo add robusta https://robusta-charts.storage.googleapis.com && helm repo update
helm install kubewatch robusta/kubewatch --set='rbac.create=true,slack.channel=#YOUR_CHANNEL,slack.token=xoxb-YOUR_TOKEN,resourcesToWatch.pod=true,resourcesToWatch.daemonset=true'
```

The same installation can be done with a values file, and the README shows the full shape of one, including the rbac block with a create flag and customRoles entries that grant get, list and watch on a specific apiGroup, and the resourcesToWatch map:

```yaml
resourcesToWatch:
  deployment: false
  replicationcontroller: false
  replicaset: false
  daemonset: false
  services: true
  pod: true
  job: false
  node: false
  clusterrole: true
  clusterrolebinding: true
  serviceaccount: true
  persistentvolume: false
  namespace: false
  secret: false
  configmap: false
  ingress: false
  coreevent: false
  event: true
customresources:
  - group: monitoring.coreos.com
    version: v1
    resource: prometheusrules
```

That map is the whole configuration surface for what you get told about, and it is where the noise lives. The default set includes cluster roles, cluster role bindings and service accounts, which in a busy cluster generate a lot of events, and a values file that turns those off is the difference between a useful channel and one nobody reads.

The customresources block is the extension point, and it shows that kubewatch can watch any resource type, not just the built-in list, as long as you give the group, version and resource name. The example watches Prometheus rules from the monitoring.coreos.com group, and the customRoles entry in the rbac block grants the matching permissions.

Applying the file afterwards is the same as installing it:

```console
$ helm upgrade --install kubewatch robusta/kubewatch --values=values-file.yml
```

## The kubectl route and the sidecar arrangement

The alternative installation avoids Helm entirely and uses a ConfigMap to hold the configuration. An example is provided at kubewatch-configmap.yaml in the repository, and the reminder is to update the Slack channel and token parameters, with secrets as another option.

Creating the ConfigMap is a single apply:

```console
$ kubectl create -f kubewatch-configmap.yaml
```

Then you create the pod directly, or write your own deployment:

```console
$ kubectl create -f kubewatch.yaml
```

The deployment brings up a kubewatch container alongside a kubectl sidecar container, and the reason given is to reach the API server. That is an unusual arrangement and worth understanding, because it explains a constraint: the watcher is not a Deployment with a service account by default, it is a pod with a second container that talks to the cluster.

Once the pod is running you start seeing Kubernetes events in the configured Slack channel. To change what you get, you update the kubewatch ConfigMap and turn resources on and off, or configure any resource of your choosing with customresources.

RBAC gets its own section because the service account is a separate step. Kubernetes Engine clusters running 1.6 or higher introduced Role-Based Access Control, and the ServiceAccount has to be created for it to work:

```console
$ kubectl create -f kubewatch-service-account.yaml
```

If you cannot create it you need to be an admin first, and the GKE example given is a cluster role binding to cluster-admin for your own user:

```
$ kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=REPLACE_EMAIL_HERE
```

Then the service account is wired into the pod spec with serviceAccountName: kubewatch, which the README does with a sed insertion:

```console
$ sed -i '/spec:/a\ \ serviceAccountName: kubewatch' kubewatch.yaml
```

## Secret watching and what gets redacted

Secret watching is off by default, with secret: false in the resource configuration, and the documentation then describes what happens if you turn it on, in more detail than most projects would give.

When secret watching is enabled, kubewatch notifies on Secret creates, updates and deletes, but the secret values themselves never leave the process. The values under a Secret's data and stringData are replaced with a redaction marker before any notification is built. That applies to the previous version of the object too, which update notifications also carry, and it applies to Secrets reached through customresources rather than through the secret flag.

What is kept is the useful part. Key names, labels, annotations, the Secret's type and the rest of its metadata are preserved, so a notification still tells you which Secret changed and which of its keys were added or removed. It just does not tell you their values. For most purposes that is the whole point of watching Secrets, since the interesting event is that a credential rotated, not what the credential says.

The redaction happens before the notification is constructed rather than after, which is the right order. Handlers that serialize whole objects, and cloudevent is called out specifically, redact again on the bytes they are about to send. So there are two layers: the object is scrubbed as it enters the notification path, and a handler that forwards the raw object scrubs again on the way out.

That design is the main reason to consider turning secret watching on at all, and it is a change from what an unredacted watcher would do.

## Fine-grained filtering belongs to Robusta, not to kubewatch

The first section of the README is about fine-grained resource tracking, and it is where the project draws a boundary with its maintainer.

KubeWatch tracks all changes to Kubernetes resources of given types. If you need fine-grained filtering of which changes are forwarded, you can use KubeWatch in conjunction with Robusta, and the Robusta docs on change-tracking are the reference for the details. A diagram in the README shows the two options, with the flow that only uses KubeWatch in one colour and the flow that adds Robusta in the other.

That is a fair division. KubeWatch is a type-level filter, and it is deliberately simple: give it a list of resource types and it tells you about all changes to them. Anything narrower, by label, by field, by namespace, by any predicate, needs a layer that can evaluate a rule, which is what Robusta provides.

The practical consequence is a design decision about how many components you want. A team that wants a Slack channel showing pod and service changes runs one kubewatch pod and nothing else. A team that wants to be told when a specific annotation changes on a specific deployment in a specific namespace runs Robusta and keeps kubewatch underneath it. The cost of the second path is another component, and the benefit is that the notification volume becomes something you designed rather than something you tuned by turning off resource types.

## The image and the CVE wall of comments

The Dockerfile is the most unusual file in the repository, because its top half is a list of CVE identifiers grouped by the Go version each one requires.

The comments say that patching a set of CVEs requires Go 1.26.2, another set requires 1.26.4, another 1.26.5, and another 1.26.6. The builder stage is golang:1.26.6, which satisfies the highest requirement in the list. The second group of comments is about the runtime base image, where patching a further set requires glibc 2.44 provided by a chainguard bash base built after May 2026, and others require a libcrypto3 version, a libnghttp2 version, and a rebuild on a current latest base, with the instruction that the image must be rebuilt regularly, within thirty days, for the tag to stay clean even when nothing else changes.

That is an unusually honest record of what it takes to ship a Go binary in a container now. Rather than pinning a base image and hoping, the project tracks the minimum toolchain version each security fix demands and rebuilds on a rolling base.

The rest of the build is conventional. The builder adds the arm64 architecture, installs build-essential, copies the source into the GOPATH layout the old Makefile expects, and builds with CGO_ENABLED=0 and the architecture taken from dpkg, which is how one Dockerfile produces both amd64 and arm64 images. The final stage copies the binary onto a chainguard bash base, sets KW_CONFIG to the configuration directory, and sets the entrypoint to the binary.

## Where kubewatch is the wrong choice

The first limitation is the granularity, which is the same point as the Robusta section but from the other side. Every change to a watched type produces a notification, and a cluster with automatic pod restarts, node additions and controller churn will produce a lot of them. The only lever kubewatch gives you is turning resource types off, which is coarse. If your team needs a signal that fires ten times a day rather than a thousand times a day, kubewatch alone will not get you there.

The second is the operational shape. The default install is a pod with a kubectl sidecar rather than a proper Deployment with a service account, and the RBAC steps are manual, including a sed command to insert the service account name into the pod spec. That is workable for a demonstration and rough for a production install that has to survive a node drain, which is why the Helm chart exists and why the maintainer is also the company behind Robusta, the commercial product that sits on top of it.

The third is the elephant: this is a notification tool for cluster changes, and cluster change notifications are a solved problem that most platforms now cover. Kubernetes Events, the kubectl output, the cloud provider's own audit log and the chat integration in the platform console all give you some of this already. kubewatch earns its place when you want all resource types in one chat channel with a specific format and a specific filter, and you accept running a component with cluster read access to provide it.

The comparison with a simple kubectl get loop in cron is also worth making. That is what kubewatch was, and it is still the right answer if the event volume is low and the channel count is one.

## Conclusion

kubewatch fits a cluster operator who wants resource change notifications in a chat channel within a minute of a change, and who can run one pod with access to the API server. It does not fit a team that needs filtering by field, by label or by anything more specific than resource type, because that is the job Robusta does alongside it. Before deploying, decide which resource types to watch, since the default set is wide and the notification volume follows it, set the Slack channel and token in the values file rather than on the command line, and read the Secret redaction behaviour so you know what a notification will and will not tell you.

## FAQ

### What does kubewatch do and which notification channels does it support?

It is a Kubernetes watcher that runs in your cluster, tracks changes to the resource types you list, and publishes notifications. The supported webhooks are slack, slackwebhook, msteams, hipchat, mattermost, flock, webhook, cloudevent and smtp.

### How do I install kubewatch with Helm?

Add the chart repository with `helm repo add robusta https://robusta-charts.storage.googleapis.com && helm repo update`, then install with the rbac, slack and resourcesToWatch values, or point at a values file with `helm upgrade --install kubewatch robusta/kubewatch --values=values-file.yml`.

### What happens to secret values when kubewatch watches Secrets?

Secret watching is off by default. When enabled, the values under a Secret's data and stringData are replaced with a redaction marker before any notification is built, including the previous version carried in update notifications. Key names, labels, annotations, type and other metadata are kept, and handlers that serialize whole objects redact again on the bytes they send.

### Can kubewatch watch custom resources?

Yes. The resourcesToWatch map lists the built-in types, and a customresources block with a group, version and resource name adds any other type, with the example watching Prometheus rules from the monitoring.coreos.com group. The rbac customRoles block grants the matching get, list and watch permissions.

### Who maintains kubewatch and what is the relationship to Robusta?

It is the official Kubewatch project, originally by Bitnami and now maintained by Robusta.dev. The documentation points at Robusta for fine-grained filtering of which changes are forwarded, since KubeWatch itself filters at the level of resource type only.

## Sources

- [Issues](https://github.com/robusta-dev/kubewatch/issues)
- [License: Apache-2.0](https://github.com/robusta-dev/kubewatch/blob/master/LICENSE)
- [README](https://github.com/robusta-dev/kubewatch/blob/master/README.md)
- [Releases](https://github.com/robusta-dev/kubewatch/releases)
- [robusta-dev/kubewatch on GitHub](https://github.com/robusta-dev/kubewatch)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/robusta-dev-kubewatch
