Skip to content
Edouard Topin's Blog
Observability as Code on VCF & Kubernetes / Series 01/05

Observability foundations for VCF: metrics, logs and traces

The three pillars of observability defined by the OpenTelemetry specification, why they matter for VCF and VKS, and how to choose the right tool for each.

Edouard Topin
7 min read
Abstract editorial illustration of three pillars representing metrics, logs and traces connected by a shared platform base.

There is a specific moment in every infrastructure incident when you realise you are flying blind. A service is degraded, users are affected, and your first reflex — opening vCenter — gives you CPU, memory and network graphs that show nothing obviously wrong. Meanwhile, something at the application layer is silently failing.

That moment is what observability is designed to prevent. And yet, the majority of VCF platforms I encounter are instrumented for infrastructure-layer visibility only. The Kubernetes workloads running on top generate a sea of data — events, logs, metrics, traces — that nobody is collecting systematically.

This article establishes the conceptual framework. Before deploying Prometheus or configuring Fluent Bit, you need a precise understanding of what each observability signal is, what it cannot tell you, and how the three signals compose into a coherent picture. The OpenTelemetry project has done the work of formalising these definitions. We will use them as our reference.

The OpenTelemetry specification: a common vocabulary

The OpenTelemetry specification is the CNCF-backed effort to standardise how observability data is generated, collected, and transmitted. Its value is not primarily in the tooling — it is in the vocabulary it provides. When you say “span”, “trace”, “metric point” or “log record” in an OTel context, everyone in the room means the same thing.

The specification distinguishes three signal types, each with a distinct data model and semantic.

Metrics — A measurement captured at a point in time, aggregated over a series of points. The OTel metric data model defines six instrument kinds: Counter, UpDownCounter, Gauge, Histogram, ObservableCounter, and ObservableGauge. A metric point carries a value, a timestamp, and a set of attributes (labels). Metrics are the most compact signal: they lose individual event detail in exchange for efficient aggregation and long-term retention.

Logs — A record of a discrete event. The OTel log data model defines a LogRecord with a timestamp, observed timestamp, trace context (traceId, spanId), severity number, severity text, body, and attributes. Logs carry the richest context per event, but at the cost of volume — a busy cluster produces millions of log lines per minute.

Traces — A record of a distributed request’s journey across services. A trace is a directed acyclic graph of spans. Each span has a name, a start/end timestamp, a status, attributes, events, and links. The trace model is what makes distributed debugging possible: you can follow a single user request from the API gateway through five microservices and identify exactly which database call added 400ms.

The three signals are not alternatives to each other. They are complementary. A metric alert tells you that something is wrong. Logs tell you what happened. A trace tells you where the latency or error originated in the call graph.

Why VCF environments need all three layers

A common mistake in platform teams is to equate observability with monitoring. Monitoring is the practice of watching known failure modes — setting thresholds on metrics you already understand. Observability is the property of a system that allows you to ask arbitrary questions about its internal state from its external outputs.

VCF platforms combine multiple layers with very different operational characteristics. The hypervisor layer (ESXi, vSAN, NSX) is managed and emits structured metrics via the vSphere API and Aria Operations. The Kubernetes control plane (Supervisor, VKS clusters) exposes metrics via the /metrics endpoint on its components. The application workloads running inside pods are largely opaque unless instrumented.

Each layer requires a different collection mechanism:

  • ESXi and vSAN metrics are available via Aria Operations (vROps) or via the vSphere API polled by exporters like vsphere-exporter for Prometheus.
  • Kubernetes component metrics (kube-apiserver, etcd, kubelet, kube-scheduler) are scraped directly by Prometheus using ServiceMonitor resources.
  • Application metrics require either auto-instrumentation (OTel Java/Python/Go agents) or explicit SDK calls from application code.
  • Logs from pods are written to stdout/stderr and collected by a DaemonSet (Fluent Bit, Fluentd, or Vector) forwarding to a log aggregation backend.
  • Traces require instrumentation — either via OTel language SDKs or via service mesh-level tracing (Istio, Linkerd) that captures span data at the proxy level.

Architecture of reference for VCF + VKS

The architecture that works for a production VCF platform combines two collection layers.

The first layer is the infrastructure layer: Aria Operations collects host, cluster, datastore and NSX metrics. These metrics cover resource contention, vSAN performance, network saturation, and platform-level events. Aria Operations is the authoritative source for infra-layer visibility.

The second layer is the cloud-native layer: a Prometheus stack (kube-prometheus-stack via Helm) running inside each VKS cluster collects Kubernetes component metrics, node metrics (via node-exporter), and application metrics. Grafana provides dashboards correlating both layers via remote_write from Aria Operations.

Fluent Bit runs as a DaemonSet in each VKS cluster, collecting pod logs and forwarding to Loki. The OpenTelemetry Collector runs as a Deployment receiving OTLP from instrumented applications and forwarding traces to Tempo or Jaeger.

ESXi / vSAN / NSX

  Aria Operations ──── remote_write ──── Prometheus
       │                                      │
   vROps API                              Grafana
                                         │       │
                                       Loki    Tempo
                                         │       │
                                    Fluent Bit  OTel Collector
                                         │       │
                                      VKS pods ──┘

This architecture avoids the trap of deploying a single massive observability platform for the entire VCF estate. Instead, it composes specialised tools: Aria Operations for infrastructure, Prometheus for Kubernetes metrics, Loki for logs, Tempo for traces, unified under Grafana as the single query and dashboard layer.

Choosing the right tool for each signal

The tool selection question is frequently overcomplicated. The principles are simple.

Metrics: Prometheus vs Aria Operations vs InfluxDB
Prometheus is the Kubernetes-native choice. Its pull model, label-based data model, and PromQL are optimised for the cardinality patterns you encounter in Kubernetes. Aria Operations is superior for vSphere-layer metrics — it understands the vSphere object hierarchy and provides out-of-the-box correlation between host, cluster and VM objects. InfluxDB excels in time-series workloads with high write throughput and SQL-like queries (Flux), but lacks native Kubernetes integration. In a VCF context: use Aria Operations for infra metrics, Prometheus for Kubernetes metrics. They complement rather than compete.
Logs: Loki vs Elasticsearch vs Splunk
Loki is the lightweight choice for Kubernetes-first environments. It indexes only labels (not the full log body), making it significantly cheaper to operate than Elasticsearch. Its LogQL query language is modeled on PromQL, so the same team that operates Prometheus can operate Loki. Elasticsearch (ELK stack) is the better choice when you need full-text search across log content or complex aggregation pipelines. Splunk is the enterprise choice with the highest operational cost and the richest security analytics feature set. For most platform teams running VCF + VKS: start with Loki. Its storage cost is typically 10-20x lower than ELK for equivalent log volume.
Traces: Jaeger vs Tempo vs Zipkin
Jaeger and Zipkin are both mature distributed tracing backends with UI support for visualising trace waterfalls. Tempo is Grafana Labs' trace storage backend, designed to be query-only from Grafana Explore — it has no standalone UI but integrates natively with Loki (log-to-trace correlation) and Prometheus (exemplar-to-trace correlation). If your team already operates Grafana, Tempo is the lowest-friction choice. If you need a standalone trace UI without Grafana, Jaeger is the reference.
Collection: OpenTelemetry Collector vs language-specific agents
The OpenTelemetry Collector is the standard processing pipeline for OTel signals. It receives data via OTLP (or legacy formats), processes it (attribute manipulation, sampling, batching), and exports to multiple backends. The alternative — sending signals directly from the application to the backend — creates tight coupling between application code and infrastructure topology. The Collector acts as the vendor-neutral decoupling layer. For VCF deployments: run the Collector as a Deployment (one per cluster) for traces and metrics, and as a DaemonSet if you need host-level collection.

The four golden signals and where to apply them

The four golden signals — latency, traffic, errors, and saturation — were defined by Google’s SRE book as the minimum instrumentation required for production service readiness. They map onto the three observability pillars in a predictable way.

Latency is best measured with traces (P50/P95/P99 at the span level) and histograms (Prometheus _bucket metrics). Logs can record latency per request but aggregate poorly.

Traffic is a metric signal: requests per second, bytes per second, events per second. Prometheus counters are the natural fit.

Errors live in both metrics (error rate counters) and logs (error-level log records). Traces carry error status on spans, enabling you to correlate “this trace contains an error” with the specific service responsible.

Saturation is primarily an infrastructure metric: CPU ready time, memory pressure, disk queue depth, network buffer drops. These come from the infrastructure layer — Aria Operations or node-exporter — rather than from application instrumentation.

Getting started without boiling the ocean

The most common failure mode in observability projects is attempting to instrument everything simultaneously. The result is a months-long deployment that delivers no value until everything is complete.

The pragmatic approach is to start with the two signals that deliver the fastest time-to-value for production operations. Metrics first — deploy kube-prometheus-stack with the default scrape configuration and you immediately have Kubernetes component health, node resource usage, and pod restart counts without writing a single line of application code. Logs second — a Fluent Bit DaemonSet with the Kubernetes metadata filter gives you structured pod logs with namespace, pod name, container name and node labels immediately queryable in Loki.

Traces come last, because they require application instrumentation. Auto-instrumentation agents for Java, Python, Go and Node.js can reduce the overhead significantly, but they still require a deployment change per application. Reserve distributed tracing for services where latency analysis is a documented production requirement.

The following articles in this series cover each layer in detail: Prometheus and Grafana deployment patterns for VKS in the next article, Loki and Fluent Bit configuration in the third, OpenTelemetry Collector pipeline design in the fourth, and Aria Operations integration with the open-source stack in the fifth.

References.

Get the next one by email

New articles and series, sent when they are published. No other mail.

One click to unsubscribe, any time.

Back to blog
Share

Related articles

  1. 16 min read

    FinOps cost models: what AWS, Azure and GCP bill — and what VCF calculates

    An EKS cluster-hour, an AKS tier, a GKE Pod request and depreciated VCF hardware are not four values of one variable. What each platform bills, and what VCF calculates instead.

  2. 23 min read

    Network policies and Cilium: building a defensible default-deny

    The NetworkPolicy API ships with Kubernetes; enforcing it is the CNI's job. What Cilium adds, what stays standard, and how to reach default-deny by watching real flows before blocking any.

  3. 18 min read

    Kubernetes RBAC: the foundations, and the pitfalls that survive an audit

    Every one of these pitfalls is published on kubernetes.io. What is missing is the ordering — and the path that leads from a vSphere Namespace straight to cluster-admin.

Follow along

New articles, thoughts, and updates.