Kubernetes Watcher
The Kubernetes watcher discovers and monitors workloads running in Kubernetes clusters, reporting when newer image versions are available.
DeploymentStatefulSetDaemonSetCronJob
Prerequisites​
WUD must be able to reach the Kubernetes API server. Two modes are supported:
- In-cluster (default): WUD runs inside the cluster with an appropriate
ServiceAccount. - Out-of-cluster: provide a path to a
kubeconfigfile viaWUD_WATCHER_KUBERNETES_{name}_KUBECONFIG.
RBAC (In-Cluster Mode)​
When running WUD inside a Kubernetes cluster, configure the following RBAC resources so that WUD can read workloads, nodes, and pods:
apiVersion: v1
kind: ServiceAccount
metadata:
name: wud
namespace: wud
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: wud-reader
rules:
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets", "daemonsets"]
verbs: ["get", "list"]
- apiGroups: ["batch"]
resources: ["cronjobs"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["nodes", "pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: wud-reader-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: wud-reader
subjects:
- kind: ServiceAccount
name: wud
namespace: wud
Configuration Options​
CRON schedule for automatic checks
Random jitter in milliseconds applied to the CRON schedule
Path to a kubeconfig file. When omitted, in-cluster ServiceAccount is used.
Kubernetes namespace to watch. Empty means all namespaces.
Trigger a watch cycle immediately at startup
If true, all workloads are watched unless explicitly opted out
Default behavior for digest watching on non-semver images
Workload kinds to discover and monitor
Workload Annotations​
WUD supports annotations on Kubernetes workloads to fine-tune update discovery, filtering, and notifications:
| Annotation | Description | Example |
|---|---|---|
wud.getwud.io/watch | Opt-in or opt-out | "true" / "false" |
wud.getwud.io/tag.include | Regex to include tags | "^1\\.27\\..*" |
wud.getwud.io/tag.exclude | Regex to exclude tags | ".*-alpine" |
wud.getwud.io/tag.transform | Tag transform expression | "s/^v//" |
wud.getwud.io/watch.digest | Watch image digest | "true" |
wud.getwud.io/link.template | Link template | "`https://hub.docker.com/r/library/nginx/tags?name=${tag}`" |
wud.getwud.io/display.name | Friendly display name | "My Nginx" |
wud.getwud.io/display.icon | Iconify icon | "mdi:kubernetes" |
wud.getwud.io/trigger.include | Trigger include filter | "slack.*" |
wud.getwud.io/trigger.exclude | Trigger exclude filter | "email" |
wud.getwud.io/stack | Stack/group name (default: namespace) | "frontend" |
Per-container annotations (multi-container pods)​
Suffix annotations with the container name to target a specific container within a pod:
annotations:
wud.getwud.io/display.name.nginx: "My Nginx"
wud.getwud.io/display.name.sidecar: "My Sidecar"
wud.getwud.io/watch.digest.nginx: "true"
Examples​
- In-Cluster (default)
- Out-of-Cluster (kubeconfig)
- Deployment with annotations
WUD_WATCHER_KUBERNETES_MYCLUSTER_NAMESPACE=production
WUD_WATCHER_KUBERNETES_MYCLUSTER_WATCHBYDEFAULT=false
WUD_WATCHER_KUBERNETES_HOMELAB_KUBECONFIG=/home/wud/.kube/config
WUD_WATCHER_KUBERNETES_HOMELAB_NAMESPACE=default
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
namespace: production
annotations:
wud.getwud.io/watch: "true"
wud.getwud.io/tag.include: "^1\\.27\\..*"
wud.getwud.io/display.name: "My Nginx"
wud.getwud.io/display.icon: "mdi:nginx"
spec:
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.27.0
Container ID format​
WUD builds a unique ID for each watched container:
{namespace}_{kind}_{workloadName}_{containerName}
Example: production_deployment_my-nginx_nginx