Hubble UI, when you first spin it up, can feel like a black box, but it’s actually a surprisingly simple system for visualizing network flows generated by Cilium.
Here’s a quick look at it in action. Imagine you’ve got a couple of pods, frontend-abcde and backend-fghij, and you want to see how they’re talking.
# First, make sure you have Hubble CLI installed and configured to talk to your Hubble agent
hubble observe --output json | jq '. | select(.Source.PodName == "frontend-abcde" and .Destination.PodName == "backend-fghij")'
This command will stream flow data. You’ll see entries like this, which Hubble UI then renders graphically:
{
"Timestamp": "2023-10-27T10:00:00Z",
"Source": {
"Namespace": "default",
"PodName": "frontend-abcde",
"PodNamespace": "default",
"IP": "10.0.1.5",
"Labels": {
"io.kubernetes.pod.name": "frontend-abcde",
"app": "frontend"
}
},
"Destination": {
"Namespace": "default",
"PodName": "backend-fghij",
"PodNamespace": "default",
"IP": "10.0.2.10",
"Labels": {
"io.kubernetes.pod.name": "backend-fghij",
"app": "backend"
}
},
"L7": {
"HTTP": {
"Code": 200,
"Method": "GET",
"URL": "/api/data"
}
},
"Network": {
"Protocol": "TCP",
"Port": 8080
},
"Verdict": "forwarded"
}
Hubble UI’s core job is to ingest these flow records, aggregate them, and present them in a user-friendly, interactive graph. It’s not just about showing connections; it’s about showing what is happening over those connections, down to the L7 protocol level if Cilium is configured for it. This allows you to see not only that frontend is talking to backend, but that it’s making GET requests to /api/data over TCP port 8080, and that these requests are being successfully forwarded.
The main problem Hubble UI solves is making the complex, dynamic network traffic within a Kubernetes cluster visible and understandable. Without it, you’re left with fragmented logs and the daunting task of correlating events across numerous pods and services. Hubble UI provides a single pane of glass, allowing you to trace requests, identify bottlenecks, and troubleshoot connectivity issues by visualizing the actual flow of data.
Internally, Hubble works by having agents (typically running as a DaemonSet or as part of the Cilium agent itself) capture network packets. These packets are then processed to extract flow information, including source/destination IPs, ports, protocols, and L7 application data (like HTTP methods and URLs) if available. This flow data is then sent to a central Hubble server, which stores and indexes it. The Hubble UI is a frontend that queries this server to build and display the network graph.
The exact levers you control are primarily in the Cilium configuration. Enabling network policy observability (enable-l7-proxy: true in Cilium’s ConfigMap) is crucial for seeing L7 details. You also configure where the Hubble server receives its data, typically via a Kubernetes Service. The Hubble CLI and UI then connect to this server.
What most people don’t realize is that the "verdict" field in the flow data (forwarded, dropped, error) isn’t just a label; it’s the direct output of Cilium’s CNI logic. When you see a dropped verdict, it means a network policy explicitly denied that flow before it even reached the destination pod. This makes Hubble an indispensable tool for validating and debugging your network policies in real-time.
The next step after visualizing flows is often to start filtering and searching these flows based on specific criteria like namespace, pod labels, or L7 request details.