This is the best way to learn Kubernetes and Observability at the same time.
The LGTM stack is an observability stack built around Grafana Labs components for logs, metrics, and traces. It is the open-source counterpart to things like the ELK/Prometheus stacks, but with Grafana as the central “pane of glass”.
What is the LGTM stack?
The acronym typically refers to four core components that work together as an integrated observability suite:
- Loki – Log aggregation and querying, optimized for labels and cheap storage rather than full-text indexing.
- Grafana – Visualization and alerting layer, providing dashboards and correlations across data sources.
- Tempo – Distributed tracing backend for storing and querying trace spans.
- Mimir (or Prometheus) – Metrics backend for large-scale time-series data.
Together, these give you the three pillars of observability (logs, metrics, traces) plus dashboards and alerting in one ecosystem.
High-level Architecture
In a typical deployment:
- Applications emit metrics (Prometheus format or OTLP), logs (via agents like Promtail or Alloy), and traces (OTLP) to a gateway or directly to the backends.
- Loki stores logs in an object-store-plus-index model, usually with cheap, large object storage and a relatively lean index.
- Mimir (or Prometheus in smaller setups) stores metrics as time-series, scraped or pushed from your workloads.
- Tempo stores traces, often using object storage and sampling strategies to control volume.
- Grafana connects to all of these as data sources and provides dashboards, unified queries, alerting rules, and correlations (e.g., jump from a metric spike to related logs and traces).
This design is meant to scale horizontally in Kubernetes and other distributed environments, and to be relatively cost-efficient in storage-heavy use cases.
Typical Use Cases
Common scenarios for using the LGTM stack include:
- Kubernetes cluster observability: cluster/node/pod metrics in Mimir/Prometheus, container logs in Loki, and service traces in Tempo, all visualized in Grafana.
- Microservices debugging: correlating a latency spike in metrics with trace spans in Tempo and then drilling into the exact log lines in Loki.
- Self-hosted alternative to SaaS APM: teams that want control over their observability data and cost profile use LGTM instead of fully managed commercial platforms.
For side projects and home labs, people often start with a minimal version (Grafana + Loki + Tempo + Prometheus) and later swap in Mimir when they hit scale or need multi-tenancy.
Advantages and Trade-offs
Some notable advantages:
- Tight integration: components are designed to work together, especially with Grafana’s dashboards and data-source plugins.
- Cost-conscious design: Loki and Tempo both lean on object storage and indexing strategies that try to keep costs down for high-volume data.
- Open source and CNCF-friendly: easy to integrate with OpenTelemetry and existing Prometheus setups.
Trade-offs to be aware of:
- Operational complexity: running Loki, Mimir, Tempo, and Grafana in HA mode (especially in Kubernetes) is non-trivial and involves tuning ingestion, compaction, and storage backends.
- Query ergonomics: Loki’s log query language and Tempo’s trace querying may feel different compared with traditional log search or vendor APM tools, requiring some learning.
- Scale planning: object storage, index backends, and retention strategies need careful design to avoid performance or cost surprises.
If you say what you’re running today (e.g., Prometheus + Loki + Grafana, or Datadog, etc.), a more concrete “from-here-to-LGTM” migration or architecture sketch can be outlined.
What is Kubernetes (K8s)?
Kubernetes is an open source platform for running and managing containerized applications across a cluster of machines. It automates deployment, scaling, and recovery of containers so applications stay in the desired state with minimal manual intervention.
Core idea
Kubernetes lets you describe how many instances of each component you want, how they should be exposed on the network, and what resources they need, using declarative configs (usually YAML). The system continuously compares this desired state to the actual state of the cluster and takes actions (scheduling, restarting, rescheduling) to reconcile the two.
Main building blocks
- Cluster: A set of machines (nodes) that run your workloads, split into control plane components and worker nodes.
- Pods: The basic unit of scheduling, typically one or a small group of tightly coupled containers sharing network and storage.
- Control plane: API server, scheduler, controller manager, and etcd, which together decide where pods run and track cluster state.
What Kubernetes does for you
Kubernetes handles container placement on nodes based on CPU, memory, and other constraints, and can automatically reschedule pods if nodes fail. It also provides built-in service discovery, load balancing, rolling updates, rollbacks, and autoscaling based on metrics such as CPU or custom signals.
Why it matters
By abstracting away individual servers, Kubernetes makes it easier to run microservices-based and cloud native applications consistently across on‑prem and cloud environments. Most major cloud providers now offer managed Kubernetes services, so teams can rely on the Kubernetes API and ecosystem as a standard layer for deployment and operations.
Components to focus on when implementing LGTM stack inside of a K8s Cluster
For running an LGTM stack inside Kubernetes, the key is to design around stateful services, ingestion, and access paths. The focus areas below assume Loki, Grafana, Tempo, and Mimir/Prometheus deployed in‑cluster.
Core Kubernetes primitives
- Namespaces: Separate an
observability(or similar) namespace for the LGTM components and possibly amonitoringnamespace for exporters and agents, to isolate RBAC, quotas, and network policies. - Deployments vs StatefulSets: Use StatefulSets for Loki, Tempo, and Mimir ingesters/queriers when they maintain identity or local cache; use Deployments for stateless API gateways, query frontends, and Grafana.
- Services: ClusterIP Services for internal communication between LGTM components and agents; LoadBalancer/Ingress for Grafana and any public query endpoints.
Storage and data durability
- PersistentVolumeClaims: Allocate PVCs (often via StorageClasses backed by SSD) for Loki indexes/chunks (if not fully remote), Tempo WAL/blocks cache, and Mimir components that rely on local disk.
- Object storage integration: Configure access (Secrets + ConfigMaps) for S3/GCS/MinIO buckets used by Loki, Tempo, and Mimir, as these are the primary durable stores in production setups.
- Backup and retention policies: Use ConfigMaps for retention settings and ensure the underlying storage class and bucket policies align with log/trace/metric retention goals.
Configuration, secrets, and discovery
- ConfigMaps: Centralize component configs (Loki
config.yaml, Tempotempo.yaml, Mimirmimir.yaml, Grafana datasources and dashboards) as ConfigMaps mounted into Pods or injected via init containers.[2][1] - Secrets: Store credentials for object storage, databases (if used), and Grafana admin/passwords as Kubernetes Secrets, referenced in LGTM pods via env vars or files.
- Service discovery: Rely on k8s Service DNS and labels/Selectors for Prometheus/Mimir scraping and for agents (Promtail/Alloy) to find LGTM endpoints.
Ingestion and agents
- DaemonSets: Run Promtail or Grafana Alloy as DaemonSets on every node to ship container logs to Loki and metrics/traces (via OTLP/Prometheus endpoints) to Mimir/Tempo.
- Pod annotations: Use standard scrape/otlp annotations or ServiceMonitor resources (if using the Prometheus Operator) so metrics exporters are automatically discovered.
- Resource requests/limits: Carefully size DaemonSets and ingesters (CPU/memory) to avoid log/trace backpressure or dropping data under load.
Networking, security, and multi-tenancy
- NetworkPolicies: Lock down access so only agents and observability components can talk to Loki/Mimir/Tempo ingestion endpoints, and restrict Grafana admin endpoints as needed.
- Ingress / Gateway: Expose Grafana and optional query APIs via Ingress or Gateway API with TLS termination and auth (OIDC/OAuth2, etc.).
- RBAC: Create minimal Roles/ClusterRoles for LGTM components to watch Pods/Endpoints (for service discovery) and to manage ConfigMaps/Secrets only where necessary.[1]
Scaling, reliability, and lifecycle
- HorizontalPodAutoscaler: Apply HPAs to stateless frontends (query-frontend, distributors, gateway, Grafana) based on CPU, QPS, or custom metrics to handle spikes.
- PodDisruptionBudgets: Add PDBs for ingesters, queriers, and gateways to maintain availability during node drains and upgrades.
- Affinity and topology: Use node affinity/anti‑affinity and topology spread constraints to spread replicas across nodes and zones, especially for stateful components.
If you describe your current cluster setup (managed vs bare‑metal, CSI, object store, scale), a concrete LGTM k8s manifest layout (which components as Deployments/StatefulSets and where to put DaemonSets/Ingress) can be sketched next.
The 5 Parts of Implement an LGTM stack in K8s: Architecture
Implement an LGTM stack in K8s: Architecture
Implement an LGTM stack in K8s: Bootstrap
Implement an LGTM stack in K8s: LGTM Stack
Implement an LGTM stack in K8s: Ingest External Metrics
Implement an LGTM stack in K8s: Debugging and Troubleshooting