This repository contains the qlack-lgtm Helm chart, which deploys a complete observability stack built around Grafana Loki, Mimir, Tempo, Grafana, and the OpenTelemetry Collector.
The chart itself lives in helm/, and the chart name in helm/Chart.yaml is qlack-lgtm.
The chart installs and wires together the following components:
- OpenTelemetry Collector (
otelCollector) for ingesting OTLP telemetry from applications, with optional Kubernetes and node metrics collection - Grafana Loki for log storage and querying
- Grafana Mimir for Prometheus-compatible metrics storage
- Grafana Tempo for distributed tracing
- Grafana with pre-provisioned datasources and a built-in QLACK dashboard
By default, the deployment works like this:
- Collection
- The OpenTelemetry Collector runs as a DaemonSet.
- It accepts OTLP traces, metrics, and logs from applications on ports
4317and4318. - Host, kubelet, and cluster metrics collection is supported, but disabled by default.
- Processing
- The collector applies batching and memory limiting.
- Export
- Logs are exported to Loki
- Metrics are exported to Mimir
- Traces are exported to Tempo
- Visualization
- Grafana is pre-configured with Loki, Prometheus/Mimir, and Tempo datasources.
- A built-in dashboard is provisioned from
helm/files/dashboards/qlack-overview.json.
Grafana ships with a pre-provisioned QLACK OTEL-LGTM Observability Overview dashboard (set as the Grafana home page). It correlates metrics, logs, and traces from the LGTM stack in a single view. The screenshots below highlight its main sections.
Panels may show No data until applications start sending OTLP telemetry to the collector.
Rate, Errors, and Duration summary derived from Tempo metrics-generator span metrics, including request rate, error rate, p95/p99 latency, and trace/log counts for the selected range.
Per-service request rate, error rate, and p95 duration over time, plus tables of the slowest and most error-prone operations.
Log volume and error logs broken down by service, alongside a live view of recent application errors.
Tempo-backed trace tables for exploring recent, slow, error, and HTTP 5xx traces, with root-cause hint panels for deeper investigation.
Before deploying, note these defaults from helm/values.yaml:
- Container log scraping is disabled by default:
otelCollector.presets.logsCollection.enabled: false- This means application logs are expected to arrive via OTLP, unless you explicitly enable collector log scraping.
- Kubernetes and node metrics collection is disabled by default:
otelCollector.presets.hostMetrics.enabled: falseotelCollector.presets.kubeletMetrics.enabled: falseotelCollector.presets.clusterMetrics.enabled: false- Enable these values if you want the collector to collect host, kubelet, and cluster-level Kubernetes metrics.
- Grafana Ingress is disabled by default:
- Enable it and set your own host/TLS values if you want external access through an ingress controller.
- Grafana persistence is enabled by default:
- Grafana data is stored on a PVC so password changes and other state survive pod recreation.
- Grafana admin credentials default to
admin/admin:- Out of the box the chart sets
adminUser: adminandadminPassword: adminfor easy first-time access. - For real deployments either supply an existing Kubernetes Secret (Option A) or let this chart create one (Option B) — see the Quick start section.
- Out of the box the chart sets
- Image pull secrets are empty by default:
- Set
global.imagePullSecrets,loki.imagePullSecrets,mimir.image.pullSecrets, ortempo.tempo.pullSecretsonly if your environment uses private registries.
- Set
- Storage backends are configured for filesystem/local persistence, which is suitable for evaluation or simpler setups, but usually not enough for production-grade HA deployments.
- Kubernetes
1.20+ - Helm
3.x - A StorageClass / persistent volumes suitable for the stateful components
- An Ingress controller if you keep
grafana.ingress.enabled=true - Grafana admin credentials — see the Grafana admin credentials section below. The chart works out of the box with Grafana's built-in defaults (
admin/admin), but you should supply real credentials for any non-throwaway deployment.
This is the most important part: the chart path in this repository is ./helm, not ./helm/qlack-lgtm.
From the repository root:
helm upgrade --install qlack-lgtm ./helm \
--namespace lgtm \
--create-namespaceThis is the recommended command because it works for both first install and later upgrades.
If you prefer a plain install and the release does not already exist:
helm install qlack-lgtm ./helm \
--namespace lgtm \
--create-namespaceThese commands are safe and useful before a real install:
helm dependency list ./helm
helm lint ./helm
helm template qlack-lgtm ./helm > rendered.yaml
helm upgrade --install qlack-lgtm ./helm \
--namespace lgtm \
--create-namespace \
--dry-run --debugThis repository already contains vendored chart archives under helm/charts/, so in normal use you can usually deploy directly from ./helm without rebuilding dependencies first.
If you need to rebuild dependencies manually, use:
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm dependency build ./helmUse helm dependency build ./helm when:
- you cloned the repository but
helm/charts/is missing, - you want to reconstruct dependencies from
Chart.lock, or - Helm reports missing chart dependencies.
For a normal install from this repository, it is not strictly required as long as the vendored charts are already present and valid.
If you want to refresh the lock-resolved dependencies instead of just rebuilding from the lock file, you can also run:
helm dependency update ./helmYou generally do not need to run helm repo add ... just to install this repository as-is.
By default, the chart sets adminUser: admin and adminPassword: admin for easy first-time access.
This is suitable for quick evaluation only. For any shared or long-lived deployment, configure your own Grafana admin credentials using one of the options below.
Example values.override.yaml:
grafana:
ingress:
enabled: true
hosts:
- grafana.example.com
tls:
- hosts:
- grafana.example.com
admin:
existingSecret: grafana-admin
userKey: admin-user
passwordKey: admin-password
global:
imagePullSecrets:
- name: my-registry-secretCreate the secret before installing:
kubectl -n lgtm create secret generic grafana-admin \
--from-literal=admin-user=admin \
--from-literal=admin-password='change-me'Example values.override.yaml:
grafana:
ingress:
enabled: false
admin:
create: true
existingSecret: grafana-admin
userKey: admin-user
passwordKey: admin-password
username: admin
password: change-me
global:
imagePullSecrets: []With this option, you do not need to create the secret manually.
Then deploy with:
helm upgrade --install qlack-lgtm ./helm \
--namespace lgtm \
--create-namespace \
-f values.override.yamlBy default every persistent volume (Loki, Mimir, Tempo and Grafana) is
provisioned using each cluster's default StorageClass, so no configuration is
required. If you want specific components to use a particular StorageClass, set
the relevant field(s) — for example in a values.override.yaml:
loki:
singleBinary:
persistence:
storageClass: fast-ssd
mimir:
ingester:
persistentVolume:
storageClass: fast-ssd
store_gateway:
persistentVolume:
storageClass: fast-ssd
compactor:
persistentVolume:
storageClass: fast-ssd
ruler:
persistentVolume:
storageClass: fast-ssd
alertmanager:
persistentVolume:
storageClass: fast-ssd
tempo:
persistence:
storageClassName: fast-ssd
grafana:
persistence:
storageClassName: fast-ssdYou only need to set the components you care about; any field left unset keeps
using the cluster's default StorageClass. The same fields are also present (as
commented-out examples) in helm/values.yaml.
The full configuration lives in helm/values.yaml. The table below highlights defaults that are especially important when deploying.
| Parameter | Default | Notes |
|---|---|---|
global.imagePullSecrets |
[] |
Set only if your environment uses private registries |
otelCollector.enabled |
true |
Collector is enabled by default |
otelCollector.mode |
daemonset |
One collector pod per node |
otelCollector.presets.logsCollection.enabled |
false |
Pod stdout/stderr scraping is off by default |
otelCollector.presets.hostMetrics.enabled |
false |
Host metrics enabled |
otelCollector.presets.kubeletMetrics.enabled |
false |
Kubelet metrics enabled |
otelCollector.presets.clusterMetrics.enabled |
false |
Cluster metrics enabled |
loki.enabled |
true |
Loki enabled |
loki.deploymentMode |
Monolithic |
Single-binary style deployment |
loki.loki.storage.type |
filesystem |
Local filesystem storage |
mimir.enabled |
true |
Mimir enabled |
mimir.mimir.structuredConfig.blocks_storage.backend |
filesystem |
Local filesystem blocks storage |
tempo.enabled |
true |
Tempo enabled |
tempo.tempo.storage.trace.backend |
local |
Local trace storage |
tempo.tempo.metricsGenerator.enabled |
true |
Tempo generates span metrics and service graph metrics |
grafana.enabled |
true |
Grafana enabled |
grafana.ingress.enabled |
false |
Enable and set your own ingress host/TLS values if needed |
grafana.ingress.hosts[0] |
grafana.example.com |
Example host used when ingress is enabled |
grafana.persistence.enabled |
true |
Grafana state is stored on a PVC |
grafana.admin.create |
false |
When true, this chart creates the Grafana admin secret |
grafana.admin.existingSecret |
"" |
Leave empty to use adminUser/adminPassword; set to a Secret name to use your own |
grafana.admin.userKey |
admin-user |
Username key inside the secret |
grafana.admin.passwordKey |
admin-password |
Password key inside the secret |
grafana.grafana.ini.dashboards.default_home_dashboard_path |
/var/lib/grafana/dashboards/qlack/qlack-overview.json |
Built-in dashboard is the Grafana home page |
If you enable ingress, point DNS for your chosen hostname to your ingress controller and open Grafana there.
If you disable ingress, or just want quick local access:
kubectl -n lgtm port-forward svc/qlack-lgtm-grafana 8080:80Then open:
http://localhost:8080
If you installed the chart without configuring a custom Grafana admin Secret, use the default credentials:
- User:
admin - Password:
admin
⚠️ On first login Grafana will prompt you to change the password. Use the new password for all subsequent logins.
If you configured grafana.admin.existingSecret, use the credentials stored in that Secret.
If you also set grafana.admin.create: true, this chart creates the Secret using:
grafana.admin.usernamegrafana.admin.password
In Grafana you can:
- Open the default QLACK dashboard
- Use Explore with:
- Loki for logs
- Prometheus for metrics stored in Mimir
- Tempo for traces
- Applications should send OTLP telemetry to the OpenTelemetry Collector on:
4317for OTLP/gRPC4318for OTLP/HTTP
- The built-in dashboard expects:
- traces in Tempo
- Tempo metrics-generator metrics in Mimir
- logs in Loki labeled appropriately
- Because container log scraping is disabled by default, log panels will stay empty unless:
- your applications send logs via OTLP, or
- you change the collector configuration to enable Kubernetes/container log collection
When Grafana persistence is enabled, the upstream Grafana Helm chart may run an
init-chown-data init container before starting Grafana. This init container tries to
recursively change the ownership of /var/lib/grafana so that the main Grafana container
can write to the persistent volume.
On some storage backends, especially pre-provisioned volumes, NFS-backed volumes, or volumes
with restrictive ownership settings, this ownership change may fail with errors such as
permission denied, operation not permitted, or read-only file system.
If the Grafana pod fails during the init-chown-data step and the volume is already writable
by the Grafana container user, you can disable the init container:
grafana:
initChownData:
enabled: falsehelm uninstall qlack-lgtm -n lgtm- European Dynamics SA: https://www.eurodyn.com



