Google Cloud Tracking VM and sole-tenant node usage for license reporting

When we bring our own Windows licenses (BYOL) to Google Cloud, we must keep track of the number of physical servers that we’re using those licenses on. That’s because Windows Server is licensed by core and not by VM.

By using sole-tenant nodes, we can control which nodes our VMs run on. A node is an abstraction of a physical server and at any point in time, a node corresponds to exactly one physical server. But the association between nodes and physical servers can change over time: over the period of, say, 3 months, a single node might correspond to 2 different physical servers.

Because nodes and physical servers aren’t the same thing, it’s insufficient to count the number of sole-tenant nodes if we want to track Windows BYOL license usage. We have to go one level deeper and count the number of physical servers.


Let’s consider a sole-tenant VM instance that was started and, several months later, stopped again. During its lifetime, the VM ran on a single node, but that node actually corresponded to two different servers: First, the node corresponded to Server 1. Then, because of server maintenance, all VMs from Server 1 were migrated to Server 2 and later back to Server 1. This history corresponds to 3 placements:


If we know the placement history of all our sole-tenant VMs, we can accurately identify the number of physical servers that were used at any point in time. But how can we identify those placements?

Analyzing the audit log

Whenever Compute Engine places a sole-tenant VM, it emits a NotifyInstanceLocation log record to the audit logs. This record contains the VM’s instance ID and a server ID that uniquely identifies the physical server.

  "protoPayload": {
    "@type": "",
    "serviceName": "",
    "methodName": "NotifyInstanceLocation",
    "request": {
      "@type": ""
    "metadata": {
      "nodeType": "c2-node-60-240",
      "serverId": "4bb28f112cfc377652c4b91...",
      "timestamp": "2022-07-25T03:49:41.593387Z",
      "@type": ""
  "resource": {
    "type": "gce_instance",
    "labels": {
      "zone": "asia-southeast1-b",
      "instance_id": "405913213...",
      "project_id": "my-project"

Each NotifyInstanceLocation identifies the beginning of a placement.

Unfortunately, there’s no corresponding event that would clearly identify the end of a placement. Instead, we have to infer this information from a multitude of other events. For example, when we see a v1.compute.instances.stop, v1.compute.instances.suspend, or v1.compute.instances.delete event, we know that a VM was intentionally stopped and can infer the end of a placement. Similarly, a compute.instances.hostError or compute.instances.guestTerminate event indicates that the VM was involuntarily stopped, which also implies the end of a placement.

Doing this kind of audit log analysis gives us precise results, but it’s tedious and time consuming to do without proper tool support.

License Tracker

License Tracker is an open-source tool I recently published that automates the process of identifying placements by analyzing audit logs. It then writes its result to BigQuery which lets us further aggregate and analyze the information to infer licensing implications.

Technically, License Tracker is a command line tool, but it’s intended to be used in concert with Cloud Run, BigQuery, and DataStudio:

  • The License Tracker tool is deployed on Cloud Run and configured to analyze the logs of one or more projects.
  • Once a day, Cloud Scheduler triggers the Cloud Run job, causing the License Tracker tool to update a BigQuery dataset.
  • A DataStudio dashboard visualizes the data from BigQuery and makes it available to users.


Here’s a screenshot from the DataStudio dashboard, showing the number of VM instances, sole-tenant nodes, and cores to-be-licensed:


To find out more about how to deploy and use License Tracker, see Track VM and sole-tenant node usage for license reporting in the Google Cloud docs or check out the GitHub repository.

For a full list of articles I’ve published on the Google Cloud website, see Articles on

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home