Kubernetes is a powerful platform for running scalable, distributed applications, but its complexity makes monitoring challenging. Therefore, without proper visibility, issues can go unnoticed and degrade performance and availability.
Now, enter Zabbix, Grafana, and Skedler (ZGS) together, they form a powerful trio that provides an end-to-end observability and reporting solution for Kubernetes.
Why Monitor Kubernetes with Zabbix?
Zabbix is a powerful open-source monitoring solution for infrastructure, including Kubernetes clusters. It helps teams:
- Detect pod failures and service slowdowns
- Send real-time alerts
- Maintain system uptime and performance
However, Zabbix’s native dashboards and reporting features are limited. At this point, Grafana and Skedler step in.
The Ideal Stack: Zabbix + Grafana + Skedler (ZGS Stack)
Zabbix for Data Collection
Zabbix monitors pods, nodes, and services with deep metrics.

Grafana for Visualization
Grafana complements Zabbix by adding:
- Interactive dashboards
- Custom visualizations per stakeholder
- Unified views from multiple sources (Zabbix, Prometheus, MySQL, etc.)

Skedler for Reporting
Grafana OSS lacks built-in reporting. Skedler bridges that gap with:
- Scheduled PDF, Excel, or HTML reports
- No coding required
- Role-based access
- Audit-ready reports for compliance
Get Started with Skedler for
Automated Kubernetes Monitoring
Get Started Today

Therefore, this stack equips you with full observability and automated insights.
Kubernetes Monitoring Architecture with Zabbix, Grafana, and Skedler (ZGS)

Step-by-Step: Kubernetes Monitoring Setup
In this article, we’ll guide you through monitoring a Kubernetes cluster using Zabbix. Then, we’ll explore how to query relevant metrics and build powerful visualizations in Grafana. Step by step, you’ll learn how to collect and process Kubernetes data, integrate it into Grafana for interactive dashboards, and finally, use Skedler to automate report generation.
As a result, you’ll end up with a full-fledged monitoring and reporting solution that leverages Zabbix, Grafana, and Skedler for clear and actionable insights into your Kubernetes environment.
Install Zabbix Monitoring for Kubernetes
1. Prerequisites
- kubectl installed
- helm installed
- Docker installed
- Kubernetes cluster running (example: minikube)
2. Download the Zabbix Helm repository
Add the Zabbix chart repository to your local Helm setup with the following commands:
cd ~
git clone https://git.zabbix.com/scm/zt/kubernetes-helm.git
cd kubernetes-helm
3. Zabbix Configuration Setup
Accordingly, based on your setup, a few configurations may be necessary—usually just setting environment variables for the Zabbix Agent and Proxy
nano $kubernetes-helm/values.yaml
By default, the Zabbix Helm chart deploys the Zabbix Proxy with SQLite3, which works fine for testing or small setups. However, the Zabbix Server does not support SQLite3; it requires a full-featured SQL database like MySQL, MariaDB, or PostgreSQL.
If you want the proxy to work with a Zabbix Server that uses a SQL database, it’s best to update the Zabbix Proxy configuration to use MySQL or PostgreSQL as well.
In this setup, I’m using MySQL as the backend database for Zabbix. Instead of deploying MySQL within the same Helm release as the Zabbix Proxy or Server, I’ve opted to run MySQL as a standalone deployment. As a result, this offers better separation of concerns and greater flexibility in managing database persistence and scaling independently.
Below is the “zabbix-mysql-server.yaml” manifest used to deploy the MySQL service and deployment in the Kubernetes cluster:
apiVersion: v1
kind: Service
metadata:
name: zabbix-mysql-server
spec:
selector:
app: zabbix-mysql
ports:
- port: 3306
targetPort: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zabbix-mysql
spec:
replicas: 1
selector:
matchLabels:
app: zabbix-mysql
template:
metadata:
labels:
app: zabbix-mysql
spec:
containers:
- name: mysql
image: mysql:8.0.30
env:
- name: MYSQL_ROOT_PASSWORD
value: root
- name: MYSQL_DATABASE
value: zabbix
ports:
- containerPort: 3306
Zabbix Proxy
Additionally, I’ve configured the Zabbix Proxy to connect to this external MySQL service by updating their database connection details according.
zabbixProxy:
enabled: true
serviceAccount:
create: false
name: zabbix-service-account
containerSecurityContext: {}
resources: {}
image:
repository: zabbix/zabbix-proxy-mysql
tag: alpine-7.0-latest
pullPolicy: IfNotPresent
pullSecrets: []
env:
- name: DB_SERVER_HOST
value: zabbix-mysql-server
- name: MYSQL_DATABASE
value: zabbix
- name: MYSQL_USER
value: root
- name: MYSQL_PASSWORD
value: root
- name: ZBX_PROXYMODE
value: "0"
- name: ZBX_HOSTNAME
value: zabbix-proxy
- name: ZBX_SERVER_HOST
value: "192.168.1.35:10051"
- name: ZBX_DEBUGLEVEL
value: "3"
- name: ZBX_CACHESIZE
value: 128M
- name: ZBX_PROXYCONFIGFREQUENCY
value: "10"
Zabbix Agent
As part of this setup, I’m configuring the agent’s passive server environment variable so that it can accept connections from any IP address. Consequently, this allows for greater connectivity flexibility. Additionally, for the proxy, I’m specifying the server host that the proxy can reach, along with a custom (non-default) port.
zabbixAgent:
enabled: true
resources: {}
securityContext: {}
containerSecurityContext: {}
hostNetwork: false
dnsConfig: {}
hostPID: true
hostRootFsMount: true
extraHostVolumeMounts: []
image:
repository: zabbix/zabbix-agent2
tag: alpine-7.0-latest
pullPolicy: IfNotPresent
pullSecrets: []
env:
- name: ZBX_PASSIVE_ALLOW
value: "true"
- name: ZBX_ACTIVE_ALLOW
value: "false"
- name: ZBX_DEBUGLEVEL
value: "4"
- name: ZBX_TIMEOUT
value: "4"
- name: ZBX_PASSIVESERVERS
value: "0.0.0.0/0"
RBAC Setup
As part of the RBAC (Role-Based Access Control) configuration, I’ve assigned the necessary permissions to a Kubernetes ServiceAccount. Consequently, this ServiceAccount is linked to a service token, which the Zabbix server uses to authenticate and access the Kubernetes API for monitoring purposes.
Later, we’ll cover how to retrieve the service account token (typically via a Secret or by mounting it in a Pod) and how to configure Zabbix to use this token for secure communication with the Kubernetes API server.
rbac:
create: true
additionalRulesForClusterRole:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["apps"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["batch"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["extensions"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["apps", "rbac.authorization.k8s.io"]
resources: ["*"]
verbs: ["*"]
serviceAccount:
create: true
name: zabbix-service-account
4. Create a Namespace (if not already)
You can also optionally add a namespace.
kubectl create namespace monitoring
5. Deploy Zabbix Helm Chart
helm install zabbix . --dependency-update -f $kubernetes-helm/values.yaml -n monitoring
Wait until everything is up and running. You can check the status using this command:
kubectl get pods -n monitoring
Now everything is set up, the next step is to add hosts in Zabbix for your Kubernetes cluster. But before we do that, we need one more thing, the access token.
6. Get the Token (for Api & Access)
Get the access token that was created with the service account during the Helm chart installation. To do this, run the following command using the service account’s name:
kubectl get secret zabbix-service-account -n monitoring -o jsonpath={.data.token} | base64 -d
This command retrieves the secret linked to the service account and extracts the token from it. Be sure to save the token you’ll need later.
You’ll also need the Kubernetes API address. Usually, you can access it through the built-in proxy in your cluster instead of connecting directly to the server or using an external proxy. In that case, use the service DNS name:
https://kubernetes.default.svc.cluster.local:443/api
If that doesn’t work for your setup, you can run this command to find the right address:
kubectl cluster-info
7. Deploying Zabbix Server Locally with Docker Compose
Now that your Zabbix Proxy and Agent are up and running inside your Kubernetes cluster, the next step is to deploy the Zabbix Server, which will receive and process monitoring data.
For flexibility, you can set up the Zabbix Server on your local machine, a VM, or inside Docker. In this example, we’ll use Docker Compose to quickly spin up the full Zabbix stack, including the server, web UI, and MySQL database.
Here’s a basic docker-compose.yml to get started
version: '3'
services:
zabbix-mysql-server:
image: mysql:8.0.30
container_name: zabbix-mysql-server
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: root
MYSQL_PASSWORD: root # ⚠️ Use a strong password in production
MYSQL_DATABASE: zabbix
networks:
- zabbix-network
volumes:
- mysql-data:/var/lib/mysql
zabbix-server:
image: zabbix/zabbix-server-mysql:alpine-7.0-latest
container_name: zabbix-server
environment:
DB_SERVER_HOST: zabbix-mysql-server
MYSQL_DATABASE: zabbix
MYSQL_USER: root
MYSQL_PASSWORD: root
ports:
- "10051:10051" # Zabbix server listening port
networks:
- zabbix-network
zabbix-web:
image: zabbix/zabbix-web-nginx-mysql:latest
container_name: zabbix-web
environment:
DB_SERVER_HOST: zabbix-mysql-server
MYSQL_DATABASE: zabbix
MYSQL_USER: root
MYSQL_PASSWORD: root
ports:
- "8080:8080" # Web UI accessible at http://localhost:8080
networks:
- zabbix-network
networks:
zabbix-network:
volumes:
mysql-data:
- All containers are connected through an isolated Docker network (zabbix-network) for secure internal communication
- The MySQL database persists data using a named volume (mysql-data).
- Ports:
- 10051 → Zabbix Server (used by proxies and agents to send data)
- 8080 → Zabbix Web UI (use your browser to access it)
- 10051 → Zabbix Server (used by proxies and agents to send data)
- Make sure the database credentials match across all services.
Once you run this with:
docker-compose up -d
Zabbix should be accessible via http://localhost:8080. From there, you can log in to the web UI, connect your proxy, and begin monitoring your Kubernetes infrastructure
8. Adding the Proxy and Setting Up Monitoring
First, go to the Zabbix UI and navigate to: Administration → Proxies
- Click Create Proxy
Since this is an active proxy, all you need to do is enter a name. If you didn’t change anything in the Helm chart, the default name will be `zabbix-proxy`. If you want to use a different name, you can set it using the `zbx_hostname` environment variable in the Helm chart. For now, we’ll use the default. Type the name and click Add. After a few minutes, you should see that the proxy has connected.
Next, we’ll organise Kubernetes-related hosts:
- Go to Configuration → Host groups, and create a new group called Kubernetes.
Then create a new host:
- Go to Configuration → Hosts, and click Create Host.
- Name it “Kubernetes Nodes”.
- Assign it to the “Kubernetes” group you just made.
- Attach the template named “Kubernetes nodes by HTTP”.
- Set “Monitored by proxy” to the proxy you created earlier (e.g., `zabbix-proxy`).
Now configure some macros:
- Click the Macros tab and choose “Inherited and host macros”
- Set `{KUBE.API.ENDPOINT.URL}` to your Kubernetes API URL — for example:
`https://kubernetes.default.svc.cluster.local:443/api`
- Set the token macro to the API token you got earlier from the command line.
- Click Add.
After a few minutes, Zabbix will begin collecting data. Consequently, you’ll start to see metrics appear under “Latest Data,” and shortly thereafter, new hosts will show up for each Kubernetes node.
9. Creating Another Host for Kubernetes Cluster State
Now let’s create one more host to monitor the overall state of the Kubernetes cluster using the Kubernetes API and kube-state-metrics.
- Go to Configuration → Hosts and click Create Host again.
- Name the host: ”Kubernetes Cluster State”.
- Add it to the same “Kubernetes” host group.
- Attach the template called “Kubernetes Cluster State by HTTP”.
- Under “Monitored by proxy“, select the same proxy you created earlier.
Now go to the Macros tab:
- Set `{KUBE.API.ENDPOINT.URL}` to: `https://kubernetes.default.svc.cluster.local:443`
(Note: don’t include `/api` at the end this time.)
- Set the API token just like you did for the previous host.
- Once that’s done, click Add.
If everything’s set up correctly, Zabbix will start pulling cluster-level data soon.
Integrate Zabbix with Grafana & Create Dashboard
1. Install & Enable the Zabbix Plugin in Grafana
- Log in to your Grafana instance.
- Go to “Administration” → “Plugins”.
- Search for Zabbix.
- Click the “Zabbix” plugin by Alexey Kalachev and then click Install.
- Once installed click on Enable
2. Add Zabbix as a Data Source
- Go to “Configuration” → “Data Sources” → “Add data source”.
- Select Zabbix
- Fill out the following details:
- Name: Zabbix
- URL: http://<zabbix-server-host>/api_jsonrpc.php.
- Access: Server (default)
- Zabbix API Details:
- Username: Zabbix frontend user (e.g. Admin)
- Password: Corresponding password
- Click Save & Test to validate the connection.
3. Create a Custom Dashboard
- Go to “Create” → “Dashboard”
- Click “Add new panel”
- In the Query section, select:
- Data source: Zabbix
- Group: The Zabbix host group (e.g., Kubernetes Nodes)
- Host: The target host
- Item: The metric you want (e.g., CPU Load, Memory Usage)
- Choose a visualisation type (graph, gauge, table, etc.).
- Customise titles, thresholds, and legends as needed.
- Click Apply.
Repeat this process to add more panels and build a full dashboard.
4. Save Your Dashboard
- Click the disc icon or “Save dashboard” button.
- Give it a name (e.g., Zabbix Kubernetes Monitoring).
- Optionally, select a folder to organise your dashboards.
- Click Save.
Creating & Scheduling Reports in Skedler for Grafana Dashboards
Moreover, Skedler allows you to generate rich, formatted PDF, Excel, and HTML reports with minimal configuration—perfect for sharing insights with teams or stakeholders.
For a detailed, step-by-step guide, be sure to visit the official Skedler blog and tutorial video:
https://www.skedler.com/blog/grafana-pdf-report-export-guide/
Final Thoughts
If you’re running Kubernetes, monitoring is non-negotiable.
Overall, the Zabbix + Grafana + Skedler (ZGS Stack) provides a cost-effective, scalable, and elegant solution for monitoring, visualizing, and reporting on your Kubernetes environment.
Ready to Try It Out?
First, deploy the stack and customize your dashboards. Then, let Skedler handle reporting. As a result, your SRE and compliance teams will thank you.


