Récupérer les logs d'audit MKS avec Vector

J'administre au quotidien des clusters managés OVHCloud. Parmi mes tâches, je dois gérer la stack d'observabilité, et notamment avoir les logs des applis et autres composants du cluster.

Autant, récupérer les logs des applis du cluster c'est simple à coup de Promtail/Alloy/Loki, ELK ou autre stack, mais pour récupérer les logs d'audit du control-plane ce n'était pas évident... Jusqu'à maintenant 😉

OVHCloud Managed Kubernetes Service & Logs Data Platform

La Logs Data Platform (aka "LDP") permet de centraliser les logs. Je ne ferai pas une présentation de cette plateforme, car j'utilise ma propre stack, et j'ai des besoins d'archivage/export de logs sur d'autres environnements, pour de l'archivage, SOC, etc.

Cette Logs Data Platform est notamment utilisée pour permettre l'envoi des logs d'audit du control-plane des clusters MKS, sur lesquels nous n'avons pas la main.

En effet, depuis l'interface du manager OVHCloud, on peut transférer les logs :

Logs MKS

Pour paramétrer l'envoi de ces logs, je vous renvoie sur la doc officielle.

Vector & websocket

OK, jusque là j'ai mes logs sur la "LDP", mais je veux pouvoir les récupérer chez moi (ou pouvoir les envoyer ailleurs) !

A la suite d'articles comme Falco, j'ai découvert qu'il était possible de récupérer les logs via websocket ! Et si, par chance, il n'existerait pas un outil pour ça ?

Vector

Vous l'aurez deviné, Vector est un outil qui permet de récupérer, transformer, envoyer des logs, métriques et traces, un très bon outil d'observabilité !

Parmi ses qualités, on notera :

  • sa rapidité de traitement vs sa faible empreinte cpu/mémoire (oui, c'est écrit en rust)
  • son écosystème de plugins riches
  • sa facilité de déploiement.

Architecture Vectordev

Et, "comme par hasard", la version v0.49.0 vient de sortir avec une fonctionnalité qui m'intéresse :

"A websocket source was introduced. A WebSocket source in Vector enables ingestion of real-time data from services that expose WebSocket APIs."

Bon, ben y a plus qu'à !!

Paramétrage & test local

Avant de déployer ça sur mes clusters, on va tester ça localement, pour éviter trop de git push, rollout et CrashLoopBackoff 😅. Etant sous MacOS, l'install se fait facilement avec brew :

1$ brew tap vectordotdev/brew && brew install vector
2$ vector --version
3vector 0.49.0 (aarch64-apple-darwin dc7e792 2025-08-12 13:47:08.632326804)

Ensuite, il faut :

  1. Récupérer l'URL websocket

    • Depuis l'interface OVH, allez dans l'onglet "Flux de Données", "Suivre en direct"
    • Puis cliquer sur "Actions", "Copier l'adresse WebSocket"
    • L'adresse sera de type wss://gra1.logs.ovh.com/tail/?tk=abcdefghijklmnopqrstuvwxyz
  2. Paramétrer Vector, en éditant un fichier vector.yaml

    • Définir un objet source de type websocket
    • Définir les transforms souhaitées et les sinks (destinations)

Pour l'exemple, on va simplement renvoyer sur la console :

 1# vector-1.yaml
 2sources:
 3  ovh_ldp_source:
 4    type: websocket
 5    uri: "wss://gra1.logs.ovh.com/tail/?tk=abcdefghijklmnopqrstuvwxyz"
 6    tls: # le websocket OVHCloud est en TLS, sinon vous aurez une erreur de connection ^^
 7      enabled: true
 8
 9sinks:
10  stdout_sink:
11    type: console
12    inputs:
13      - ovh_ldp_source

On lance !

1$ vector -c vector-1.yaml
22025-08-29T09:05:09.371791Z  INFO vector::app: Log level is enabled. level="info"
32025-08-29T09:05:09.373257Z  INFO vector::app: Loading configs. paths=["vector-1.yaml"]
42025-08-29T09:05:09.575776Z  INFO vector::topology::running: Running healthchecks.
52025-08-29T09:05:09.575874Z  INFO vector: Vector has started. debug="false" version="0.49.0" arch="aarch64" revision="dc7e792 2025-08-12 13:47:08.632326804"
62025-08-29T09:05:09.575918Z  INFO vector::topology::builder: Healthcheck passed.
72025-08-29T09:05:09.575929Z  INFO vector::app: API is disabled, enable by setting `api.enabled` to `true` and use commands like `vector top`.
8{"message":"{\"message\":\"{\\\"_audit_apiVersion\\\":\\\"audit.k8s.io/v1\\\",\\\"_audit_objectNamespace\\\":\\\"default\\\",\\\"_audit_authorizationReason\\\":\\\"\\\",\\\"_audit_requestReceivedTimestamp_date\\\":\\\"2025-08-29T09:05:13.486642Z\\\[...]"}
9{"message":"{\"message\":\"{\\\"_audit_apiVersion\\\":\\\"audit.k8s.io/v1\\\",\\\"_audit_objectNamespace\\\":\\\"kyverno\\\",\\\"_audit_authorizationReason\\\":\\\"RBAC: allowed by RoleBinding \\\\\\\"kyverno:reports-controller/kyverno\\\\\\\" of Role[...]"}

Cool, j'arrive à récupérer les logs, et vais pouvoir les envoyer sur ma propre stack et/ou ailleurs, au choix !! On va quand même faire un peu de ménage dans le format des messages, y a du redondant. Ce qui nous donne le fichier de conf suivant :

 1# vector-2.yaml
 2sources:
 3  ovh_ldp_source:
 4    type: websocket
 5    uri: "wss://gra1.logs.ovh.com/tail/?tk=abcdefghijklmnopqrstuvwxyz"
 6    tls:
 7      enabled: true
 8    decoding:
 9      codec: json
10
11transforms:
12  ovh_ldp_transform:
13    type: remap
14    inputs:
15      - ovh_ldp_source
16    source: |
17      . = parse_json!(.message)
18      . = parse_json!(.short_message)
19
20sinks:
21  stdout_sink:
22    type: console
23    inputs:
24      - ovh_ldp_transform
25    encoding:
26      codec: "json"
27      json:
28        pretty: true
 1$ vector -c vector-2.yaml
 22025-08-29T09:20:09.555364Z  INFO vector::app: Log level is enabled. level="info"
 32025-08-29T09:20:09.559014Z  INFO vector::app: Loading configs. paths=["vector-2.yaml"]
 42025-08-29T09:20:09.787928Z  INFO vector::topology::running: Running healthchecks.
 52025-08-29T09:20:09.789154Z  INFO vector::topology::builder: Healthcheck passed.
 62025-08-29T09:20:09.789801Z  INFO vector: Vector has started. debug="false" version="0.49.0" arch="aarch64" revision="dc7e792 2025-08-12 13:47:08.632326804"
 72025-08-29T09:20:09.790055Z  INFO vector::app: API is disabled, enable by setting `api.enabled` to `true` and use commands like `vector top`.
 8{
 9  "annotations": {
10    "authorization.k8s.io/decision": "allow",
11    "authorization.k8s.io/reason": "RBAC: allowed by RoleBinding \"kyverno:background-controller/kyverno\" of Role \"kyverno:background-controller\" to ServiceAccount \"kyverno-background-controller/kyverno\""
12  },
13  "apiVersion": "audit.k8s.io/v1",
14  "auditID": "f861cf50-a561-4ad7-b8f0-8bbb068152d3",
15  "kind": "Event",
16  "level": "Metadata",
17  "objectRef": {
18    "apiGroup": "coordination.k8s.io",
19    "apiVersion": "v1",
20    "name": "kyverno-background-controller",
21    "namespace": "kyverno",
22    "resource": "leases",
23    "resourceVersion": "37003755025",
24    "uid": "9fca9fef-d75f-4342-a69f-eada6f93de0f"
25  },
26  [...]

Ahh, c'est beaucoup mieux 👍 !

La suite

On a pu voir comment récupérer les logs de la "Logs Data Plaform" d'OVHCloud via websocket, grâce notamment à l'outil Vector.

Ca marche très bien en local, maintenant à vous de configurer vos transforms et sinks pour traiter vos logs comme bon vous semble.

De mon côté, c'est déployé via chart Helm en mode Aggregator sur mes clusters, avec quelques transforms nécessaires pour coller avec d'autres logs envoyés dans Loki.

Amusez-vous bien avec tous ces nouveaux logs !