Unified Monitoring for Multi-Cloud Ecosystems

As a South African SRE working with teams spread across Johannesburg, Cape Town, and remote sites, Unified Monitoring for Multi-Cloud Ecosystems is no longer a “nice to have” — it’s a survival requirement. Our platforms run across AWS…

Unified Monitoring for Multi-Cloud Ecosystems

Unified Monitoring for Multi-Cloud Ecosystems

As a South African SRE working with teams spread across Johannesburg, Cape Town, and remote sites, Unified Monitoring for Multi-Cloud Ecosystems is no longer a “nice to have” — it’s a survival requirement. Our platforms run across AWS regions in Europe, Azure in South Africa North, GCP in the US, and a couple of on‑prem Kubernetes clusters. Without a unified observability layer, incident response quickly turns into a game of “which cloud broke this time?”

In this article, I’ll walk through how I use Grafana to build Unified Monitoring for Multi-Cloud Ecosystems — focusing on AWS, Azure, GCP, and on‑prem — with practical examples and code snippets you can adapt for your own environment.[1][2][3]

Why Unified Monitoring for Multi-Cloud Ecosystems Matters

Unified Monitoring for Multi-Cloud Ecosystems is about creating a single, consistent observability layer across all your cloud providers and on‑prem so you can detect, debug, and remediate incidents without jumping between multiple dashboards and CLIs.[1][2] The goal is a single pane of glass that blends metrics, logs, and traces from AWS, Azure, GCP, and on‑prem into one view.[1][3]

For DevOps engineers and SREs, this has concrete benefits:

  • Lower MTTD and MTTR because you correlate issues across providers in one place.[1][2]
  • Standardized alerting and runbooks regardless of where a service is hosted.[2][9]
  • Portable dashboards that work across providers instead of being tied to a single cloud.[2][3]

Grafana is a natural fit here: it integrates natively with CloudWatch, Azure Monitor, and Google Cloud Monitoring, plus Prometheus, Loki, and Tempo, to provide unified dashboards for multi‑cloud environments.[3][4][5]

Reference Architecture for Unified Monitoring

Let’s start with a practical reference architecture for Unified Monitoring for Multi-Cloud Ecosystems using Grafana:[1][2][9]

  1. Deploy metrics/logs agents (Prometheus, OpenTelemetry Collector, Fluent Bit) into each cloud and on‑prem.[1][9]
  2. Standardize labels and resource identifiers (`cloud`, `region`, `env`, `service`) across all telemetry.[1][2]
  3. Forward telemetry to a central observability stack: self‑hosted Grafana + Prometheus/Loki/Tempo, or Grafana Cloud.[1][5][10]
  4. Connect native cloud monitoring (CloudWatch, Azure Monitor, GCP Monitoring) as additional Grafana data sources.[1][3][4]
  5. Build cross‑cloud dashboards, SLOs, and alerts that slice by provider, region, and environment.[1][2]

In my case, we run a central Grafana stack in AWS (Cape Town connects via VPN), but the same design works with Grafana Cloud’s Cloud Provider Observability app, which gives a unified experience for monitoring AWS, Azure, and GCP from one place.[4][5]

Step 1: Standardize Labels Across Clouds

The foundation of Unified Monitoring for Multi-Cloud Ecosystems is a consistent labeling scheme. If your metrics in AWS, Azure, and GCP all use different label names, your Grafana dashboards will be a mess.

We enforce a shared label model via Prometheus and OpenTelemetry Collector:[1][2][9]

  • cloud: aws, azure, gcp, onprem
  • region: provider region (eu-west-1, southafricanorth, us-central1, etc.)
  • env: prod, staging, dev
  • service: logical service name, e.g. payments-api, auth-service[1][2]

Here’s a simple Prometheus scrape config snippet (Kubernetes) that injects these labels per cluster:

scrape_configs:
  - job_name: 'kubernetes-services'
    kubernetes_sd_configs:
      - role: endpoints
    relabel_configs:
      - source_labels: [__meta_kubernetes_namespace]
        target_label: env
      - source_labels: [__meta_kubernetes_label_app]
        target_label: service
      - replacement: 'aws'
        target_label: cloud
      - replacement: 'eu-west-1'
        target_label: region

For an on‑prem cluster in Johannesburg, I simply change cloud and region:

      - replacement: 'onprem'
        target_label: cloud
      - replacement: 'za-jhb-dc1'
        target_label: region

This consistency is what makes cross‑cloud Grafana panels and alerts possible.[1][2]

Step 2: Connect Multi-Cloud Data Sources to Grafana

Next, we connect all cloud‑native and open‑source data sources into Grafana.[1][2][3]

Provisioning Prometheus and CloudWatch

Using Grafana’s provisioning feature, we describe data sources in YAML so they’re version‑controlled and repeatable.[11]

apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    url: http://prometheus.monitoring.svc.cluster.local:9090
    access: proxy
    isDefault: true

  - name: AWS CloudWatch
    type: cloudwatch
    jsonData:
      defaultRegion: eu-west-1
      authType: default

This gives us infrastructure metrics from Prometheus and native AWS service metrics from CloudWatch in the same Grafana instance.[1][3][8]

Provisioning Azure Monitor and GCP Monitoring

We add Azure and GCP similarly (credentials omitted for brevity):[3][4][8]

  - name: Azure Monitor
    type: grafana-azure-monitor-datasource
    jsonData:
      cloudName: azurepublic
      tenantId: <tenant-id>
      subscriptionId: <subscription-id>

  - name: Google Cloud Monitoring
    type: stackdriver
    jsonData:
      authenticationType: gce
      gceProjectId: <gcp-project-id>

At this point, Grafana can query AWS, Azure, and GCP metrics side‑by‑side, which is the core of Unified Monitoring for Multi-Cloud Ecosystems.[3][4][5][8]

Step 3: Build Cross-Cloud Dashboards

With labels standardized and data sources connected, we focus on portable dashboards that don’t care which cloud they’re talking to.[2][3]

Example: Multi-Cloud Latency Comparison

One of my favourite panels compares latency for the same service across AWS, Azure, and GCP to validate regional failover strategies.[2]

Assume you’ve exposed HTTP latency metrics as http_request_duration_seconds_bucket via Prometheus in all environments. A Grafana panel query might look like:

histogram_quantile(
  0.95,
  sum by (le, cloud, region, service) (
    rate(http_request_duration_seconds_bucket{
      service="payments-api",
      env="prod"
    }[5m])
  )
)

This gives you 95th percentile latency per cloud and region on a single chart: you can immediately see if payments-api is slower in southafricanorth than in eu-west-1.[1][2]

Example: Unified Error Rate Panel

Similarly, you can aggregate error rates for a service across providers:

sum by (cloud, region, service)(
  rate(http_requests_total{
    service="auth-service",
    status_code=~"5..",
    env="prod"
  }[5m])
)

Displayed as a stacked bar chart, this quickly shows whether a spike is isolated to one provider (