k8s-loki-troubleshooting
Skill36 starsChanged 15 days agoApache-2.0View on GitHub
Use when Grafana Loki on Kubernetes rejects, drops or cannot query logs: clients getting 400, 401 or 429 from /loki/api/v1/push, "write operation failed", "has timestamp too old", "entry too far behind", "Per stream rate limit exceeded", "ingestion rate limit exceeded", "maximum active stream limit exceeded", "no org id" (missing X-Scope-OrgID tenant), Loki crashing at start with "validating config" or "invalid schema config", "failed to flush chunks", ring or memberlist errors ("empty ring", "too many unhealthy instances in the ring"), or queries failing with "the query time range exceeds the limit" or timing out. Investigates with kubectl get, logs and read-only Loki endpoints, and proposes fixes. Reads first and asks before changing anything.
In this repository31 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- k8s-aks-troubleshootingSkill
- k8s-api-troubleshootingSkill
- k8s-argocd-troubleshootingSkill
- k8s-autoscaling-troubleshootingSkill
- k8s-cert-manager-troubleshootingSkill
- k8s-cilium-troubleshootingSkill
- k8s-cloudnative-pg-troubleshootingSkill
- k8s-coredns-troubleshootingSkill
- k8s-envoy-gateway-troubleshootingSkill
- k8s-envoy-troubleshootingSkill
- k8s-external-secrets-troubleshootingSkill
- k8s-fluent-bit-troubleshootingSkill
- k8s-flux-troubleshootingSkill
- k8s-gatekeeper-troubleshootingSkill
- k8s-gateway-api-troubleshootingSkill
- k8s-grafana-troubleshootingSkill
- k8s-helm-troubleshootingSkill
- k8s-istio-troubleshootingSkill
- k8s-kyverno-troubleshootingSkill
- k8s-network-troubleshootingSkill
- k8s-node-troubleshootingSkill
- k8s-opentelemetry-collector-troubleshootingSkill
- k8s-prometheus-troubleshootingSkill
- k8s-rbac-troubleshootingSkill
- k8s-storage-troubleshootingSkill
- k8s-triageSkill
- k8s-upgrade-readinessSkill
- k8s-velero-troubleshootingSkill
- k8s-workload-troubleshootingSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 38
Never read Secrets. Loki's config may hold storage keys: if it is in a Secret, do not read it.
- Very specific: line 41
Avoid kubectl describe pod on Loki: it prints literal environment values.
- Distinctive: line 162
After a client's fix rolls out, restart the client to retry at once:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Loki troubleshooting
Find out why Loki does not accept, keep or return logs, and propose a fix. Read first, ask before changing. Run the investigation commands freely. Run a command under an "Ask first" line only after the user approves that exact command; if your credentials do not allow it, give it to the user to run. Never run a "Proposed fix"; hand it to the user.
Clients (Promtail, Grafana Alloy, Fluent Bit, the OpenTelemetry Collector) push log
lines to /loki/api/v1/push. The distributor validates each line (labels, size,
age) and applies the tenant's ingestion rate; the ingester applies per-stream limits
and writes chunks to storage; queriers answer LogQL queries. In monolithic mode one pod
(-target=all) runs every part; in microservices mode each part is its own workload.
Loki answers a refused push with 400 (invalid, not retried), 429 (rate limit,
retried) or 401 (no tenant), and logs refused pushes as msg="write operation
failed" details="<reason>", except 401s, which it does not log.
The commands use placeholders: my-namespace, my-loki (the Loki workload, its Service
and its ConfigMap) and my-app-logger (a client). Replace them with the real names.
Never read Secrets. Loki's config may hold storage keys: if it is in a Secret, do not
read it; if it is in a ConfigMap, read only the parts you need and never repeat a key,
password or token you see. Prefer the /config endpoint, which masks typed secret fields.
Avoid kubectl describe pod on Loki: it prints literal environment values.
Never call /flush or /ingester/shutdown, not even with GET: Loki flushes all
chunks or shuts the ingester down. Never POST to a ring page (forget= removes an
instance). Use only the read endpoints listed here.
When to use
- A log agent reports 4xx errors from Loki, or logs are missing in Grafana.
- Loki pods crash, restart, or are not Ready.
- Queries fail, time out, or return nothing for data that was sent.
Hand-offs, by skill name. When the evidence points elsewhere, continue with that skill; if it is not installed, keep going with the steps here and tell the user which skill would help:
- The client cannot reach Loki at all (DNS, Service, NetworkPolicy):
k8s-network-troubleshooting. - The log agent itself fails (Fluent Bit, the OpenTelemetry Collector):
k8s-fluent-bit-troubleshooting,k8s-opentelemetry-collector-troubleshooting. - Grafana's Loki datasource fails while Loki answers:
k8s-grafana-troubleshooting. - Loki pods are Pending or OOMKilled:
k8s-workload-troubleshooting; a full volume:k8s-storage-troubleshooting.
Investigate
Work through the steps in order. Stop when you have the cause and its evidence.
1. See Loki's pods and the client's result. The HTTP status the client got points to the part that refused it.
kubectl get pods -n my-namespace -o wide
kubectl logs -n my-namespace deployment/my-app-logger --tail=202. Read Loki's log: refused pushes, start-up errors, storage and ring errors.
kubectl logs -n my-namespace deployment/my-loki --tail=200 | grep -E 'level=(error|warn)'
kubectl logs -n my-namespace deployment/my-loki --previous --tail=50
kubectl get events -n my-namespace --sort-by=.lastTimestamp3. Check where the config lives and what it sets: auth_enabled, the limits and
the schema. Check the kind of object first; a Secret is not read. Match only the keys
you need, so storage credentials near them are not printed.
kubectl get deployment my-loki -n my-namespace -o jsonpath='{.spec.template.spec.containers[0].args}{"\n"}{range .spec.template.spec.volumes[*]}{.name}{" "}{.configMap.name}{.secret.secretName}{"\n"}{end}'
kubectl get configmap my-loki -n my-namespace -o jsonpath='{.data.config\.yaml}' | grep -E 'auth_enabled|store:|schema:|period:|reject_old_samples|ingestion_rate|ingestion_burst|per_stream_rate|max_global_streams|max_line_size'4. Ask Loki itself, through the API server's service proxy, if your credentials
allow get on services/proxy (the built-in view role does not). With
auth_enabled: true the query endpoints need a tenant header and answer no org id
here; the status endpoints below do not.
kubectl get --raw /api/v1/namespaces/my-namespace/services/my-loki:http-metrics/proxy/ready
kubectl get --raw /api/v1/namespaces/my-namespace/services/my-loki:http-metrics/proxy/services
kubectl get --raw "/api/v1/namespaces/my-namespace/services/my-loki:http-metrics/proxy/config?mode=diff"
kubectl get --raw /api/v1/namespaces/my-namespace/services/my-loki:http-metrics/proxy/metrics | grep -E 'loki_discarded_samples_total|status_code="(4|5)'5. Open the matching reference and follow its steps:
| What you see | Reference |
Pushes refused (400, 401, 429), write operation failed, tenants, limits | references/ingestion.md |
| Loki does not start, not Ready, ring and memberlist, storage, flushes, retention, queries | references/startup-storage-queries.md |
Read the results
What the common findings mean (Loki 3.7):
- Client 400 and
msg="write operation failed" details="entry for stream '{app=\"my-app\", service_name=\"my-app\"}' has timestamp too old: 2020-09-13T12:26:40Z, oldest acceptable timestamp is: ...": the lines are older thanreject_old_samples_max_age(7 days by default). Loki adds theservice_namelabel itself. The client's clock or its timestamps are wrong, or it replays old logs. - Client 401 and nothing in Loki's log:
auth_enabled: true(multi-tenant) and the client sends noX-Scope-OrgIDheader; Loki answersno org id. Every client and the Grafana datasource need the tenant ID. - Client 429 with
Per stream rate limit exceededoringestion rate limit exceeded for user ...: a stream or the tenant sends more thanper_stream_rate_limit(3MB/s) oringestion_rate_mb(4MB/s) allow. Clients retry 429s, so logs arrive late or not at all. - Loki in CrashLoopBackOff with
msg="validating config" err="CONFIG ERROR: invalid schema config: validating period_config: tsdb must always have periodic config for index set to 24h": thetsdbindex needsperiod: 24h. Clients then getconnection refusedor no endpoints. failed to flush chunks: ...: the ingester cannot write to object storage; the wrapped error names the bucket, credentials or network problem. Data stays in memory and the WAL until it can.too many unhealthy instances in the ringorempty ring: ingesters are not ACTIVE or not found (memberlist cannot join, pods not Ready).
State the cause in one sentence, then the evidence you saw (the client's status, Loki's log line, the config field), then the proposed fix.
Proposed fix
Show each fix to the user before running it: what it changes and how to undo it. Loki's config, its limits and its storage are shared by every client and tenant: never change them yourself; hand them to the user as proposed fixes. A client's own config (its timestamps, its tenant header, its URL) belongs to that client's owners. Prefer fixing the source (the Helm values, the manifests in Git). Write each undo with the values you found.
Change Loki's config in its source and roll it out, for example index.period: 24h, or
limits_config.reject_old_samples_max_age for a client that must replay older logs:
Proposed fix: review before running. The agent does not run this.
kubectl apply -f my-loki-config.yaml
kubectl rollout restart deployment/my-loki -n my-namespace
# Undo: kubectl apply -f my-loki-config-before.yaml, then restart my-loki againAfter a client's fix rolls out, restart the client to retry at once:
Ask first: the agent runs this only after the user approves it.
kubectl rollout restart deployment/my-app-logger -n my-namespace
# Undo: none needed; the restart only recreates the pods with the same templateSources
Checked against the Loki 3.7 documentation and source (v3.7.9):
- Troubleshoot log ingestion and request validation and rate limits.
- Troubleshoot operations:
rings, memberlist,
-verify-config. - Multi-tenancy, HTTP API, deployment modes, schema and retention.
- Helm install: the OSS chart is now in grafana-community/helm-charts.
- Messages from the source:
validation/validate.go,
ingester/flush.go
and storage/config/schema_config.go.
The docs'
failed to store chunks: storage unavailabledoes not exist in 3.7. The refusals quoted here were seen on a Kubernetes 1.37 kind cluster with Loki 3.7.9.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

