In mijn vorige post over Prometheus en Thanos behandelde ik de sidecar architectuur — Thanos Sidecar draait naast Prometheus, uploadt TSDB blocks naar object storage, en stelt data beschikbaar aan de Querier. Het werkt uitstekend voor clusters met stabiele connectiviteit naar je centrale infrastructuur.
Maar wat als je clusters aan de edge staan? Als ze uren of dagen connectiviteit kunnen verliezen? Als je tientallen of honderden kleine clusters draait en geen sidecar complexiteit op elk daarvan wilt?
Daar komt Thanos Receive om de hoek kijken. Push in plaats van pull.
Het Probleem met Sidecars op Schaal
Het sidecar model vereist:
- Thanos Sidecar draaiend op elke Prometheus instance
- Directe object storage toegang vanaf elk cluster
- Stabiele netwerkconnectiviteit voor block uploads
- gRPC connectiviteit naar de centrale Querier voor real-time queries
Voor een handvol clusters in hetzelfde datacenter is dit prima. Maar overweeg:
- Edge locaties met intermitterende internetconnectiviteit
- Air-gapped omgevingen die alleen outbound kunnen pushen
- Honderden kleine clusters waar sidecar overhead optelt
- Multi-tenant platforms waar je niet alle clusters beheert
Het sidecar model werkt niet meer. Je hebt iets simpelers nodig.
Maak Kennis met Thanos Receive
Thanos Receive draait het model om. In plaats van sidecars die data uit Prometheus halen, pusht Prometheus metrics direct naar een centrale Receive component.
flowchart TD
subgraph edge["Edge Clusters"]
subgraph E1["Site A (Fabriek)"]
P1["Prometheus"]
end
subgraph E2["Site B (Magazijn)"]
P2["Prometheus"]
end
subgraph E3["Site C (Retail)"]
P3["Prometheus"]
end
end
subgraph central["Centraal Cluster"]
R["Thanos Receive<br/>(HA cluster)"]
Q["Thanos Querier"]
SG["Store Gateway"]
C["Compactor"]
OS["Object Storage"]
end
P1 -->|"remote_write"| R
P2 -->|"remote_write"| R
P3 -->|"remote_write"| R
R --> OS
OS --> SG
SG --> Q
R --> Q
OS --> C
Q --> G["Grafana"]
Het kernpunt: Prometheus heeft al remote_write. Het is een ingebouwde feature die samples pusht naar elk compatibel endpoint. Thanos Receive implementeert deze API.
Waarom Push Beter is voor Edge
1. Simpelere Edge Deployment
Geen sidecar. Geen object storage credentials aan de edge. Geen gRPC poorten om te exposen. Alleen Prometheus met een remote_write URL.
# De HELE edge configuratie
global:
external_labels:
cluster: factory-site-a
region: europe-west
remote_write:
- url: https://thanos-receive.central.example.com/api/v1/receive
bearer_token_file: /etc/prometheus/token
Dat is alles. Het edge cluster hoeft niets te weten over object storage, Thanos componenten of iets anders. Het pusht gewoon metrics.
2. Tolereert Connectiviteitsverlies
Als connectiviteit wegvalt, buffert Prometheus samples lokaal. Als connectiviteit terugkeert, haalt het in. De Write-Ahead Log (WAL) regelt dit automatisch.
remote_write:
- url: https://thanos-receive.central.example.com/api/v1/receive
queue_config:
capacity: 100000 # Buffer grootte
max_shards: 50 # Parallelle send workers
min_shards: 1
max_samples_per_send: 5000
batch_send_deadline: 30s
min_backoff: 1s
max_backoff: 5m # Exponential backoff bij failure
Ik heb edge clusters gezien die 4+ uur connectiviteit verloren en succesvol inhaalden toen het netwerk terugkwam. De WAL hield alles veilig.
3. Alleen Outbound Connectiviteit
Edge locaties hebben vaak restrictieve firewalls. Inbound connecties? Geblokkeerd. VPNs? Nachtmerrie om te onderhouden. Maar outbound HTTPS naar een bekend endpoint? Meestal toegestaan.
Push architectuur sluit aan bij hoe edge netwerken daadwerkelijk werken.
4. Lager Resource Gebruik aan Edge
Geen sidecar betekent:
- Minder geheugen op edge nodes
- Geen extra container om te beheren
- Geen gRPC connecties om te onderhouden
- Simpelere failure modes
Voor resource-beperkte edge devices maakt dit uit.
Thanos Receive Opzetten
Centraal Cluster: Receive Deployment
Thanos Receive is stateful — het schrijft naar disk voordat het upload naar object storage. Draai het als StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: thanos-receive
namespace: monitoring
spec:
serviceName: thanos-receive
replicas: 3
selector:
matchLabels:
app: thanos-receive
template:
metadata:
labels:
app: thanos-receive
spec:
containers:
- name: thanos-receive
image: quay.io/thanos/thanos:v0.34.0
args:
- receive
- --http-address=0.0.0.0:10902
- --grpc-address=0.0.0.0:10901
- --remote-write.address=0.0.0.0:19291
- --tsdb.path=/var/thanos/receive
- --objstore.config-file=/etc/thanos/objstore.yaml
- --label=receive_replica="$(POD_NAME)"
- --tsdb.retention=6h
# Hashring voor HA distributie
- --receive.hashrings-file=/etc/thanos/hashring.json
- --receive.local-endpoint=$(POD_NAME).thanos-receive.monitoring.svc:10901
ports:
- name: http
containerPort: 10902
- name: grpc
containerPort: 10901
- name: remote-write
containerPort: 19291
volumeMounts:
- name: data
mountPath: /var/thanos/receive
- name: objstore-config
mountPath: /etc/thanos
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumes:
- name: objstore-config
secret:
secretName: thanos-objstore-secret
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: longhorn
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
Hashring voor High Availability
Bij meerdere Receive replicas heb je een hashring nodig om inkomende data te distribueren:
[
{
"endpoints": [
"thanos-receive-0.thanos-receive.monitoring.svc:10901",
"thanos-receive-1.thanos-receive.monitoring.svc:10901",
"thanos-receive-2.thanos-receive.monitoring.svc:10901"
]
}
]
Sla dit op in een ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: thanos-receive-hashring
namespace: monitoring
data:
hashring.json: |
[
{
"endpoints": [
"thanos-receive-0.thanos-receive.monitoring.svc:10901",
"thanos-receive-1.thanos-receive.monitoring.svc:10901",
"thanos-receive-2.thanos-receive.monitoring.svc:10901"
]
}
]
De hashring zorgt dat samples van dezelfde time series altijd naar dezelfde Receive instance gaan, wat duplicaten voorkomt.
Load Balancer Service
Expose Receive voor externe clusters:
apiVersion: v1
kind: Service
metadata:
name: thanos-receive-lb
namespace: monitoring
spec:
type: LoadBalancer
ports:
- name: remote-write
port: 443
targetPort: 19291
selector:
app: thanos-receive
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: thanos-receive
namespace: monitoring
annotations:
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
tls:
- hosts:
- thanos-receive.example.com
secretName: thanos-receive-tls
rules:
- host: thanos-receive.example.com
http:
paths:
- path: /api/v1/receive
pathType: Prefix
backend:
service:
name: thanos-receive
port:
number: 19291
Edge Cluster: Prometheus Configuratie
Op elk edge cluster, configureer Prometheus om metrics te pushen:
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
retention: 24h # Lokale retentie voor edge queries
externalLabels:
cluster: factory-site-a
region: europe-west
environment: production
remoteWrite:
- url: https://thanos-receive.example.com/api/v1/receive
bearerTokenSecret:
name: thanos-remote-write-token
key: token
queueConfig:
capacity: 50000
maxShards: 20
minShards: 1
maxSamplesPerSend: 2000
batchSendDeadline: 30s
minBackoff: 1s
maxBackoff: 5m
writeRelabelConfigs:
# Drop high-cardinality metrics die je centraal niet nodig hebt
- sourceLabels: [__name__]
regex: 'go_.*'
action: drop
Belangrijk: Zet zinvolle externalLabels. Deze identificeren van welk cluster de metrics komen. Zonder kan je data van verschillende sites niet onderscheiden.
Authenticatie en Beveiliging
Expose nooit Thanos Receive zonder authenticatie. Opties:
Bearer Token (Simpel)
Genereer een token en deel het met edge clusters:
# Genereer token
openssl rand -hex 32 > receive-token.txt
# Maak secret in centraal cluster
kubectl create secret generic thanos-receive-auth \
--from-file=token=receive-token.txt \
-n monitoring
# Maak secret in edge cluster
kubectl create secret generic thanos-remote-write-token \
--from-file=token=receive-token.txt \
-n monitoring
Configureer Receive om tokens te valideren:
# Voeg toe aan Receive container args
- --receive.tenant-header=THANOS-TENANT
- --receive.default-tenant-id=anonymous
mTLS (Veiliger)
Voor omgevingen die sterkere authenticatie vereisen:
# Receive args
- --grpc-server-tls-cert=/etc/tls/server.crt
- --grpc-server-tls-key=/etc/tls/server.key
- --grpc-server-tls-client-ca=/etc/tls/ca.crt
# Edge Prometheus remoteWrite
remoteWrite:
- url: https://thanos-receive.example.com/api/v1/receive
tlsConfig:
certFile: /etc/prometheus/tls/client.crt
keyFile: /etc/prometheus/tls/client.key
caFile: /etc/prometheus/tls/ca.crt
Multi-Tenancy
Thanos Receive ondersteunt multi-tenancy via de tenant header:
# Edge cluster A
remoteWrite:
- url: https://thanos-receive.example.com/api/v1/receive
headers:
THANOS-TENANT: tenant-a
# Edge cluster B
remoteWrite:
- url: https://thanos-receive.example.com/api/v1/receive
headers:
THANOS-TENANT: tenant-b
Data wordt opgeslagen met het tenant label, wat isolatie in queries mogelijk maakt:
# Query alleen tenant-a data
http_requests_total{tenant_id="tenant-a"}
Dit is handig wanneer verschillende teams of klanten dezelfde Receive infrastructuur delen.
Omgaan met Intermitterende Connectiviteit
De killer feature voor edge: graceful degradation wanneer connectiviteit faalt.
Prometheus WAL Buffering
Prometheus buffert niet-verzonden samples in zijn Write-Ahead Log. Configureer voor je connectiviteitspatronen:
remoteWrite:
- url: https://thanos-receive.example.com/api/v1/receive
queueConfig:
capacity: 100000 # Samples om te bufferen
maxShards: 30 # Parallelle senders bij inhalen
maxSamplesPerSend: 5000
batchSendDeadline: 60s
minBackoff: 1s
maxBackoff: 10m # Niet hameren als het down is
Voor een typisch edge cluster dat elke 30s scraped:
- 100k sample buffer ≈ 3-4 uur metrics
- Pas aan op basis van je scrape interval en aantal targets
Monitor Remote Write Health
Op het edge cluster, alert op remote write failures:
- alert: PrometheusRemoteWriteFailing
expr: |
rate(prometheus_remote_storage_failed_samples_total[5m]) > 0
for: 15m
labels:
severity: warning
annotations:
summary: "Prometheus remote write faalt"
description: "Edge cluster {{ $labels.cluster }} faalt met verzenden metrics"
Centrale Monitoring van Edge Health
Op het centrale cluster, detecteer stille edges:
- alert: EdgeClusterMissing
expr: |
absent_over_time(up{job="prometheus", cluster=~"edge-.*"}[1h])
for: 30m
labels:
severity: critical
annotations:
summary: "Edge cluster rapporteert niet"
description: "Geen metrics van {{ $labels.cluster }} voor 1 uur"
Sidecar vs Receive: Wanneer Welke Gebruiken
| Aspect | Sidecar | Receive |
|---|---|---|
| Edge/offline ondersteuning | Slecht | Uitstekend |
| Real-time queries | Ja (via gRPC) | Ja (via Receive gRPC) |
| Resources aan edge | Hoger | Lager |
| Object storage toegang | Vereist aan edge | Alleen centraal |
| Netwerk richting | Outbound + inbound | Alleen outbound |
| Complexiteit aan edge | Hoger | Lager |
| Block upload latency | 2h (block grootte) | Real-time |
Gebruik Sidecar wanneer:
- Alle clusters stabiele connectiviteit hebben
- Je minimale centrale infrastructuur wilt
- Real-time queries over alle clusters belangrijk zijn
Gebruik Receive wanneer:
- Edge clusters intermitterende connectiviteit hebben
- Je schaalt naar veel (50+) clusters
- Edge resources beperkt zijn
- Alleen outbound firewall regels gelden
Hybride aanpak:
- Sidecar voor core/stabiele clusters
- Receive voor edge/remote clusters
- Beide voeden dezelfde Querier en object storage
Mijn Productie Setup
Ik draai een hybride model:
# Centraal infrastructuur cluster: Sidecar
# (stabiele connectiviteit, heeft real-time queries nodig)
prometheus:
thanos:
enabled: true
objectStorageConfig:
name: thanos-objstore
# Edge manufacturing sites: Remote Write
# (intermitterende connectiviteit, resource beperkt)
prometheus:
remoteWrite:
- url: https://thanos-receive.central:443/api/v1/receive
bearerTokenSecret:
name: edge-token
queueConfig:
capacity: 150000 # 6+ uur buffer
maxBackoff: 15m
# Alles voedt dezelfde Thanos Query
thanos:
query:
stores:
- dnssrv+_grpc._tcp.prometheus-operated.monitoring.svc # Sidecars
- dnssrv+_grpc._tcp.thanos-receive.monitoring.svc # Receive
- dnssrv+_grpc._tcp.thanos-store.monitoring.svc # Historisch
Edge sites kunnen uren connectiviteit verliezen. Als ze reconnecten, worden metrics automatisch ingehaald. De centrale Grafana dashboards tonen het volledige beeld, ongeacht welke architectuur de data leverde.
Waarom Dit Ertoe Doet
Monitoring is niet optioneel. Je moet zien wat er gebeurt over al je clusters — niet alleen degene met perfecte connectiviteit.
Het push model met Thanos Receive geeft je:
- Resilience: Edge clusters overleven connectiviteitsverlies
- Simpelheid: Geen sidecars, geen object storage creds aan edge
- Schaalbaarheid: Centraliseer complexiteit, houd edges simpel
- Flexibiliteit: Mix sidecar en receive naar behoefte
Dit is hoe je observability bouwt die werkt in de echte wereld, waar netwerken falen en edge locaties bestaan.
Pull werkt als alles connected is. Push werkt als de realiteit tussenbeide komt. Goede architecturen kunnen beide aan.
