Aller au contenu principal

Monitoring Multi-Cloud


1 - Défis du monitoring Multi-Cloud

1.1 Problématiques

DéfiDescription
SilosDonnées dispersées par cloud
CorrélationDifficile de lier les événements
DashboardsMultiples interfaces
AlertingRègles dupliquées
CoûtPlusieurs outils payants

2 - Solutions de monitoring unifié

2.1 Options

SolutionTypeMulti-Cloud
DatadogSaaSNatif
Grafana CloudSaaSNatif
Prometheus + GrafanaSelf-hostedOui
Elastic StackSelf-hosted/SaaSOui
New RelicSaaSNatif

2.2 Architecture recommandée


3 - Prometheus Multi-Cluster

3.1 Installation par cluster

# values-prometheus.yaml (Helm)
prometheus:
prometheusSpec:
replicas: 2
retention: 24h # Local retention court

externalLabels:
cluster: aws-production
cloud: aws
region: eu-west-1

remoteWrite:
- url: https://thanos-receive.monitoring.svc:19291/api/v1/receive
headers:
X-Scope-OrgID: tenant1

3.2 Thanos pour agrégation

# Thanos Query Frontend
apiVersion: apps/v1
kind: Deployment
metadata:
name: thanos-query
spec:
template:
spec:
containers:
- name: thanos-query
image: quay.io/thanos/thanos:v0.32.0
args:
- query
- --http-address=0.0.0.0:9090
- --store=thanos-store-aws:10901
- --store=thanos-store-azure:10901
- --store=thanos-store-gcp:10901
- --query.replica-label=replica
- --query.auto-downsampling

3.3 Labels pour Multi-Cloud

# Métriques avec labels cloud
- targets: ['app:8080']
labels:
cloud: aws
cluster: production
region: eu-west-1
environment: prod

4 - Logging centralisé

4.1 Architecture

4.2 Fluent Bit Configuration

# fluent-bit.conf
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
Refresh_Interval 5

[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Merge_Log On
K8S-Logging.Parser On

[FILTER]
Name record_modifier
Match *
Record cloud ${CLOUD_PROVIDER}
Record cluster ${CLUSTER_NAME}
Record region ${REGION}

[OUTPUT]
Name es
Match *
Host elasticsearch.monitoring.svc
Port 9200
Index logs-multicloud
Type _doc

4.3 Loki avec Grafana

# Loki configuration
auth_enabled: false

server:
http_listen_port: 3100

distributor:
ring:
kvstore:
store: memberlist

ingester:
lifecycler:
ring:
kvstore:
store: memberlist
replication_factor: 3

schema_config:
configs:
- from: 2024-01-01
store: boltdb-shipper
object_store: s3
schema: v11
index:
prefix: loki_index_
period: 24h

storage_config:
boltdb_shipper:
active_index_directory: /loki/index
cache_location: /loki/cache
shared_store: s3
aws:
s3: s3://eu-west-1/loki-logs

5 - Tracing distribué

5.1 OpenTelemetry

# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318

processors:
batch:
timeout: 10s

resource:
attributes:
- key: cloud.provider
value: ${CLOUD_PROVIDER}
action: upsert
- key: cloud.region
value: ${REGION}
action: upsert

exporters:
jaeger:
endpoint: jaeger-collector:14250
tls:
insecure: true

otlp:
endpoint: tempo.monitoring.svc:4317

service:
pipelines:
traces:
receivers: [otlp]
processors: [batch, resource]
exporters: [jaeger, otlp]

5.2 Instrumentation application

# Python avec OpenTelemetry
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource

resource = Resource.create({
"service.name": "my-service",
"cloud.provider": os.getenv("CLOUD_PROVIDER", "unknown"),
"cloud.region": os.getenv("REGION", "unknown"),
"deployment.environment": os.getenv("ENVIRONMENT", "unknown")
})

provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="otel-collector:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

6 - Alerting unifié

6.1 Alertmanager

# alertmanager.yml
global:
resolve_timeout: 5m

route:
group_by: ['alertname', 'cloud', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'pagerduty'
- match:
severity: warning
receiver: 'slack'

receivers:
- name: 'default'
webhook_configs:
- url: 'http://webhook.example.com/alert'

- name: 'pagerduty'
pagerduty_configs:
- service_key: '<pagerduty-key>'
severity: critical

- name: 'slack'
slack_configs:
- api_url: '<slack-webhook>'
channel: '#alerts'
title: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
text: 'Cloud: {{ .GroupLabels.cloud }} | Cluster: {{ .GroupLabels.cluster }}'

6.2 Règles d'alerte communes

# prometheus-rules.yaml
groups:
- name: multicloud-alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (cloud, cluster, service)
/
sum(rate(http_requests_total[5m])) by (cloud, cluster, service)
> 0.01
for: 5m
labels:
severity: warning
annotations:
summary: "High error rate on {{ $labels.service }}"
description: "Error rate is {{ $value | humanizePercentage }} on {{ $labels.cloud }}/{{ $labels.cluster }}"

- alert: ClusterDown
expr: up{job="kubernetes-nodes"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Cluster {{ $labels.cluster }} on {{ $labels.cloud }} is down"

7 - Dashboards Multi-Cloud

7.1 Dashboard Grafana

{
"title": "Multi-Cloud Overview",
"panels": [
{
"title": "Requests by Cloud",
"type": "stat",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m])) by (cloud)",
"legendFormat": "{{cloud}}"
}
]
},
{
"title": "Error Rate by Region",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total{status=~\"5..\"}[5m])) by (cloud, region) / sum(rate(http_requests_total[5m])) by (cloud, region)",
"legendFormat": "{{cloud}}-{{region}}"
}
]
},
{
"title": "Cluster Health",
"type": "table",
"targets": [
{
"expr": "count(up{job=\"kubernetes-nodes\"} == 1) by (cloud, cluster)",
"format": "table"
}
]
}
]
}

Résumé

Dans ce chapitre, nous avons appris :

  • Les défis du monitoring Multi-Cloud
  • Les solutions de monitoring unifié
  • Prometheus et Thanos multi-cluster
  • Le logging centralisé avec Loki/ELK
  • Le tracing distribué avec OpenTelemetry
  • L'alerting unifié

Prochaine étape

Dans le prochain chapitre, nous verrons les Bonnes pratiques.

→ Chapitre suivant : Bonnes pratiques


← Retour à la table des matières