How to Set Up Kubernetes Monitoring with Zabbix

How to Set Up Kubernetes Monitoring with Zabbix

Zabbix has been a mainstay of infrastructure monitoring for over two decades, and while Kubernetes-native tooling like Prometheus tends to dominate the conversation, plenty of teams already run Zabbix across their entire infrastructure estate and want Kubernetes folded into that same system rather than run in parallel. In this guide, I’ll cover how to set up Kubernetes monitoring with Zabbix, using its official Helm charts and native Kubernetes monitoring template.

Why Zabbix for Kubernetes

Zabbix gives you a single, mature monitoring platform across bare metal, VMs, network devices, and now Kubernetes — with built-in alerting, escalation policies, and a long history of enterprise reliability. If your infrastructure team already has Zabbix triggers, templates, and dashboards built out, extending that same system into Kubernetes avoids maintaining two separate alerting stacks with two separate on-call workflows.

Kubernetes Architecture Context

Zabbix’s Kubernetes integration works differently from the typical Prometheus pull model. It uses:

  • Zabbix Agent 2, deployed as a DaemonSet, collecting node and container-level metrics.
  • Zabbix Java Gateway or the newer native Kubernetes monitoring feature, which polls the Kubernetes API server directly for cluster-level object state (Pods, Deployments, Nodes) — conceptually similar to what kube-state-metrics does for Prometheus.
  • Zabbix Server, the central component that stores collected data, evaluates triggers, and fires alerts.
  • Zabbix Proxy (optional), useful in multi-cluster setups to reduce load on the central server and handle network segmentation.

Step 1: Deploy Zabbix Components via Helm

helm repo add zabbix-community https://zabbix-community.github.io/helm-zabbix
helm repo update

Install the Zabbix server, web frontend, and database:

helm install zabbix zabbix-community/zabbix -n zabbix --create-namespace \
  --set zabbixServer.enabled=true \
  --set zabbixWeb.enabled=true \
  --set mysql.enabled=true

Check the deployment:

kubectl get pods -n zabbix

Step 2: Deploy the Zabbix Agent as a DaemonSet

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: zabbix-agent
  namespace: zabbix
spec:
  selector:
    matchLabels:
      app: zabbix-agent
  template:
    metadata:
      labels:
        app: zabbix-agent
    spec:
      hostNetwork: true
      hostPID: true
      containers:
        - name: zabbix-agent2
          image: zabbix/zabbix-agent2:6.4-alpine-latest
          env:
            - name: ZBX_SERVER_HOST
              value: "zabbix-server.zabbix.svc.cluster.local"
            - name: ZBX_HOSTNAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
          volumeMounts:
            - name: proc
              mountPath: /host/proc
              readOnly: true
            - name: sys
              mountPath: /host/sys
              readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys
kubectl apply -f zabbix-agent-daemonset.yaml

Step 3: Configure Native Kubernetes Monitoring

Modern Zabbix (6.4+) includes a native Kubernetes monitoring data collection feature that polls the API server directly, rather than requiring a separate exporter. Configure it through the Zabbix frontend:

  1. Data collection → Kubernetes → Create Kubernetes cluster
  2. Provide the API server URL and a ServiceAccount token with read-only access (see RBAC below).
  3. Zabbix auto-discovers Nodes, Pods, and Deployments and creates corresponding hosts and items automatically.

Create the ServiceAccount and token Zabbix will authenticate with:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: zabbix-monitoring
  namespace: zabbix
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: zabbix-monitoring-role
rules:
  - apiGroups: [""]
    resources: ["pods", "nodes", "namespaces", "events", "services"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets", "daemonsets", "replicasets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: zabbix-monitoring-binding
subjects:
  - kind: ServiceAccount
    name: zabbix-monitoring
    namespace: zabbix
roleRef:
  kind: ClusterRole
  name: zabbix-monitoring-role
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Secret
metadata:
  name: zabbix-monitoring-token
  namespace: zabbix
  annotations:
    kubernetes.io/service-account.name: zabbix-monitoring
type: kubernetes.io/service-account-token

Retrieve the token to paste into the Zabbix frontend:

kubectl get secret zabbix-monitoring-token -n zabbix -o jsonpath='{.data.token}' | base64 -d

Note this uses read-only verbs (get, list, watch) exclusively — Zabbix never needs write access to your cluster to monitor it.

Step 4: Install the Kubernetes Metrics Server (Required for Resource Metrics)

Zabbix’s metrics.k8s.io polling depends on the standard Kubernetes metrics-server being present in the cluster:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl get deployment metrics-server -n kube-system

Without this, Zabbix can still see object state (Pod phase, restart counts) but won’t get live CPU/memory utilization numbers.

Step 5: Import the Kubernetes Nodes/Pods Template

Zabbix ships official templates (“Kubernetes nodes by HTTP”, “Kubernetes cluster state”) that map directly onto the discovered objects. Import via Data collection → Templates → Import, then link them to the auto-discovered host group for your cluster.

Step 6: Build Triggers and Alerts

Common triggers worth configuring immediately:

  • Node NotReady condition sustained for more than 2 minutes.
  • Pod CrashLoopBackOff state detected.
  • Deployment’s available replicas below desired replicas for more than 5 minutes.
  • PersistentVolumeClaim usage above 85%.

Example trigger expression (Zabbix trigger syntax) for a Pod restart spike:

last(/Kubernetes cluster state/kube.pod.restarts.rate[production,api-server])>5

Set escalation actions in Alerts → Actions → Trigger actions to route these into whatever notification channel your team already uses in Zabbix (email, Slack integration, PagerDuty via webhook).

Dashboards

Zabbix’s built-in dashboard widgets (Graph, Problems, Top hosts) can be composed into a Kubernetes overview dashboard without needing a separate tool like Grafana, though Zabbix also supports a Grafana data source plugin if your team prefers that visualization layer while keeping Zabbix as the collection/alerting backend.

Security Considerations

  • Scope the monitoring ServiceAccount strictly to read-only verbs, as shown above — never grant create/update/delete.
  • Run the Zabbix Agent DaemonSet with only the host mounts it actually needs (/proc, /sys read-only); avoid unnecessary hostPID/hostNetwork if your monitoring needs don’t require them.
  • Store the Kubernetes API token as a Kubernetes Secret and restrict who can read it via RBAC on the zabbix namespace itself.
  • If exposing the Zabbix web frontend externally, put it behind proper authentication (LDAP/SAML integration, which Zabbix supports natively) and TLS.

Performance and Scaling

  • For large clusters (500+ nodes), consider a Zabbix Proxy per cluster or region to offload polling and reduce load on the central Zabbix Server, syncing data asynchronously.
  • Tune the discovery interval for Kubernetes objects — very frequent polling on large clusters can generate significant load on both the API server and Zabbix’s own database.
  • Archive/trend older historical data according to your retention needs; Zabbix’s housekeeping settings control this independently of Kubernetes.

Common Mistakes

  • Forgetting to deploy metrics-server, then wondering why CPU/memory graphs are empty even though Pod state monitoring works fine.
  • Granting the monitoring ServiceAccount write permissions “just in case” — unnecessary and a real security risk if the Zabbix server itself is ever compromised.
  • Not setting resource limits on the Zabbix Agent DaemonSet, letting it compete with actual workloads for node resources.
  • Over-polling large clusters without a Proxy tier, causing API server load spikes that show up as false “Node NotReady” alerts.

Summary

Zabbix can serve as a genuine, capable Kubernetes monitoring solution — not just a bolt-on — by combining its DaemonSet-based agent for node/container metrics with its native Kubernetes API polling for cluster object state. The setup takes a bit more manual RBAC and template work than a Prometheus stack, but it pays off if you’re consolidating Kubernetes into an observability platform your team already trusts and knows how to operate at scale.

References

Total
7
Shares

Leave a Reply

Previous Post
How to Use ResourceQuotas in Kubernetes

How to Use ResourceQuotas in Kubernetes

Next Post
How to Implement StatefulSets with Helm in Kubernetes

How to Implement StatefulSets with Helm in Kubernetes

Related Posts