MONITORING_FIX.md
Rama main · réplica de lectura del repositorio original.
# Monitoring Stack Fix
## Issues Identified
1. **Memory Quota Exceeded**: Alloy and Grafana pods cannot start due to `monitoring-quota` having only 512Mi memory limit
2. **Quota Ownership Conflict**: The quota is owned by `ai-alloy` app but should be owned by `mimir` app
3. **Loki Template Error**: Missing `bucketNames` at the correct level in storage config
4. **Incorrect Sync Wave Order**: Alloy (collector) was deploying before Mimir/Loki (storage backends)
## Current State
```bash
# Current quota (WRONG - too low)
requests.memory: 512Mi
used: 370Mi (alloy 256Mi + tempo 64Mi + overhead)
# Desired quota (from mimir config)
requests.memory: 8Gi
```
## Root Cause Analysis
### Sync Wave Anti-Pattern (FIXED)
**Before:**
- Wave -2: Alloy (collector) ❌
- Wave -1: Mimir, Loki, Tempo (storage) ❌
**Problem:** Alloy deployed first and created the namespace with a 512Mi quota, preventing Mimir's correct 8Gi quota from being applied.
**After (CORRECT):**
- Wave -2: Mimir, Loki, Tempo (storage backends with quota) ✅
- Wave -1: Alloy (collector) ✅
- Wave 0: Grafana (visualization) ✅
### Why This Order Matters
1. **Storage backends must exist before collectors** - Alloy needs Mimir and Loki endpoints to send data to
2. **Namespace infrastructure (quotas) should deploy with the first app** - Mimir now creates the namespace with correct quota
3. **Collectors depend on storage** - Alloy config references `mimir-nginx` and `loki-gateway` services
This follows the standard monitoring architecture pattern:
```
Infrastructure (quotas/limits) → Storage (Mimir/Loki/Tempo) → Collection (Alloy) → Visualization (Grafana)
```
## Fixes Applied
### 1. ✅ Loki Storage Configuration Fixed
Moved `bucketNames` from under `s3` to the `storage` level to match Loki chart expectations.
### 2. ✅ Sync Wave Order Corrected
- Mimir: -1 → -2 (storage backend, creates namespace with correct quota)
- Loki: -1 → -2 (storage backend)
- Tempo: -1 → -2 (storage backend)
- Alloy: -2 → -1 (collector, now deploys after storage)
- Grafana: 0 (unchanged, visualization layer)
### 3. ⚠️ Quota Ownership Transfer Required (Manual Step)
The monitoring quota is currently tracked by ArgoCD as belonging to the `alloy` application:
```
argocd.argoproj.io/tracking-id: ai-alloy:/ResourceQuota:monitoring/monitoring-quota
```
But it's defined in the `mimir` application's `extraObjects` with the correct 8Gi limit.
## Manual Steps Required
### Recommended Approach: Clean Slate Deployment
Since the sync wave order has been corrected, the cleanest approach is to delete and redeploy in the correct order:
```bash
# 1. Delete the old quota (owned by alloy)
kubectl delete resourcequota monitoring-quota -n monitoring
# 2. Sync in the correct order (storage backends first)
argocd app sync mimir # Wave -2: Creates namespace with correct 8Gi quota
argocd app sync loki # Wave -2: Storage backend
argocd app sync tempo # Wave -2: Storage backend
# 3. Wait for storage backends to be healthy
argocd app wait mimir --health
argocd app wait loki --health
argocd app wait tempo --health
# 4. Now sync the collector (depends on storage)
argocd app sync alloy # Wave -1: Collector
# 5. Finally sync visualization
argocd app sync grafana # Wave 0: Visualization
# 6. Verify the new quota
kubectl get resourcequota monitoring-quota -n monitoring -o yaml | grep -A 10 "spec:"
# Should show: requests.memory: 8Gi
```
### Alternative: Patch Existing Quota (If You Can't Redeploy)
### Alternative: Patch Existing Quota (If You Can't Redeploy)
```bash
# 1. Patch the quota to increase memory limit
kubectl patch resourcequota monitoring-quota -n monitoring --type=merge -p '
{
"spec": {
"hard": {
"requests.cpu": "4",
"requests.memory": "8Gi",
"limits.cpu": "16",
"limits.memory": "24Gi",
"count/pods": "40"
}
}
}'
# 2. Update the tracking annotation to point to mimir
kubectl annotate resourcequota monitoring-quota -n monitoring \
argocd.argoproj.io/tracking-id=mimir:/ResourceQuota:monitoring/monitoring-quota \
--overwrite
# 3. Sync applications (they will now respect the new sync wave order)
argocd app sync mimir loki tempo alloy grafana
```
## Verification
After applying the fix, verify all pods are running:
```bash
# Check quota usage
kubectl get resourcequota monitoring-quota -n monitoring
# Expected output should show:
# requests.memory: 370Mi/8Gi (plenty of headroom)
# Check all monitoring pods
kubectl get pods -n monitoring
# All pods should be Running:
# - alloy-* (DaemonSet - one per node)
# - grafana-*
# - loki-*
# - mimir-*
# - tempo-*
```
## Root Cause
The issue occurred because of an **anti-pattern in sync wave ordering**:
1. **Alloy deployed first** (sync-wave -2) before storage backends
2. **Alloy created the namespace** and somehow a 512Mi quota was applied (possibly from an old config or default)
3. **Mimir deployed second** (sync-wave -1) but couldn't update the existing quota
4. **Mimir's correct 8Gi quota definition was ignored** because the resource already existed
### Why the Original Order Was Wrong
```
❌ WRONG: Collector → Storage
- Alloy (collector) at wave -2
- Mimir/Loki/Tempo (storage) at wave -1
- Problem: Collector has nowhere to send data, creates namespace prematurely
```
```
✅ CORRECT: Storage → Collector
- Mimir/Loki/Tempo (storage) at wave -2
- Alloy (collector) at wave -1
- Benefit: Storage backends exist with correct quota, collector can immediately send data
```
This follows the fundamental monitoring architecture principle:
**Infrastructure → Storage → Collection → Visualization**
## Prevention
1. ✅ **Sync wave order corrected** - Storage backends now deploy before collectors
2. ✅ **Quota ownership clarified** - Only Mimir defines the monitoring-quota
3. ✅ **Loki storage config fixed** - Template will now render correctly
4. 📝 **Document the pattern** - Storage must always precede collection in monitoring stacks