Collecter et traiter les données télémétriques (logs, metrics, traces) devient plus lourd à mesure que l'infrastructure grandit. Vector, développé par Datadog puis passé en open-source, construit des pipelines d'observabilité unifiés. Ce guide couvre Vector de bout en bout pour reprendre la main sur votre infrastructure de monitoring.
L'évolution des pipelines d'observabilité
Le problème des outils fragmentés
Traditionnellement, l'observabilité repose sur une multitude d'agents spécialisés : Filebeat pour les logs, Telegraf pour les metrics, Jaeger agents pour les traces, Logstash pour les transformations. Cette fragmentation crée plusieurs problèmes. D'abord, chaque agent consomme des ressources : CPU, mémoire, et surtout des connexions réseau. Sur un serveur de production, voir 5-6 agents différents tourner en même temps n'a rien d'exceptionnel, chacun ouvrant ses propres connexions vers des backends différents.
Ensuite, la configuration devient un cauchemar. Chaque outil a sa propre syntaxe, ses propres paradigmes. Filebeat utilise YAML avec une logique spécifique, Logstash a son propre DSL, Telegraf encore un autre format. Maintenir la cohérence entre tous ces outils exige de maîtriser chacun d'eux et multiplie les risques d'erreur de configuration.
Enfin, l'overhead réseau explose. Filebeat envoie des logs vers Elasticsearch, Telegraf vers InfluxDB, Prometheus scrape ses metrics, Jaeger agent vers Jaeger collector. Chacun établit ses propres connexions, parfois vers le même datacenter, créant un trafic redondant et coûteux, surtout dans les environnements cloud où le trafic sortant est facturé.
Vector : l'approche unifiée
Vector prend ces problèmes par une approche différente : un seul agent, tous les types de données. Vector collecte, transforme et route logs, metrics et traces dans un pipeline unifié. L'unification n'a rien de superficiel : Vector traite chacun de ces types nativement, avec un modèle de données cohérent et des transformations qui s'appliquent transversalement.
L'architecture de Vector repose sur sources (collecter les données), transforms (modifier/enrichir) et sinks (envoyer vers destinations). Cette séparation des responsabilités sert à construire des pipelines complexes de façon déclarative, sans sacrifier la lisibilité de la configuration.
L'atout principal de Vector tient à ses performances. Écrit en Rust, il affiche une empreinte mémoire 10x inférieure à Logstash et un débit 2-3x supérieur à Filebeat selon les benchmarks officiels. L'écart n'a rien d'anecdotique : sur une infrastructure qui traite des millions d'événements par seconde, la différence avec les solutions traditionnelles se chiffre en dizaines de serveurs économisés.
Cas d'usage modernes
Vector excelle dans plusieurs scénarios critiques de l'observabilité moderne :
Centralisation multi-cloud : Les entreprises opèrent rarement sur un seul cloud provider. Vector peut collecter depuis AWS CloudWatch, GCP Stackdriver, Azure Monitor et les unifier vers un backend centralisé comme Elasticsearch ou Datadog. Cette capacité à agréger des sources hétérogènes simplifie drastiquement l'observabilité multi-cloud.
Edge computing et IoT : L'empreinte mémoire réduite de Vector (quelques MB) le rend idéal pour des déploiements edge où les ressources sont limitées. Vector peut tourner sur des Raspberry Pi ou des edge nodes, collectant et pré-traitant les données localement avant envoi vers le cloud, réduisant les coûts de bande passante.
Compliance et redaction : Vector transforme les données à la volée, masque des PII (données personnelles), redacte des secrets, enrichit avec des métadonnées. Ces transformations s'appliquent avant l'envoi vers le stockage, ce qui empêche les données sensibles de quitter votre infrastructure.
Cost optimization : sampling intelligent (ne conserver qu'un % des logs), agrégation de metrics avant envoi, routage conditionnel vers des storage tiers différents selon l'importance des données. Vector fait baisser nettement la facture d'observabilité.
Installation et configuration initiale
Prérequis et architecture système
Avant d'installer Vector, comprenez son modèle de déploiement. Vector tourne en mode agent (un Vector par host, collecte locale) ou en mode aggregator (Vector centralisé, reçoit depuis plusieurs agents). De quoi construire des architectures adaptées à chaque besoin, du single-node au cluster distribué.
Les ressources nécessaires pour Vector restent modestes. Un agent Vector consomme 50-100 MB de mémoire au repos, avec des pics à 200-300 MB sous charge intense. Une stack Filebeat+Logstash atteint vite 1-2 GB, l'économie compte. Côté CPU, le runtime Rust se contente de typiquement 1-5 % d'utilisation pour des charges moyennes.
Le placement de Vector dépend de votre architecture. Pour de l'observabilité applicative, déployez Vector en sidecar container ou agent systemd sur chaque host. Pour des flux centralisés (logs applicatifs envoyés directement depuis les apps via HTTP), un Vector aggregator derrière un load balancer convient mieux. Les deux approches coexistent : les agents collectent les logs système/OS, les aggregators reçoivent les logs applicatifs.
Installation sur distributions Linux
L'installation de Vector est standardisée sur les distributions majeures grâce aux repositories officiels :
Sur Debian/Ubuntu, Vector fournit des packages .deb :
# Ajouter repository Vector
bash -c "$(curl -L https://setup.vector.dev)"
# Installer Vector
sudo apt-get update
sudo apt-get install vector
# Vérifier installation
vector --version
# vector 0.37.0 (x86_64-unknown-linux-gnu)
# Vector installé comme service systemd
systemctl status vector
Sur RHEL/CentOS/Fedora, le processus est similaire avec packages RPM :
# Ajouter repo
bash -c "$(curl -L https://setup.vector.dev)"
# Installer
sudo yum install vector
# Vérifier
vector --version
systemctl status vector
L'installation crée automatiquement un service systemd configuré pour démarrer au boot. Les fichiers de configuration sont placés dans /etc/vector/, les logs dans /var/log/vector/, et les données (buffers) dans /var/lib/vector/.
Configuration fichier principal
Le fichier de configuration principal /etc/vector/vector.toml utilise le format TOML (lisible et explicite). Sa structure se lit ainsi :
# /etc/vector/vector.toml
# Section Data Directory - où Vector stocke buffers et state
data_dir = "/var/lib/vector"
# Configuration sources - collecter données
[sources.system_logs]
type = "journald" # Lire depuis systemd journald
current_boot_only = false
[sources.app_logs]
type = "file"
include = ["/var/log/nginx/*.log", "/var/log/app/*.log"]
read_from = "beginning" # Ou "end" pour logs existants
# Configuration transforms - modifier données
[transforms.parse_nginx]
type = "remap"
inputs = ["app_logs"]
source = '''
. = parse_nginx_log!(.message)
'''
# Configuration sinks - envoyer données
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["parse_nginx", "system_logs"]
endpoint = "http://elasticsearch:9200"
bulk.index = "logs-%Y-%m-%d"
# Health check endpoint
[api]
enabled = true
address = "127.0.0.1:8686"
Cette structure en trois blocs (sources → transforms → sinks) définit le pipeline de données. Les inputs de chaque composant référencent les outputs des précédents, créant un graphe de flux explicite.
Validation et test configuration
Avant de démarrer Vector en production, validez toujours votre configuration :
# Valider syntaxe config
vector validate /etc/vector/vector.toml
# Test avec output dry-run (pas d'envoi réel)
vector --config /etc/vector/vector.toml --dry-run
# Mode verbose pour debug
vector --config /etc/vector/vector.toml --verbose
# Lancer en foreground (utile pour debug)
vector --config /etc/vector/vector.toml
# Une fois validé, restart service
sudo systemctl restart vector
sudo systemctl status vector
# Vérifier logs démarrage
journalctl -u vector -f
Vector offre également un mode watch qui recharge automatiquement la config lors de changements, idéal pour itérer rapidement :
# Watch mode - reload automatique sur changements
vector --config /etc/vector/vector.toml --watch-config
Sources : collecte de données
Sources logs : fichiers et journald
La collecte de logs reste le use case le plus courant pour Vector. Deux sources dominent : fichiers texte et journald (systemd).
File source pour logs applicatifs classiques :
[sources.nginx_logs]
type = "file"
include = ["/var/log/nginx/access.log", "/var/log/nginx/error.log"]
exclude = ["*.gz"] # Ignorer archives
read_from = "end" # Ne pas retraiter logs existants
# Options avancées
max_line_bytes = 102400 # 100KB max par ligne
line_delimiter = "\n"
encoding = "utf-8"
# Fingerprinting pour suivre rotations
fingerprint.strategy = "device_and_inode"
fingerprint.ignored_header_bytes = 0
# Multiline support (stack traces, etc)
multiline.start_pattern = '^[^\s]' # Ligne ne commençant pas par whitespace
multiline.mode = "continue_through"
multiline.condition_pattern = '^\s'
multiline.timeout_ms = 1000
Les options de fingerprinting conditionnent la gestion des log rotations. Vector suit l'inode des fichiers pour détecter quand un fichier est roté et reprendre la lecture du nouveau fichier sans perte.
Le multiline support agrège des stack traces Java ou des logs JSON multi-lignes en un seul événement. Sans lui, chaque ligne d'une stack trace deviendrait un événement séparé et rendrait l'analyse impossible.
Journald source pour logs système :
[sources.systemd]
type = "journald"
current_boot_only = false # Tous boots, pas juste actuel
units = ["nginx.service", "postgresql.service"] # Filter par unit
# Ou collecter tout
[sources.systemd_all]
type = "journald"
# Pas de filter = tout systemd
Journald reste la source préférée pour les logs système sur distributions modernes : elle donne des métadonnées structurées (unit, PID, UID, etc.) et une lecture rapide via l'API native.
Sources metrics : Prometheus, StatsD, Host
Vector peut collecter des metrics via plusieurs protocoles standards :
Prometheus scraping :
[sources.prometheus_scrape]
type = "prometheus_scrape"
endpoints = ["http://localhost:9090/metrics"]
scrape_interval_secs = 15
# Avec authentification
auth.strategy = "basic"
auth.user = "prometheus"
auth.password = "${PROMETHEUS_PASSWORD}"
Vector se comporte comme un Prometheus scraper et collecte des metrics depuis n'importe quel endpoint exposant le format Prometheus.
StatsD listener :
[sources.statsd]
type = "statsd"
address = "0.0.0.0:8125"
mode = "tcp" # Ou "udp"
# Parsing tags (format Datadog)
parse_tags = true
Cela transforme Vector en serveur StatsD, remplaçant avantageusement statsd-exporter avec de meilleures performances.
Host metrics (CPU, mémoire, disque) :
[sources.host_metrics]
type = "host_metrics"
collectors = ["cpu", "memory", "disk", "network", "filesystem"]
scrape_interval_secs = 10
# Filter disques
filesystem.devices.excludes = ["binfmt_misc"]
filesystem.filesystems.excludes = ["binfmt_misc"]
Cette source transforme Vector en agent de monitoring système complet, collectant les metrics vitales du host comme node_exporter.
Sources traces : OTLP et Jaeger
Vector supporte les traces distribuées via OpenTelemetry Protocol (OTLP) et Jaeger :
[sources.otel_traces]
type = "opentelemetry"
address = "0.0.0.0:4317" # gRPC
mode = "server"
# HTTP également supporté
[sources.otel_http]
type = "opentelemetry"
address = "0.0.0.0:4318"
mode = "http"
Vector reçoit alors des traces depuis des applications instrumentées avec OpenTelemetry SDK et remplace l'OTEL Collector dans des architectures simplifiées.
Transforms : traitement et enrichissement
VRL : Vector Remap Language
Le cœur de Vector tient à VRL (Vector Remap Language), un DSL conçu pour transformer des données d'observabilité. VRL est typé, vérifié à la compilation, et taillé pour le débit.
Parsing logs structurés :
[transforms.parse_json]
type = "remap"
inputs = ["app_logs"]
source = '''
# Parser JSON depuis champ message
. = parse_json!(.message)
# Extraire timestamp custom
.timestamp = to_timestamp!(.custom_time)
# Ajouter metadata
.source = "app-server"
.environment = get_env_var!("ENVIRONMENT")
'''
VRL utilise des fonctions infaillibles (avec !) qui paniquent si l'opération échoue, et des fonctions fallibles (sans !) qui retournent un résultat optionnel. Cette distinction garantit que vous gérez explicitement les cas d'erreur.
Parsing logs non-structurés (regex) :
[transforms.parse_nginx]
type = "remap"
inputs = ["nginx_logs"]
source = '''
# Regex pour Nginx access log
parsed = parse_regex!(.message, r'^(?P<ip>\S+) - (?P<user>\S+) \[(?P<timestamp>[^\]]+)\] "(?P<method>\S+) (?P<path>\S+) (?P<protocol>\S+)" (?P<status>\d+) (?P<bytes>\d+)')
# Promouvoir champs parsés au top-level
. = merge(., parsed)
# Convertir types
.status = to_int!(.status)
.bytes = to_int!(.bytes)
# Parser timestamp Nginx
.timestamp = parse_timestamp!(.timestamp, "%d/%b/%Y:%H:%M:%S %z")
'''
Ce transform parse un log Nginx brut en structure exploitable avec types corrects, indispensable pour l'indexation Elasticsearch ou l'analyse.
Enrichissement geo-IP :
[transforms.geoip]
type = "geoip"
inputs = ["parse_nginx"]
source = "ip" # Champ contenant IP
database = "/usr/share/GeoIP/GeoLite2-City.mmdb"
# Ajoute automatiquement champs .geoip.city, .geoip.country, etc.
Filtrage et routage
Filtrer événements par conditions :
[transforms.filter_errors]
type = "filter"
inputs = ["parse_nginx"]
condition = '.status >= 400' # Garder seulement erreurs 4xx et 5xx
Router vers multiple destinations selon contenu :
[transforms.route_by_level]
type = "route"
inputs = ["app_logs"]
# Définir routes
route.error = '.level == "error"'
route.warning = '.level == "warning"'
route.info = '.level == "info"'
route._default = true # Catch-all
# Ensuite, différents sinks peuvent référencer route_by_level.error, etc.
Ce routage envoie les logs critiques vers un sink prioritaire (avec alerting) et les logs debug vers un sink low-cost (S3).
Aggregation et sampling
Reducer pour agréger metrics :
[transforms.aggregate_metrics]
type = "aggregate"
inputs = ["statsd"]
interval_ms = 10000 # Fenêtre 10 secondes
# Agréger par tags
group_by = ["service", "host"]
# Opérations
aggregate.count.type = "count"
aggregate.sum.type = "sum"
aggregate.sum.field = "value"
Sampling pour réduire volume :
[transforms.sample_debug_logs]
type = "sample"
inputs = ["app_logs"]
rate = 10 # Garder 1 événement sur 10
# Ou sampling avec clé (consistent hashing)
key_field = "trace_id" # Même trace_id toujours samplé ensemble
Le sampling pilote les coûts sur des volumes massifs de logs. Un sampling à 10 % (rate=10) divise par 10 les coûts de stockage/transfert tout en gardant une visibilité statistique.
Sinks : destinations multiples
Elasticsearch : indexation et ILM
Vector fournit un sink Elasticsearch optimisé avec support du bulk API et gestion des erreurs :
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["parse_nginx", "app_logs"]
# Endpoints (avec load balancing automatique)
endpoints = [
"http://es-node1:9200",
"http://es-node2:9200"
]
# Authentification
auth.strategy = "basic"
auth.user = "vector"
auth.password = "${ES_PASSWORD}"
# Index dynamique avec date rolling
bulk.index = "logs-%Y-%m-%d"
# Ou index par type de log
bulk.index = "{{ source }}-{{ environment }}-%Y-%m-%d"
# Bulk settings
bulk.action = "create" # Ou "index", "update"
bulk.timeout_secs = 30
# Retry et buffers
request.retry_max_duration_secs = 30
request.timeout_secs = 60
# Buffer (crucial pour performance)
buffer.type = "disk"
buffer.max_size = 268435488 # 256 MB
buffer.when_full = "block" # Ou "drop_newest"
# Compression (économie bande passante)
compression = "gzip"
# Healthcheck
healthcheck.enabled = true
Les index templates se configurent dans Elasticsearch en amont. Vector n'en crée pas automatiquement, à vous de définir les mappings appropriés.
Le buffering sur disque s'impose en production. Si Elasticsearch devient indisponible un moment, Vector bufferise sur disque (jusqu'à max_size) plutôt que de perdre des données. Ce mécanisme découple la disponibilité des sources et des sinks.
Loki : logs cloud-native
Grafana Loki est une alternative légère à Elasticsearch pour les logs :
[sinks.loki]
type = "loki"
inputs = ["app_logs"]
endpoint = "http://loki:3100"
# Labels (crucial pour Loki)
labels.job = "{{ source }}"
labels.host = "{{ host }}"
labels.environment = "production"
# Encoding
encoding.codec = "json"
# Compression
compression = "gzip"
# Tenant (Loki multi-tenant)
tenant_id = "tenant1"
# Buffer
buffer.type = "disk"
buffer.max_size = 104857600 # 100 MB
Loki fonctionne par labels, pas par full-text search. Choisir les bons labels (peu nombreux, cardinalité faible) conditionne ses performances. En général, service, environment et host suffisent.
Datadog : SaaS monitoring
Vector s'intègre nativement avec Datadog :
[sinks.datadog_logs]
type = "datadog_logs"
inputs = ["app_logs"]
# API key depuis env var
default_api_key = "${DD_API_KEY}"
# Region
site = "datadoghq.eu" # Ou datadoghq.com pour US
# Compression
compression = "gzip"
# Encoding
encoding.codec = "json"
# Metrics également
[sinks.datadog_metrics]
type = "datadog_metrics"
inputs = ["host_metrics"]
default_api_key = "${DD_API_KEY}"
site = "datadoghq.eu"
Utiliser Vector plutôt que l'agent Datadog natif apporte la transformation pré-envoi et le multiplexage vers d'autres destinations en parallèle.
S3 : archivage long terme
Pour l'archivage low-cost ou la compliance :
[sinks.s3]
type = "aws_s3"
inputs = ["app_logs"]
# Bucket et région
bucket = "logs-archive"
region = "eu-west-1"
# Credentials (via IAM role recommandé)
auth.access_key_id = "${AWS_ACCESS_KEY}"
auth.secret_access_key = "${AWS_SECRET_KEY}"
# Key template (partitioning)
key_prefix = "logs/%Y/%m/%d/"
filename_time_format = "%Y%m%dT%H%M%S"
filename_append_uuid = true
# Compression (crucial pour coûts S3)
compression = "gzip"
# Encoding
encoding.codec = "ndjson" # Newline-delimited JSON
# Batching (réduire nombre de PUTs S3)
batch.max_events = 10000
batch.timeout_secs = 300
# Storage class
storage_class = "STANDARD_IA" # Ou GLACIER pour long terme
L'archivage S3 coûte très peu : avec compression gzip (~5x) et storage class GLACIER, le coût descend sous $0.001/GB/mois.
Pipelines avancés et architecture
Architecture multi-tier
Pour des infrastructures à grande échelle, une architecture multi-tier est recommandée :
Tier 1 : Agents sur chaque host
# Agent config (/etc/vector/vector.toml sur hosts)
[sources.logs]
type = "file"
include = ["/var/log/**/*.log"]
[sources.metrics]
type = "host_metrics"
# Envoi vers aggregator central
[sinks.to_aggregator]
type = "vector"
inputs = ["logs", "metrics"]
address = "aggregator.internal:9000"
# Compression
compression = true
# Buffer local (résilience)
buffer.type = "disk"
buffer.max_size = 1073741824 # 1 GB
Tier 2 : Aggregators centralisés
# Aggregator config
[sources.from_agents]
type = "vector"
address = "0.0.0.0:9000"
# Transformations centralisées (parsing, enrichissement)
[transforms.parse]
type = "remap"
inputs = ["from_agents"]
source = '''
# Parsing complexe ici
'''
# Envoi vers backends finaux
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["parse"]
endpoints = ["http://es:9200"]
[sinks.s3_archive]
type = "aws_s3"
inputs = ["parse"]
bucket = "logs-archive"
Cette architecture apporte la résilience (buffers sur agents et aggregators), le scaling horizontal (ajouter des aggregators derrière LB) et la centralisation du parsing/enrichissement (économie CPU sur agents).
Pipelines parallèles et fan-out
Vector permet d'envoyer les mêmes données vers multiple destinations simultanément :
[sources.app_logs]
type = "file"
include = ["/var/log/app/*.log"]
[transforms.parse]
type = "remap"
inputs = ["app_logs"]
source = '...'
# Sink 1 : Elasticsearch (recherche)
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["parse"]
endpoints = ["http://es:9200"]
# Sink 2 : S3 (archivage)
[sinks.s3]
type = "aws_s3"
inputs = ["parse"]
bucket = "logs-archive"
# Sink 3 : Datadog (monitoring)
[sinks.datadog]
type = "datadog_logs"
inputs = ["parse"]
default_api_key = "${DD_API_KEY}"
Un seul pipeline d'ingestion, trois destinations. Vector gère le fan-out, le backpressure et les retries indépendamment pour chaque sink.
Conditional routing avancé
Router différents logs vers différentes destinations selon contenu :
[sources.all_logs]
type = "file"
include = ["/var/log/**/*.log"]
[transforms.parse_and_classify]
type = "remap"
inputs = ["all_logs"]
source = '''
# Parser et ajouter classification
.parsed = parse_json(.message) ?? parse_syslog(.message) ?? .message
.severity = .parsed.level ?? "info"
.is_error = includes(["error", "fatal", "critical"], .severity)
.is_security = contains(string!(.message), "authentication") || contains(string!(.message), "authorization")
'''
[transforms.route]
type = "route"
inputs = ["parse_and_classify"]
# Route errors vers sink prioritaire
route.errors = '.is_error == true'
# Route security vers SIEM
route.security = '.is_security == true'
# Route normal vers storage standard
route.normal = '!.is_error && !.is_security'
# Sinks pour chaque route
[sinks.errors_pagerduty]
type = "http"
inputs = ["route.errors"]
uri = "https://events.pagerduty.com/v2/enqueue"
# ... config PagerDuty
[sinks.security_siem]
type = "splunk_hec"
inputs = ["route.security"]
endpoint = "https://siem:8088"
[sinks.normal_s3]
type = "aws_s3"
inputs = ["route.normal"]
bucket = "logs-standard"
storage_class = "STANDARD_IA"
Ce pattern réduit les coûts : seuls les logs critiques partent vers des sinks coûteux/prioritaires, le reste va vers du storage low-cost.
Performance, tuning et monitoring
Buffering stratégies
Le choix du buffer est critique pour les performances et la résilience :
Memory buffer : Rapide mais perte de données si crash
[sinks.fast_sink]
buffer.type = "memory"
buffer.max_events = 500000 # 500k événements en RAM
buffer.when_full = "drop_newest" # Ou "block"
Disk buffer : Plus lent mais durable
[sinks.reliable_sink]
buffer.type = "disk"
buffer.max_size = 10737418240 # 10 GB sur disque
buffer.when_full = "block" # Backpressure vers source
En production, prenez disk buffer pour les sinks critiques (Elasticsearch, Datadog). Pour des sinks secondaires (métriques debug, S3 archivage), memory buffer suffit.
Batch sizing et throughput
Ajuster le batching fait grimper le throughput :
[sinks.elasticsearch_tuned]
type = "elasticsearch"
inputs = ["logs"]
# Batch size (nombre d'événements)
bulk.batch_size = 1000 # Défaut: 100
# Timeout batch (secondes)
bulk.timeout_secs = 5 # Défaut: 1
# Simultanéité (connexions parallèles)
request.concurrency = 10 # Défaut: 1
# Compression (crucial)
compression = "gzip"
Augmenter batch_size et request.concurrency multiplie le throughput par 10-20x sur des workloads haute volumétrie. Attention quand même à l'utilisation mémoire qui monte d'autant.
Health checks et observabilité
Vector expose des métriques Prometheus sur son endpoint API :
[api]
enabled = true
address = "0.0.0.0:8686"
# Avec authentification optionnelle
[api.playground]
enabled = false # Playground GraphQL (dev seulement)
Scraper ces métriques :
# Métriques Prometheus format
curl http://localhost:8686/metrics
# Métriques clés à monitorer :
# vector_events_processed_total{component_id="parse"} - événements traités
# vector_events_out_total{component_id="elasticsearch"} - événements envoyés
# vector_buffer_events{component_id="elasticsearch"} - événements bufferisés
# vector_errors_total{component_id="elasticsearch"} - erreurs
Surveiller ces métriques dans Grafana fait ressortir les goulots d'étranglement, les erreurs et l'état des buffers en temps réel.
Logging et troubleshooting
Vector lui-même log dans journald ou fichiers :
# Logs Vector via journald
journalctl -u vector -f
# Niveau de log (env var)
VECTOR_LOG=debug vector
# Ou dans config
[log_schema]
level_key = "level"
Pour debugger un pipeline, activez le tap (console output temporaire) :
# Tap pour debug (désactiver en prod)
[sinks.debug_console]
type = "console"
inputs = ["parse"]
encoding.codec = "json"
Les événements s'affichent en temps réel dans stdout, parfait pour valider les transforms.
Intégration Kubernetes et containers
Déploiement DaemonSet
Vector se déploie typiquement en DaemonSet sur Kubernetes pour collecter les logs de tous les pods :
# vector-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: vector
namespace: monitoring
spec:
selector:
matchLabels:
name: vector
template:
metadata:
labels:
name: vector
spec:
serviceAccountName: vector
containers:
- name: vector
image: timberio/vector:0.37.0-alpine
resources:
requests:
memory: '128Mi'
cpu: '100m'
limits:
memory: '512Mi'
cpu: '500m'
volumeMounts:
- name: config
mountPath: /etc/vector
- name: var-log
mountPath: /var/log
readOnly: true
- name: var-lib-docker
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: config
configMap:
name: vector-config
- name: var-log
hostPath:
path: /var/log
- name: var-lib-docker
hostPath:
path: /var/lib/docker/containers
ConfigMap pour la config Vector :
apiVersion: v1
kind: ConfigMap
metadata:
name: vector-config
namespace: monitoring
data:
vector.toml: |
[sources.kubernetes_logs]
type = "kubernetes_logs"
[transforms.parse]
type = "remap"
inputs = ["kubernetes_logs"]
source = '''
# Parser JSON logs
. = parse_json!(.message)
# Ajouter metadata K8s
.kubernetes = .kubernetes
'''
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["parse"]
endpoints = ["http://elasticsearch.monitoring:9200"]
bulk.index = "k8s-logs-%Y-%m-%d"
Source Kubernetes logs
La source kubernetes_logs est optimisée pour Kubernetes :
[sources.kubernetes_logs]
type = "kubernetes_logs"
# Annotation-based routing
annotation_fields.container_image = "container_image"
annotation_fields.container_name = "container_name"
annotation_fields.pod_name = "pod_name"
annotation_fields.pod_namespace = "pod_namespace"
# Exclusions (éviter boucles)
exclude_paths_glob_patterns = [
"**/var/log/pods/monitoring_vector-*/**"
]
# Auto-découverte pods
auto_partial_merge = true
Vector détecte les nouveaux pods, collecte leurs logs et les enrichit avec les metadata Kubernetes (namespace, labels, annotations).
Cas d'usage production
Migration Filebeat vers Vector
Migrer une stack Filebeat/Logstash/Elasticsearch vers Vector :
Avant (Filebeat) :
# filebeat.yml
filebeat.inputs:
- type: log
paths: ['/var/log/*.log']
output.logstash:
hosts: ['logstash:5044']
Après (Vector) :
[sources.logs]
type = "file"
include = ["/var/log/*.log"]
[transforms.parse]
type = "remap"
inputs = ["logs"]
source = '''
# Parsing que faisait Logstash
'''
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["parse"]
endpoints = ["http://es:9200"]
Bénéfices : Suppression de Logstash (économie infrastructure), réduction latence (pas de hop intermédiaire), parsing plus performant (Rust vs JRuby).
Cost optimization observabilité
Réduire les coûts d'observabilité avec Vector :
# Sampling agressif logs debug
[transforms.sample_debug]
type = "filter"
inputs = ["all_logs"]
condition = '.level == "debug"'
[transforms.sample_debug_rate]
type = "sample"
inputs = ["sample_debug"]
rate = 100 # Garder 1% des debug logs
# Logs normal : sampling moindre
[transforms.sample_info]
type = "filter"
inputs = ["all_logs"]
condition = '.level == "info"'
[transforms.sample_info_rate]
type = "sample"
inputs = ["sample_info"]
rate = 5 # Garder 20% des info logs
# Errors : tout garder
[transforms.errors]
type = "filter"
inputs = ["all_logs"]
condition = '.level == "error" || .level == "fatal"'
# Router vers storage tiers
[sinks.errors_hot]
type = "elasticsearch"
inputs = ["errors"]
# Storage chaud, rapide, cher
[sinks.info_warm]
type = "elasticsearch"
inputs = ["sample_info_rate"]
# Storage tiède, moins cher
[sinks.debug_cold]
type = "aws_s3"
inputs = ["sample_debug_rate"]
# S3 GLACIER, très cheap
storage_class = "GLACIER"
Cette stratégie peut réduire les coûts de 70-80 % tout en gardant tous les logs critiques et une visibilité statistique du reste.
Conclusion
Vector réunit collecte, transformation et routage de tous les types de données télémétriques dans un seul agent. Son architecture en Rust, son langage VRL et son intégration aux pipelines modernes en font un bon candidat pour quitter les stacks Logstash/Filebeat vieillissantes.
Points clés :
- Performances exceptionnelles : 10x moins de mémoire que Logstash, 2-3x meilleur débit que Filebeat
- Unification logs/metrics/traces : Un seul agent, tous les types de données
- VRL (Vector Remap Language) : Transformations puissantes et type-safe
- Architecture flexible : Agent, aggregator, ou les deux
- Multi-destinations : Fan-out simultané vers Elasticsearch, S3, Datadog, etc.
Commandes essentielles :
# Valider config
vector validate vector.toml
# Lancer en foreground (debug)
vector --config vector.toml --verbose
# Service systemd
systemctl start vector
journalctl -u vector -f
# Métriques
curl http://localhost:8686/metrics
Vector monte des pipelines d'observabilité qui tiennent la charge et restent maîtrisables côté coûts. Son adoption chez Datadog, Cloudflare et Discord confirme sa maturité opérationnelle.
Alternatives et compléments
- Si vous préférez une approche plus légère pour les logs seuls, regardez Loki
- Intégrez Vector avec Prometheus et Grafana pour les métriques applicatives
- Pour la centralisation des logs système, rsyslog peut être un point d'entrée avant Vector


