Kubernetes Observability Query Practice
Explore how to effectively query Kubernetes observability data to monitor, troubleshoot, and optimize containerized applications.
Kubernetes Observability Query Practice is the discipline of formulating effective queries against metrics, log, and trace backends to answer specific operational questions about a cluster, covering query language idioms, common query patterns, performance pitfalls, and the habits that separate a query that quickly isolates a root cause from one that returns noise or times out.
Query Languages by Signal Type
PromQL for Metrics
Prometheus Query Language operates over time series identified by a metric name and a set of key-value labels, and is the dominant query language for Kubernetes metrics regardless of whether the backend is Prometheus itself, Mimir, Cortex, or Thanos.
sum(rate(http_requests_total{namespace="production", status=~"5.."}[5m])) by (deployment)
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{namespace="production"}[5m])) by (le, deployment)
)
LogQL for Logs
Grafana Loki's LogQL combines a label selector, similar in spirit to PromQL, with a line-filtering expression and optional parsing stages.
{namespace="production", app="checkout"} |= "OutOfMemoryError" | json | line_format "{{.message}}"
TraceQL for Traces
Grafana Tempo's TraceQL allows querying traces by span attributes directly, rather than only by trace ID.
{ .k8s.namespace.name = "production" && duration > 500ms && status = error }
Core Query Patterns
Rate, Errors, Duration (the RED Method)
A standard starting point for investigating any Kubernetes service is to query its request rate, error rate, and duration distribution together, since the combination quickly distinguishes "the service is under normal but heavy load" from "the service is failing" from "the service is slow but succeeding."
sum(rate(http_requests_total{deployment="checkout"}[5m]))
sum(rate(http_requests_total{deployment="checkout", status=~"5.."}[5m]))
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{deployment="checkout"}[5m])) by (le))
Utilization, Saturation, Errors (the USE Method)
For infrastructure-level resources such as nodes, the equivalent pattern queries utilization, saturation (queueing or throttling), and errors.
1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (node)
sum(rate(container_cpu_cfs_throttled_periods_total[5m])) by (pod) / sum(rate(container_cpu_cfs_periods_total[5m])) by (pod)
Drill-Down Sequencing
Effective query practice moves from coarse to fine: an aggregate query across a Deployment establishes whether a problem exists, a query grouped by (pod) isolates whether it affects all replicas or one, and a query filtered to the single implicated pod (or a correlated trace/log query for that pod) surfaces the specific cause.
Performance and Correctness Pitfalls
Cardinality Explosions
A query that groups by a high-cardinality label, such as pod in a cluster with thousands of frequently restarting pods, or worse, one that includes an unbounded label like a raw user ID, can generate a time series count in the millions, causing query timeouts or backend memory exhaustion; grouping by deployment or service rather than pod is usually sufficient and dramatically cheaper.
Rate Over Too Short a Window
Applying rate() over a window shorter than roughly four times the scrape interval produces noisy or statistically invalid results, since too few samples fall inside the window; a 15-second scrape interval generally requires at least a [1m] range for a stable rate calculation.
Unbounded Log Queries
A LogQL query without a label selector, or with an overly broad time range combined with a permissive line filter, forces the backend to scan enormous volumes of unindexed log lines; scoping first by namespace and app labels before applying any text filter keeps queries fast.
Habitual Practices
Saving Recurring Queries as Dashboards or Alerting Rules
Queries that prove useful during an investigation are promoted into permanent dashboard panels or alerting rules, so that the next occurrence of the same symptom is caught automatically rather than requiring the same manual investigation to be repeated.
groups:
- name: checkout-slo
rules:
- alert: CheckoutHighErrorRate
expr: sum(rate(http_requests_total{deployment="checkout", status=~"5.."}[5m])) / sum(rate(http_requests_total{deployment="checkout"}[5m])) > 0.02
for: 10m
Time-Range Discipline
Aligning the query time range tightly around the incident window, rather than querying broad ranges "just in case," both improves query performance and reduces the risk of misattributing an unrelated historical spike to the current investigation.
Relationship to Broader Observability Practice
Query practice is the skill layer built atop the infrastructure of metrics, telemetry pipelines, tracing, and correlation: even a perfectly instrumented cluster provides no operational value if the queries run against it are slow, cardinality-unsafe, or structured in a way that fails to isolate the actual root cause.