Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • See all Red Hat products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Red Hat OpenShift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • See all technologies
    • Programming languages & frameworks

      • Java
      • Python
      • JavaScript
    • System design & architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer experience

      • Productivity
      • Tools
      • GitOps
    • Automated data processing

      • AI/ML
      • Data science
      • Apache Kafka on Kubernetes
    • Platform engineering

      • DevOps
      • DevSecOps
      • Red Hat Ansible Automation Platform for applications and services
    • Secure development & architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & cloud native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • See all learning resources

    E-books

    • GitOps cookbook
    • Podman in action
    • Kubernetes operators
    • The path to GitOps
    • See all e-books

    Cheat sheets

    • Linux commands
    • Bash commands
    • Git
    • systemd commands
    • See all cheat sheets

    Documentation

    • Product documentation
    • API catalog
    • Legacy documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore the Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How to monitor Openshift Virtualization VMs with Zabbix

May 1, 2026
Leonardo Araujo
Related topics:
KubernetesObservabilityVirtualization
Related products:
Red Hat OpenShiftRed Hat OpenShift Virtualization

    In this article, I will demonstrate how to use Zabbix integrated with Prometheus/Thanos in the Red Hat OpenShift Virtualization cluster. We will use low level discovery (LLD) to automate the discovery of all VMs, and thus monitor CPU, memory, network, etc. This is for users who need to create and monitor their Openshift Virtualization using Zabbix, creating capacity alerts, applications, etc. I will not cover the installation of the Zabbix.

    Get started

    We will create a template using the LLD resource to process the collection of metrics for defining and creating the items and triggers. We will use Zabbix to connect to the Prometheus/Thanos API and have access to all metrics available in the environment, such as kubevirt metrics and infrastructure. Figure 1 shows the monitoring architecture.

    A diagram of the monitoring architecture.
    Figure 1: Monitoring architecture where Zabbix actively collects metrics from OpenShift Virtualization via Prometheus through a secure DMZ.

    Prerequisites:

    • User with the cluster-admin cluster role
    • Openshift 4.16+
    • Zabbix server

    In this article, we will use the following versions:

    • Openshift v4.18.23
    • Kubernetes v1.31.11
    • Zabbix 6.0.43

    Create a ServiceAccount

    Let's create a ServiceAccount in OpenShift to use in our Zabbix connection to Prometheus/Thanos.

    Using the oc CLI, connect to OpenShift as follows.

    $ oc project openshift-monitoring
    $ oc create sa zabbix-sa
    $ oc adm policy add-cluster-role-to-user cluster-monitoring-view -z zabbix-sa
    Now let's create a token to perform our authentication.
    $ oc create token zabbix-sa -n openshift-monitoring --duration=8760h

    Note

    Using this command, we will have a token valid for 1 year. After this period, it is necessary to create a new one.

    To create a token without expiration, create a secret of type service-account-token.

    $ cat <<EOF | oc apply -f -
    apiVersion: v1
    kind: Secret
    metadata:
      name: zabbix-token                                # <----- Secret Name
      namespace: openshift-monitoring
      annotations:
        kubernetes.io/service-account.name: zabbix-sa   # <----- ServiceAccount Name
    type: kubernetes.io/service-account-token           
    EOF
    
    To display the token, run the following command and save it for use in Zabbix.
    $ oc -n openshift-monitoring get secret zabbix-token -o jsonpath='{.data.token}' | base64 -d
    Collect the Thanos endpoint:
    $ oc -n openshift-monitoring get route thanos-querier -o jsonpath='{.spec.host}'

    Create a host group

    Let's create a host group to organize and create our OpenShift hosts to monitor. In the left side menu, click on Configuration > Host groups > Create host group > define the Group name and click Add.

    Now we'll create a template to centralize all the items we want to monitor in OpenShift Virtualization so we can reuse it in other clusters.

    In the left side menu, click on Configuration > Templates > Create template > define the Template name > in Groups enter the host group name created previously, then click ADD.

    Create the host

    Now we will create a host, which will be the identifier for our OpenShift cluster. This will allow us to monitor more than one host (OpenShift cluster) with the same template.

    In the left side menu, click on Configuration > Hosts > Create host, then define the following fields: Host name, Templates, Groups, Description. For templates and Groups, use the names created earlier.

    Before saving, click on Macros, and let's add two variables (macros), which we will associate with our host (cluster) and use in our data collection.

    Create the following Macros:

    • {$PROM_URL}: Add the Thanos URL that we collected in the last step of the ServiceAccount.
    • {$PROM_TOKEN}: Add the token we created for our ServiceAccount.

    Now we can click Add and save our host (Figure 2).

    Zabbix “Host macros” configuration screen showing PROM_URL with the Thanos/Prometheus endpoint and PROM_TOKEN used for API authentication.
    Figure 2: Zabbix host macros configured with Prometheus API endpoint and authentication token.

    Low level discovery

    LLD in Zabbix is a feature that automatically discovers resources within a monitored system and dynamically creates monitoring items, triggers, and graphs based on predefined rules.

    Knowing the function of LLD, let's create two: one for virtual machines and another for virtualization nodes in OpenShift.

    We will create a Discovery Rule (LLD) that will discover all the virtual machines created in our OpenShift Virtualization cluster.

    In the left side menu, click on Configuration > Templates > click on the template we created earlier > click on Discovery rules in the top tab > then click on Create discovery rule.

    Fill in the following fields:

    • Name: Add the name of the discovery that will be made.
    • Type: Select HTTP agent
    • Key: Define a unique identifier for this execution.
    • URL: This will be our endpoint for querying metrics using the Macro {$PROM_URL}/api/v1/query
    • Query fields: This field is responsible for passing our query promql to the endpoint in the URL field.
      • Name: query
      • Value: kubevirt_vm_info
    • Headers: Here we will add our token for authentication to the API using our token Macro.
      • Name: Authorization
      • Value: Bearer {$PROM_TOKEN}
    • Update interval: 1h is the frequency at which our VM discovery will be run to discover new VMs.

    Our query will return a JSON output, but we need to filter the content we want in this output. We will use the Preprocessingfeature.

    Click on Preprocessing > Add > In Name, select Javascript > click on Parameters and add the following script:

    var obj = JSON.parse(value);
    var out = [];
    
    for (var i = 0; i < obj.data.result.length; i++) {
      var m = obj.data.result[i].metric;
      out.push({
        "{#VM}": m.name,
        "{#NAMESPACE}": m.namespace
      });
    }
    
    return JSON.stringify({ "data": out });

    Note

    This script will process all the output and filter only the following information: VM name and Namespace already creating Macros (variables) for later use.

    To validate that our Preprocessing is working correctly, click Test all steps.

    Check the Get value from host box and add the Macros values, adding the Thanos endpoint and the bearer token. 

    Then click Get value and test as shown in Figure 3.

    The Zabbix test item window showing Prometheus API macros.
    Figure 3: Testing Zabbix item with Prometheus API, validating macros and LLD preprocessing output.

    Click Add to save our preprocessing and click Add again to save our discovery rule.

    Note

    With this test, we can see that our script is working correctly.

    Create  the item prototype

    With the Item Prototype, we will create specific queries such as CPU, memory, network, uptime, and phase using the discovery rule's Macros (variables), VM, and namespace.

    Now click on Item Prototype within the discovery rule created earlier or Configuration > Templates > Template Name created earlier > Discovery Rule created earlier > Item prototypes > Create Item prototype.

    Fill in the following fields:

    • Name: VM {#VM} CPU usage
    • Type: Select HTTP agent
    • Key: kubevirt.vm.cpu[{#NAMESPACE},{#VM}]
    • Type of Information: Numeric (float)
    • URL: {$PROM_URL}/api/v1/query
    • Query fields: Promql to collect CPU usage from VMs
      • Name: query
      • Value: sum by (name,namespace)(rate(kubevirt_vmi_cpu_usage_seconds_total{name="{#VM}",namespace="{#NAMESPACE}"}[5m]))
    • Headers: Here we will add our token for authentication to the API using our Token Macro.
      • Name: Authorization
      • Value: Bearer {$PROM_TOKEN}
    • Units: cores
    • Update interval: 1m, this is how often our item will be collected.

    Click on Preprocessing > Add . 

    In Name, select Javascript and click on Parameters to add the following script:

    var obj = JSON.parse(value);
    
    if (obj.data.result.length === 0) {
      return 0;
    }
    
    return obj.data.result[0].value[1];

    Note

    This script processes the collected information; if the VM has no CPU usage data, it will be displayed as 0.

    Click Add to save our preprocessing and click Add again to save our item.

    To speed up the creation of new items, let's clone this one by clicking on the created item. At the bottom of the page, click Clone.

    In this Item, we will update the following fields:

    • Name: VM {#VM} CPU total
    • Key: kubevirt.vm.cpu.request[{#NAMESPACE},{#VM}]
    • Type of Information: Numeric (unsigned)
    • Query fields: Promql to collect CPU Total from VMs
      • Name: query
      • Value: max by (namespace, name) (kubevirt_vm_resource_requests{resource="cpu", name="{#VM}", namespace="{#NAMESPACE}"} )

    Note

    The remaining fields should remain the same.

    Click on Preprocessing > Add. In Name, select JSONPath.

    Click Parameters and add the value $.data.result[0].value[1].

    Click Add to save our preprocessing and click Add again to save our item.

    Repeat the cloning process and add the following items.

    Memory usage:

    • Name: VM {#VM} Memory Usage
    • Key: kubevirt.vm.memory[{#NAMESPACE},{#VM}]
    • Type of Information: Numeric (unsigned)
    • Query fields: Promql to collect Memory Usage from VMs
      • Name: query
      • Value: sum by (name,namespace)(kubevirt_vmi_memory_used_bytes{name="{#VM}",namespace="{#NAMESPACE}"})
    • In Preprocessing, select JavaScript and in parameter, add the following script:

      var obj = JSON.parse(value);
      
      if (obj.data.result.length === 0) {
        return 0;
          }
      
      return obj.data.result[0].value[1];

    Memory total:

    • Name: VM {#VM} Memory total
    • Key: kubevirt.vm.mem.request[{#NAMESPACE},{#VM}]
    • Type of Information: Numeric (float)
    • Query fields: Promql to collect memory total from VMs
      • Name: query
      • Value: max by (namespace, name)(kubevirt_vm_resource_requests{resource="memory", name="{#VM}", namespace="{#NAMESPACE}"})
    • In preprocessing, select JSONPath and add  $.data.result[0].value[1] in parameter.

    For this use case, we will monitor: CPU, memory, network, and VM status. You must create all the items you deem necessary to monitor, according to the needs of the environment.

    Create the trigger prototype

    With the Trigger Prototype, we will create alerts based on the collected consumption items.

    Now click on Trigger Prototype within the Discovery Rule created earlier or Configuration > Templates > Template Namecreated earlier > Discovery Rule created earlier > Trigger prototypes > Create trigger prototype

    We will fill in the following fields:

    • Name: VM {#NAMESPACE}/{#VM} CPU usage high >= 90%
    • Severity: High
    • Expression:

      (
      avg(/Template OpenShift Virtualization/kubevirt.vm.cpu[{#NAMESPACE},{#VM}],5m)
      /
      last(/Template OpenShift Virtualization/kubevirt.vm.cpu.request[{#NAMESPACE},{#VM}])
      ) > 0.90
      and 
      last(/Template OpenShift Virtualization/kubevirt.vm.status[{#VM}])=1
      
       
    • Description: VM {#NAMESPACE}/{#VM} CPU utilization: {ITEM.LASTVALUE}

    Figure 4 illustrates the Zabbix trigger prototype.

    Zabbix trigger prototype configuration screen showing a high CPU usage alert.
    Figure 4: Zabbix trigger prototype configured to alert on high VM CPU usage using LLD macros and Prometheus-based metrics.

    Note

    Repeat the cloning process, change the value from 0.90 to 0.70 for example, and create the alert with a Warning serverity level.

    In this expression, we are dividing the total by the consumption, and the result needs to be greater than 0.90 (90%), ensuring that we only do this for the VMs that are running.

    Create alerts with different severities, according to the items that were discovered (Figure 5).

    The Zabbix interface displays a list of trigger prototypes for virtual machines.
    Figure 5: The Zabbix trigger prototypes list shows multiple alerts for VM CPU, memory, and status based on LLD discovery.

    Create the graph prototype

    With Graph Prototype, we can create specific graphs, such as a network graph.

    Click on Graph Prototype within the discovery rule created earlier or Configuration > Templates > Template Name created earlier > Discovery Rule created earlier > Graph prototypes > Create graph prototype.

    Fill in the following fields:

    • Name: VM {#NAMESPACE}/{#VM} Network throughput
    • Items:
      • Add prototype:
        • Select the prototype items created for network RX and TX.

    After adding the items, change the Function field to avg, adjust the item colors as desired, and click Add.

    Create discovery rule (LLD) for VMs

    Now, to make our monitoring more complete, let's create an LLD of nodes for virtualization. That is, nodes where the VMs run.

    In the left side menu, click on Configuration > Templates 

    Click on the template we created earlier.

    Click on Discovery rules in the top tab. 

    Then click on Create discovery rule.

    Fill in the following fields as follows:

    • Name: OpenShift - Node discovery
    • Type: Select HTTP agent
    • Key: openshift.node.discovery
    • URL: {$PROM_URL}/api/v1/query
    • Query fields: This field is responsible for passing our query promql to the endpoint in the URL field.
      • Name: query
      • Value: count by (node) (kube_node_labels{label_kubevirt_io_schedulable="true"})
    • Headers: Here we will add our token for authentication to the API using our Token Macro.
      • Name: Authorization
      • Value: Bearer {$PROM_TOKEN}
    • Update interval: 1h, this is the frequency at which our VM discovery will be run, to discover new VMs.

    Click on Preprocessing > Add.

    In Name, select Javascript. 

    Click on Parameters and add the following script:

    var obj = JSON.parse(value);
    var out = [];
    
    for (var i = 0; i < obj.data.result.length; i++) {
      out.push({ "{#NODE}": obj.data.result[i].metric.node });
    }
    
    return JSON.stringify({ "data": out });
     

    Note

    This script will process all the output and filter only the following information: NODE Name, already creating Macros (variables) for later use.

    To validate that our Preprocessing is working correctly, click Test all steps (Figure 6).

    Check the Get value from host box and add the Macros values, adding the Thanos endpoint and the bearer token. Then click Get value and test.

    The Zabbix test item window displays the Prometheus API response for node discovery.
    Figure 6: Testing Zabbix LLD for node discovery using Prometheus API and JavaScript preprocessing.

    Click Add to save our preprocessing and click Add again to save the item.

    Create the item prototype

    With the LLD of nodes, we can also create ITEM Prototype such as CPU, memory, network, uptime, and phase using the discovery rule's Macros (variables), NODE.

    Now click on Item Prototype within the discovery rule created earlier or Configuration > Templates > Template Name created earlier > Discovery Rule created earlier > Item prototypes > Create Item prototype.

    Fill in the following fields:

    • Name: Node {#NODE} Ready status
    • Type: Select HTTP agent
    • Key: node.ready[{#NODE}]
    • Type of Information: Numeric (unsigned)
    • URL: {$PROM_URL}/api/v1/query
    • Query fields: Promql to collect CPU usage from VMs
      • Name: query
      • Value: max by (node) (kube_node_status_condition{ condition="Ready", status="true", node="{#NODE}" })
    • Headers: Here we will add our token for authentication to the API using our token macro.
      • Name: Authorization
      • Value: Bearer {$PROM_TOKEN}
    • Update interval: 30s, this is how often our item will be collected.

    Click on Preprocessing > Add 

    In Name, select Javascript.

    Click on Parameters and add the following script:

    var obj = JSON.parse(value);
    
    if (obj.data.result.length === 0) return 0;
    
    return obj.data.result[0].value[1];
     

    Note

    This JavaScript will simply ensure that we get 0 as a return value if it's null or if the value is different from what's expected.

    Click Add to save our preprocessing and click Add again to save the item. Repeat the previous steps to create new items, triggers, and graph prototypes.

    In this LLD, we create items and triggers for the CPU, memory, network, boot time and ready status. Download the XML template if needed by clicking this link.

    Important

    This is not a complete template. You should use it as a base and customize according to the environment/cluster.

    Viewing the collected items

    Now that we have created our host cluster and template with the LLDs and their items, let's check if the data was collected correctly by going to Monitoring > Latest Data.

    Figure 7 shows the items collected by LLD KubeVirt - VM discovery.

    The Zabbix monitoring interface shows the latest data for multiple VMs.
    Figure 7: The Zabbix latest data view displays collected metrics for discovered virtual machines.

    Figure 8 shows the items collected by LLD OpenShift - Node discovery.

    The Zabbix monitoring interface shows the latest data for multiple OpenShift worker nodes.
    Figure 8: The Zabbix latest data view displays collected metrics for discovered OpenShift nodes.

    Note

    It's important to note that the "Without data" filter is set to 0, meaning all items are being collected correctly.

    With all our items collected correctly, we can view our dashboard and identify if there are any active alerts (Figure 9).

    The Zabbix global dashboard displays system information, problem alerts, and severity levels for VMs and OpenShift nodes.
    Figure 9: The Zabbix dashboard shows a global view of system health, including alerts for virtual machines and OpenShift nodes.

    Wrap up

    Monitoring OpenShift Virtualization with Zabbix demonstrates how easily external tools can integrate with the platform's native observability stack. By using Prometheus and Thanos, OpenShift exposes comprehensive metrics that can be consumed by Zabbix through simple HTTP queries.

    This enables effective monitoring of virtual machines and infrastructure without additional agents, using features such as LLD for dynamic discovery and automation. Ultimately, this approach combines the flexibility of Zabbix with the power of OpenShift's integrated monitoring, providing a scalable and efficient solution for modern environments.

    For more details and other configurations, start with these reference documents:

    • Openshift Virtualization - Monitoring
    • Openshift 4.18 - Accessing metrics
    • KubeVirt.io - Monitoring
    • Zabbix 6.0 - Low Level Discovery
    • Zabbix 6.0 - Item HTTP Agent
    • Zabbix 6.0 - Export and Import Templates

    Related Posts

    • Deploy hosted control planes with OpenShift Virtualization

    • Adding support for s390x in LLD, the LLVM linker

    • Ceph storage monitoring with Zabbix

    • How to run vLLM on CPUs with OpenShift for GPU-free inference

    Recent Posts

    • How to monitor Openshift Virtualization VMs with Zabbix

    • How StatefulSet deployments tripled OpenShift Pipelines throughput

    • How we turned Storybook into a behavioral verification engine

    • Boosting speed: Use eBPF and netstacklat to troubleshoot latency

    • New features in GCC 16: Improved error messages and SARIF output

    What’s up next?

    Learning Path Virtualization share image

    Red Hat OpenShift Virtualization disaster recovery

    Implement disaster recovery with storage replication and OpenShift APIs for...
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility