Un secret Kubernetes stocké nativement dans etcd n’est pas chiffré. Il est simplement encodé en base64, ce qui revient à le cacher derrière un rideau transparent. Quiconque a accès à l’API server ou à une sauvegarde etcd peut le lire en clair en quelques secondes. C’est exactement pour combler cette faille que des milliers d’équipes déploient HashiCorp Vault devant leurs clusters de production. Depuis le rachat de HashiCorp par IBM et le passage à la version 2.0 en avril 2026, l’outil a changé de visage : nouveau modèle de support, fédération d’identité sans identifiants statiques, et une cadence de correctifs de sécurité plus soutenue. Ce tutoriel vous montre comment installer Vault 2.1.1 sur un cluster Kubernetes, connecter l’authentification native du cluster, injecter des secrets dans vos pods et générer des identifiants de base de données qui expirent automatiquement. Treize étapes, environ 90 minutes, et un projet complet à la fin pour vérifier que tout fonctionne. L’exercice vise en priorité les équipes plateforme qui gèrent déjà un cluster de cloud computing en production en Europe et qui doivent démontrer, face à un auditeur ou à un client, que les mots de passe de base de données ne dorment pas en clair quelque part dans un manifeste YAML.
Pourquoi les Secrets Kubernetes Natifs Ne Suffisent Pas
Le mécanisme Secret de Kubernetes a été pensé pour découpler la configuration sensible du code, pas pour protéger cette configuration contre un attaquant qui a déjà un pied dans le cluster. Par défaut, les objets Secret sont stockés dans etcd sans chiffrement au repos, sauf si l’administrateur active explicitement un Encryption Provider. Même avec ce chiffrement activé, toute personne disposant du droit RBAC get sur les secrets d’un namespace peut les lire intégralement, sans granularité plus fine, sans rotation automatique et sans piste d’audit détaillée sur qui a consulté quoi et quand.
Notre tutoriel sur les Secrets Kubernetes natifs détaille la configuration de base à connaître avant d’aller plus loin. Vault résout trois problèmes que Kubernetes ne traite pas nativement. D’abord, il génère des identifiants dynamiques : au lieu d’un mot de passe PostgreSQL fixe partagé par toute l’équipe, chaque pod reçoit un identifiant unique avec une durée de vie limitée, révoqué automatiquement à son expiration. Ensuite, il centralise la politique d’accès avec des règles granulaires par chemin, par méthode HTTP et par identité. Enfin, il journalise chaque lecture de secret dans un log d’audit exploitable, ce qui devient indispensable pour répondre aux exigences du Cyber Resilience Act ou de NIS2 en matière de traçabilité.
Vault 2.0 : le Tournant Post-IBM pour la Gestion des Secrets
Vault 2.0, sorti le 13 avril 2026, marque le premier changement de version majeure du produit depuis le lancement de la version 1.0 en 2018. HashiCorp, racheté par IBM, a basculé Vault sur le modèle de support IBM Support Cycle-2, qui garantit au minimum deux ans de support standard par version majeure. La nouveauté la plus structurante reste la fédération d’identité de charge de travail (Workload Identity Federation), qui permet à Vault de s’authentifier auprès d’AWS, Azure ou GCP sans identifiants statiques de longue durée, un point que ce tutoriel exploite plus loin pour durcir la configuration en production.
La branche 2.1, elle, a fait sortir de bêta le support natif des workflows agentiques le 1er septembre 2026 avec la version 2.1.0, suivie le 16 septembre 2026 par un correctif 2.1.1 qui referme plusieurs bugs d’interface et une dépendance vulnérable (dompurify). Un peu plus tôt dans le cycle, Vault a aussi corrigé la CVE-2026-39829 en limitant la taille des clés RSA du moteur SSH à 8192 bits. C’est la version que ce guide installe : Vault 2.1.1, la plus récente disponible au moment de la rédaction.
Le support des workflows agentiques mérite un mot d’explication pour une audience sécurité. Il ne s’agit pas d’exposer Vault directement à un agent IA sans contrôle, mais d’un registre dédié qui permet de délivrer des jetons à portée limitée et de courte durée à des identités automatisées, avec des politiques de type “ceiling policy” qui plafonnent les droits qu’un agent peut jamais obtenir, quelle que soit la politique qui lui est attribuée par erreur. Ce garde-fou répond directement à une inquiétude montante : des agents IA qui accèdent à des secrets d’infrastructure sans limite claire de ce qu’ils peuvent lire ou modifier.
HashiCorp Vault vs Secrets Kubernetes Natifs : le Comparatif
Avant de se lancer dans l’installation, il vaut mieux comprendre précisément ce que Vault apporte par rapport à l’objet Secret natif de Kubernetes. Le tableau suivant résume les écarts fonctionnels observés en usage courant.
| Critère | Secrets Kubernetes natifs | HashiCorp Vault |
|---|---|---|
| Chiffrement au repos | Désactivé par défaut, base64 uniquement | Chiffré nativement (AES-256-GCM via le backend de stockage) |
| Identifiants dynamiques | Non, valeurs statiques | Oui, génération à la demande avec TTL |
| Rotation automatique | Manuelle uniquement | Automatique selon la politique définie |
| Journal d’audit détaillé | Limité aux événements API Kubernetes | Log d’audit dédié par requête |
| Granularité des politiques | RBAC par namespace/verbe | Politiques par chemin, méthode et identité |
| Multi-cloud / multi-cluster | Non, propre à chaque cluster | Oui, instance centralisée partagée |
| Coût opérationnel | Faible, aucun composant à gérer | Plus élevé, nécessite exploitation dédiée |
Ce comparatif ne veut pas dire qu’il faut abandonner les Secrets natifs. Vault s’intègre justement avec eux via le Vault Secrets Operator, qui synchronise les valeurs stockées dans Vault vers de vrais objets Secret Kubernetes, combinant la sécurité de Vault et la simplicité d’usage attendue par les développeurs.
Dans la pratique, l’adoption se fait rarement d’un seul coup sur l’ensemble d’un cluster. La plupart des équipes commencent par migrer les secrets les plus sensibles, typiquement les identifiants de base de données et les clés d’API tierces, avant d’étendre progressivement la couverture aux configurations moins critiques. Cette approche incrémentale limite le risque d’interruption de service et laisse le temps à l’équipe plateforme de roder ses procédures de sauvegarde et de restauration avant que Vault ne devienne un point de passage obligé pour toute la production.
Architecture : Comment Vault S’Intègre à un Cluster Kubernetes
Vault tourne comme n’importe quel StatefulSet dans le cluster, généralement en mode haute disponibilité avec trois ou cinq répliques qui partagent un même état via le protocole Raft intégré (Integrated Storage). Un seul pod détient le rôle de leader à un instant donné, les autres suivent en tant que standby et prennent le relais automatiquement en cas de panne. Les applications ne parlent jamais directement à etcd ou à un backend de stockage tiers : elles interrogent l’API HTTP de Vault, qui vérifie l’identité de l’appelant via la méthode d’authentification Kubernetes avant de renvoyer un secret.
Toutes les données écrites dans Vault, y compris dans le stockage Raft local à chaque pod, restent chiffrées au repos avec une clé de chiffrement qui n’existe jamais en clair sur disque. Cette clé de chiffrement est elle-même protégée par une clé maîtresse, reconstituée uniquement au démarrage grâce au partage de secret de Shamir : la clé maîtresse est fractionnée en plusieurs parts, et un quorum de ces parts (trois sur cinq dans ce tutoriel) est nécessaire pour la reconstituer. Tant que ce quorum n’est pas atteint, Vault reste scellé et refuse de servir la moindre requête, même à un administrateur disposant du root token. C’est cette conception qui empêche un attaquant ayant simplement copié le disque d’un pod Vault de récupérer les secrets sans posséder également les clés de descellement.
Trois mécanismes permettent de faire transiter un secret de Vault vers un pod applicatif. Le Vault Agent Injector ajoute un conteneur sidecar chargé de récupérer et de rafraîchir les secrets sur un volume partagé. Le CSI Provider monte les secrets directement via un volume CSI éphémère, sans sidecar supplémentaire. Le Vault Secrets Operator (VSO) synchronise quant à lui les secrets Vault vers de véritables objets Secret Kubernetes, surveillés en continu. Ce tutoriel couvre l’Agent Injector en détail, puis le VSO pour les cas où l’application ne peut pas être modifiée pour lire un fichier monté.
Le choix entre ces trois mécanismes dépend surtout de la contrainte opérationnelle dominante. Une équipe qui gère des centaines de microservices et surveille de près la densité de pods par nœud évitera d’empiler un sidecar sur chaque déploiement, et préférera le CSI Provider ou le VSO. Une équipe qui migre progressivement une flotte d’applications historiques, incapables de lire un secret Vault sans passer par un objet Secret Kubernetes classique, s’appuiera d’abord sur le VSO avant d’envisager une réécriture plus profonde. Il n’existe pas de méthode universellement supérieure : chaque projet de migration vers Vault commence par un inventaire des contraintes techniques réelles, pas par un choix théorique.
Prérequis et Versions Nécessaires
Voici l’environnement exact utilisé pour ce tutoriel. Les commandes ont été testées avec ces versions précises : des versions plus anciennes de Helm ou de Kubernetes peuvent provoquer des erreurs de compatibilité de CRD.
| Composant | Version utilisée | Rôle |
|---|---|---|
| Kubernetes | 1.30 ou supérieur | Cluster cible (EKS, GKE, AKS ou local) |
| Helm | 3.15 ou supérieur | Déploiement des charts Vault et VSO |
| kubectl | Alignée sur la version du cluster | Administration du cluster |
| vault-helm (chart) | 0.34.1 | Déploiement du serveur Vault |
| Vault (image du serveur) | 2.1.1 | Moteur de secrets et de politiques |
| vault-secrets-operator (chart) | 1.6.0 | Synchronisation Vault vers Secrets Kubernetes |
| CLI vault | 2.1.1 (alignée sur le serveur) | Administration en ligne de commande |
Prévoyez aussi un cluster avec au moins trois nœuds si vous testez le mode haute disponibilité, et des droits cluster-admin le temps de l’installation (vous pourrez restreindre ces droits ensuite). Un espace disque persistant (StorageClass avec provisioning dynamique) est requis pour le stockage Raft de Vault.
Ce tutoriel fonctionne aussi bien sur un cluster managé (EKS, GKE, AKS) que sur un cluster local monté avec kind ou minikube, à condition que le provisioning de volumes persistants soit configuré. Sur un cluster local, réduisez le nombre de répliques Vault à une seule instance pour économiser des ressources, en sachant que ce choix supprime la tolérance de panne offerte par le mode haute disponibilité et ne convient donc qu’à un usage de démonstration.
Étapes 1 à 3 : Installer Vault sur Kubernetes avec Helm
Étape 1 : Créer le namespace et ajouter le dépôt Helm
Isolez Vault dans son propre namespace pour appliquer des politiques réseau strictes plus tard. Si vous découvrez Helm pour la première fois, notre tutoriel Helm sur Kubernetes couvre les bases du gestionnaire de paquets utilisé ici.
kubectl create namespace vault
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm search repo hashicorp/vault --versions | head -5
Étape 2 : Rédiger le fichier values.yaml pour le mode HA
Le mode haute disponibilité avec stockage Raft intégré élimine la dépendance à un backend externe comme Consul.
server:
image:
tag: "2.1.1"
ha:
enabled: true
replicas: 3
raft:
enabled: true
setNodeId: true
auditStorage:
enabled: true
size: 5Gi
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 512Mi
cpu: 500m
injector:
enabled: true
image:
tag: "1.5.1"
ui:
enabled: true
Étape 3 : Déployer Vault avec Helm
helm install vault hashicorp/vault \
--namespace vault \
--version 0.34.1 \
-f values.yaml
kubectl get pods -n vault -w
Les pods vault-0, vault-1 et vault-2 apparaissent avec le statut Running mais 0/1 prêt : c’est normal, Vault démarre scellé (sealed) tant qu’il n’a pas été initialisé.
Étapes 4 à 6 : Initialiser, Désceller et Configurer Vault
Étape 4 : Initialiser Vault et sécuriser les clés de descellement
kubectl exec -n vault vault-0 -- vault operator init \
-key-shares=5 \
-key-threshold=3 \
-format=json > vault-init.json
cat vault-init.json | jq -r '.unseal_keys_b64[]'
cat vault-init.json | jq -r '.root_token'
Cette commande génère cinq clés de descellement, dont trois suffisent pour reconstituer la clé maîtresse. Ne stockez jamais vault-init.json dans un dépôt Git : chiffrez-le immédiatement avec une solution comme GPG ou un coffre-fort externe, puis supprimez le fichier local.
Étape 5 : Désceller chaque pod Vault
for pod in vault-0 vault-1 vault-2; do
kubectl exec -n vault $pod -- vault operator unseal
kubectl exec -n vault $pod -- vault operator unseal
kubectl exec -n vault $pod -- vault operator unseal
done
kubectl get pods -n vault
Sortie attendue une fois tous les pods déscellés :
NAME READY STATUS RESTARTS AGE
vault-0 1/1 Running 0 4m
vault-1 1/1 Running 0 4m
vault-2 1/1 Running 0 4m
Étape 6 : Se connecter à Vault et activer le moteur KV v2
kubectl exec -it -n vault vault-0 -- /bin/sh
export VAULT_TOKEN=
vault login $VAULT_TOKEN
vault secrets enable -path=secret kv-v2
vault kv put secret/demo-app/config username="app_user" password="ChangeMe123!"
vault kv get secret/demo-app/config
Étapes 7 à 9 : Authentification Kubernetes et Politiques d’Accès
Étape 7 : Activer la méthode d’authentification Kubernetes
vault auth enable kubernetes
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443"
Vault utilise le compte de service du pod pour valider les jetons de projection (Bound Service Account Token Volume), la méthode recommandée depuis l’abandon des tokens statiques de compte de service dans les versions récentes de Kubernetes. Concrètement, quand un pod tente de s’authentifier, Vault transmet le jeton présenté à l’API TokenReview du cluster, qui confirme ou infirme l’identité du ServiceAccount appelant. Vault ne fait donc jamais confiance à un jeton sur simple présentation : il revalide systématiquement chaque authentification auprès du serveur d’API Kubernetes, ce qui empêche un jeton volé et rejoué en dehors du cluster de fonctionner.
Étape 8 : Créer une politique d’accès en moindre privilège
cat <
Cette politique n'accorde que la lecture, et uniquement sous le chemin secret/data/demo-app/*. Une erreur fréquente à ce stade consiste à écrire secret/* pour aller plus vite : cela expose tous les secrets de tous les projets à cette seule application.
Étape 9 : Lier un ServiceAccount, un namespace et une politique
vault write auth/kubernetes/role/demo-app \
bound_service_account_names=demo-app-sa \
bound_service_account_namespaces=default \
policies=demo-app-policy \
ttl=1h
Le rôle demo-app n'accepte des jetons que du ServiceAccount demo-app-sa dans le namespace default, avec un jeton Vault dont la durée de vie n'excède pas une heure.
Étapes 10 à 11 : Injecter des Secrets avec le Vault Agent Injector
Étape 10 : Créer le ServiceAccount et annoter le déploiement
kubectl create serviceaccount demo-app-sa
cat < deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
spec:
replicas: 1
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "demo-app"
vault.hashicorp.com/agent-inject-secret-config.txt: "secret/data/demo-app/config"
spec:
serviceAccountName: demo-app-sa
containers:
- name: demo-app
image: node:20-alpine
command: ["sleep", "infinity"]
EOF
kubectl apply -f deployment.yaml
Étape 11 : Vérifier que le secret est bien injecté
kubectl get pods -l app=demo-app
POD=$(kubectl get pod -l app=demo-app -o jsonpath="{.items[0].metadata.name}")
kubectl exec $POD -c demo-app -- cat /vault/secrets/config.txt
Sortie attendue :
data: map[password:ChangeMe123! username:app_user]
metadata: map[created_time:2026-09-20T10:14:02.913245Z ...]
Le pod affiche désormais deux conteneurs (2/2 Ready) : votre application et le sidecar vault-agent, qui rafraîchit automatiquement le fichier config.txt tant que le jeton reste valide.
Étapes 12 à 13 : Vault Secrets Operator et Identifiants Dynamiques PostgreSQL
Étape 12 : Déployer le Vault Secrets Operator
Le VSO synchronise les secrets Vault vers de véritables objets Secret Kubernetes, ce qui évite de modifier le code applicatif pour lire un fichier monté par un sidecar. Consultez le tutoriel officiel du Vault Secrets Operator pour le détail des CRD disponibles.
helm install vault-secrets-operator hashicorp/vault-secrets-operator \
--namespace vault-secrets-operator-system \
--create-namespace \
--version 1.6.0
kubectl get pods -n vault-secrets-operator-system
Étape 13 : Activer le moteur de secrets dynamiques PostgreSQL
vault secrets enable database
vault write database/config/demo-postgres \
plugin_name=postgresql-database-plugin \
allowed_roles="demo-app-role" \
connection_url="postgresql://{{username}}:{{password}}@postgres.default.svc:5432/appdb?sslmode=disable" \
username="vault_admin" \
password="AdminPasswordFromSecretsManager"
vault write database/roles/demo-app-role \
db_name=demo-postgres \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
Chaque lecture de database/creds/demo-app-role crée un nouvel utilisateur PostgreSQL, avec un mot de passe unique et une expiration automatique après une heure. Vault révoque lui-même le compte à l'échéance, sans intervention manuelle.
Ce cycle de vie change fondamentalement la surface d'attaque d'une base de données exposée en interne. Avec un mot de passe statique, un identifiant qui fuit dans un log applicatif ou un fichier de configuration oublié reste valide indéfiniment, jusqu'à ce que quelqu'un pense à le changer. Avec des identifiants dynamiques à durée de vie d'une heure, la fenêtre d'exploitation d'une fuite se referme automatiquement, sans dépendre de la vigilance d'un humain. C'est probablement l'argument le plus convaincant pour justifier l'effort d'exploitation supplémentaire que représente Vault face à un simple objet Secret Kubernetes.
Projet Complet : une API Node.js Alimentée par des Identifiants Vault
Voici un exemple fonctionnel complet qui combine tout ce qui précède : une API Node.js qui lit ses identifiants PostgreSQL dynamiques injectés par le Vault Agent, sans jamais stocker de mot de passe en dur.
// server.js
const fs = require("fs");
const express = require("express");
const { Client } = require("pg");
const app = express();
function readVaultSecret() {
const raw = fs.readFileSync("/vault/secrets/db-creds.txt", "utf-8");
const lines = Object.fromEntries(
raw.split("\n").filter(Boolean).map((l) => l.split(": "))
);
return lines;
}
app.get("/health", async (req, res) => {
const creds = readVaultSecret();
const client = new Client({
host: "postgres.default.svc",
user: creds.username,
password: creds.password,
database: "appdb",
});
await client.connect();
const result = await client.query("SELECT 1 AS ok");
await client.end();
res.json({ status: "ok", db: result.rows[0] });
});
app.listen(3000, () => console.log("API en écoute sur le port 3000"));
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package.json server.js ./
RUN npm install express pg
CMD ["node", "server.js"]
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-api
spec:
replicas: 2
selector:
matchLabels:
app: demo-api
template:
metadata:
labels:
app: demo-api
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "demo-app"
vault.hashicorp.com/agent-inject-secret-db-creds.txt: "database/creds/demo-app-role"
vault.hashicorp.com/agent-inject-template-db-creds.txt: |
{{- with secret "database/creds/demo-app-role" -}}
username: {{ .Data.username }}
password: {{ .Data.password }}
{{- end -}}
spec:
serviceAccountName: demo-app-sa
containers:
- name: demo-api
image: registry.example.com/demo-api:1.0.0
ports:
- containerPort: 3000
Déployez avec kubectl apply -f api-deployment.yaml, puis testez avec kubectl port-forward svc/demo-api 3000:3000 et curl localhost:3000/health. La réponse {"status":"ok","db":{"ok":1}} confirme que l'API a récupéré des identifiants PostgreSQL valides directement depuis Vault, sans jamais les avoir codés en dur.
Ce projet reste volontairement minimal pour rester lisible, mais la même structure s'applique à une API en production. Il suffit de remplacer sleep infinity par une vraie image applicative, de pointer connection_url vers la base réelle et d'ajuster les creation_statements aux privilèges strictement nécessaires à chaque service. Le point à retenir : le code applicatif ne connaît jamais le mot de passe à l'avance, il le lit à chaque démarrage depuis un fichier local généré par le sidecar Vault, ce qui rend le déploiement portable d'un environnement à l'autre sans changer une ligne de configuration sensible.
Agent Injector vs CSI Provider vs VSO : Quelle Méthode Choisir
Les trois méthodes d'intégration ne se valent pas selon le contexte. Ce tableau aide à trancher rapidement.
| Méthode | Avantage principal | Limite | Cas d'usage idéal |
|---|---|---|---|
| Vault Agent Injector | Rafraîchissement automatique du fichier de secret | Ajoute un conteneur sidecar par pod | Applications qui lisent des fichiers de config |
| CSI Provider | Pas de sidecar, montage direct en volume | Ne rafraîchit pas toujours en continu selon la config | Workloads sensibles à la consommation de ressources |
| Vault Secrets Operator (VSO) | Compatible avec les objets Secret Kubernetes natifs | Le secret existe aussi en clair dans etcd (chiffré si activé) | Applications existantes non modifiables |
En pratique, beaucoup d'équipes combinent les trois : le VSO pour les applications legacy qui attendent un Secret natif, l'Agent Injector pour les nouveaux services capables de lire un fichier, et le CSI Provider quand le nombre de sidecars devient un problème de densité de pods par nœud. Rien n'empêche de faire cohabiter les trois mécanismes sur un même cluster, à condition de documenter clairement quelle équipe utilise quelle méthode pour éviter qu'un nouvel arrivant ne réinvente une quatrième approche par méconnaissance des choix déjà faits.
Vault Face aux Alternatives : AWS Secrets Manager, Azure Key Vault et External Secrets Operator
Vault n'est pas la seule option pour sortir des Secrets Kubernetes natifs, et il vaut mieux le savoir avant de s'engager dans une migration de plusieurs semaines. AWS Secrets Manager et Azure Key Vault proposent tous deux une gestion centralisée des secrets avec rotation automatique, mais restreinte à l'écosystème de leur fournisseur cloud respectif. Une équipe déjà entièrement sur AWS, sans ambition multi-cloud, tire souvent plus vite parti d'AWS Secrets Manager que d'un déploiement Vault complet, simplement parce que l'intégration IAM est native et qu'il n'y a rien à exploiter soi-même. L'inverse est vrai pour Azure Key Vault sur un socle Azure homogène : notre tutoriel Azure Key Vault détaille cette alternative pas à pas.
Le projet External Secrets Operator (ESO) occupe une position différente : ce n'est pas un coffre-fort de secrets, mais un pont générique qui synchronise des secrets depuis Vault, AWS Secrets Manager, Azure Key Vault ou une dizaine d'autres backends vers de vrais objets Secret Kubernetes. ESO peut ainsi cohabiter avec Vault, exactement comme le VSO présenté plus haut, mais avec l'avantage de ne pas verrouiller l'équipe sur l'écosystème HashiCorp si un changement de fournisseur de secrets devient nécessaire plus tard.
| Solution | Portée | Identifiants dynamiques | Meilleur cas d'usage |
|---|---|---|---|
| HashiCorp Vault | Multi-cloud, agnostique | Oui, très étendu (bases de données, cloud, PKI) | Environnements hybrides ou multi-cloud |
| AWS Secrets Manager | Écosystème AWS uniquement | Limité, surtout via Lambda de rotation | Charges de travail 100 % AWS |
| Azure Key Vault | Écosystème Azure uniquement | Limité, intégré à Azure AD | Charges de travail 100 % Azure |
| External Secrets Operator | Pont universel vers d'autres backends | Dépend du backend connecté | Synchroniser plusieurs sources de secrets existantes |
Le choix se résume rarement à une question purement technique. Une équipe soumise au Cyber Resilience Act ou à des exigences de souveraineté numérique européenne penchera plus facilement vers un déploiement Vault auto-hébergé, dont elle garde le contrôle total, plutôt que vers un service managé chez un hyperscaler américain.
Durcissement, Rotation et Bonnes Pratiques pour la Production
Une installation qui fonctionne en environnement de test n'est pas automatiquement prête pour la production. Voici les ajustements qui font la différence à l'échelle d'un cluster réel.
- Activer l'audit logging dès le premier jour avec
vault audit enable file file_path=/vault/logs/audit.log, faute de quoi les événements passés sont perdus définitivement et aucune investigation rétroactive ne sera possible après un incident. - Adopter la fédération d'identité de charge de travail (Workload Identity Federation) introduite avec Vault 2.0 pour authentifier Vault auprès d'AWS, Azure ou GCP sans clé d'accès statique stockée quelque part, ce qui supprime une catégorie entière de secrets à protéger.
- Isoler Vault avec une NetworkPolicy qui n'autorise que le trafic entrant depuis les namespaces applicatifs légitimes sur le port 8200, plutôt que de laisser le service accessible depuis n'importe quel pod du cluster. Notre tutoriel Cilium Zero Trust détaille la mise en œuvre de ces politiques réseau.
- Segmenter par namespace Vault (Vault Enterprise) ou par préfixe de chemin (Vault Community) pour qu'une équipe ne puisse jamais lire les secrets d'une autre équipe, même en cas d'erreur de configuration locale.
- Automatiser la rotation des root tokens et révoquer le token racine initial une fois l'authentification Kubernetes opérationnelle : il ne doit plus jamais servir au quotidien, et sa moindre utilisation devrait déclencher une alerte.
- Sauvegarder l'état Raft régulièrement avec
vault operator raft snapshot save, testé sur un cluster de restauration séparé au moins une fois par trimestre pour vérifier que la sauvegarde est réellement exploitable, pas seulement présente sur disque.
Conseils Avancés : PKI, Transit et Multi-Tenancy
Une fois l'installation de base stabilisée, trois fonctionnalités de Vault méritent d'être explorées pour aller au-delà de la simple substitution des mots de passe statiques. Le moteur PKI transforme Vault en autorité de certification interne : il peut émettre des certificats TLS de courte durée pour le trafic est-ouest entre microservices, avec une révocation automatique à l'expiration plutôt qu'une liste de révocation à maintenir manuellement. C'est une alternative crédible à un maillage de service complet quand l'équipe n'a pas encore les moyens d'exploiter Istio ou Linkerd.
Le moteur Transit, lui, fait de Vault un service de chiffrement à la demande sans jamais exposer la clé de chiffrement à l'application appelante. Une API envoie une donnée en clair à l'endpoint transit/encrypt/ma-cle, reçoit un texte chiffré en retour, et ne détient jamais la clé elle-même. C'est le pattern recommandé pour chiffrer des données sensibles au niveau applicatif (numéros de carte, données de santé) avant de les écrire en base, indépendamment du chiffrement au repos déjà assuré par la base de données.
Enfin, sur les clusters partagés par plusieurs équipes, les namespaces Vault (fonctionnalité Enterprise) ou une convention stricte de préfixes de chemin (en version Community) permettent d'isoler complètement les secrets d'une équipe métier de ceux d'une autre, avec des administrateurs distincts par périmètre. Cette isolation évite qu'une erreur de politique dans un projet secondaire n'expose accidentellement les secrets d'une application critique. Vault ne remplace pas un durcissement plus large du cluster : consultez aussi notre guide de durcissement Kubernetes et containerd pour couvrir les couches en dessous du cluster.
Erreurs Courantes à Éviter
La plupart des incidents liés à Vault sur Kubernetes proviennent des mêmes six erreurs, observées régulièrement dans des configurations de production. Elles ont un point commun : chacune part d'un raccourci pris pendant la phase de test, jamais corrigé avant le passage en production.
- Laisser Vault en mode développeur (
vault server -dev) en production : ce mode stocke tout en mémoire, sans persistance ni chiffrement, et se réinitialise au moindre redémarrage. Il génère aussi un root token affiché en clair dans les logs de démarrage, ce qui en fait une porte grande ouverte si le mode dev survit au-delà d'un test local. - Écrire des politiques trop larges comme
secret/*au lieu de restreindre chaque rôle à son propre préfixe applicatif. Une politique large transforme une compromission d'un seul service en fuite de tous les secrets du cluster. - Committer
vault-init.jsonou le root token dans un dépôt Git, même privé : ce fichier doit être chiffré et stocké hors du contrôle de version, idéalement dans un coffre-fort séparé du cluster qu'il protège. - Oublier de lier le rôle Kubernetes à un namespace précis, ce qui permet à n'importe quel ServiceAccount portant le même nom, dans n'importe quel namespace, de s'authentifier avec la même politique.
- Fixer un TTL de token trop long sur les rôles applicatifs, ce qui annule l'intérêt des identifiants dynamiques à courte durée de vie et redonne à un jeton volé une fenêtre d'exploitation confortable.
- Ne pas tester le processus de descellement après un redémarrage complet du cluster : sans clés accessibles rapidement, un incident de disponibilité peut durer des heures, le temps de retrouver qui détient quelle part de la clé maîtresse.
Dépannage : les Problèmes Fréquents et Leurs Solutions
Voici les incidents les plus souvent rencontrés lors du déploiement de Vault sur Kubernetes, avec la cause probable et la correction associée.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Pod vault-0 reste à 0/1 Ready | Vault est scellé après le démarrage | Exécuter vault operator unseal avec trois clés valides |
| Erreur "connection refused" sur le port 8200 | NetworkPolicy trop restrictive ou service mal ciblé | Vérifier kubectl get svc -n vault et les règles réseau |
| "permission denied" à l'authentification Kubernetes | Politique non liée au bon rôle ou ServiceAccount incorrect | Vérifier bound_service_account_names et bound_service_account_namespaces |
| Le fichier de secret injecté reste vide | Annotation d'injection mal formée ou chemin de secret inexistant | Contrôler la syntaxe des annotations vault.hashicorp.com/agent-inject-secret-* |
| Le sidecar vault-agent est en CrashLoopBackOff | Image du sidecar incompatible avec la version du serveur Vault | Aligner injector.image.tag sur une version supportée |
| VaultStaticSecret ne se synchronise jamais | CRD du VSO non installées ou opérateur non démarré | Vérifier kubectl get pods -n vault-secrets-operator-system |
| "no matching role" pendant l'authentification | Le rôle Kubernetes référencé dans les annotations n'existe pas côté Vault | Recréer le rôle avec vault write auth/kubernetes/role/... |
| Le token Vault expire trop souvent | TTL trop court sur le rôle ou la politique d'authentification | Ajuster ttl et max_ttl sur le rôle Kubernetes |
| Impossible de restaurer un snapshot Raft | Version de Vault différente entre la sauvegarde et le cluster cible | Restaurer sur une version identique ou supérieure compatible |
Pour la majorité de ces cas, le réflexe le plus rentable reste de consulter les logs du serveur Vault (kubectl logs vault-0 -n vault) avant ceux du sidecar : Vault journalise systématiquement la raison exacte d'un refus d'authentification ou d'une politique insuffisante, alors que le sidecar se contente souvent d'un message générique de connexion échouée.
Questions Fréquentes
Faut-il remplacer complètement les Secrets Kubernetes par Vault ?
Non. Le Vault Secrets Operator permet de garder des objets Secret Kubernetes classiques en façade, tout en les alimentant depuis Vault. La migration peut se faire progressivement, application par application.
Vault fonctionne-t-il sans stockage externe comme Consul ?
Oui. Le stockage Raft intégré (Integrated Storage), utilisé dans ce tutoriel, élimine la dépendance à Consul depuis plusieurs versions majeures et simplifie fortement l'exploitation.
Quelle est la différence entre Vault Community et Vault Enterprise ?
La version Community couvre l'essentiel de ce tutoriel : moteur KV, secrets dynamiques, authentification Kubernetes, moteur PKI et moteur Transit. La version Enterprise ajoute la réplication multi-région, les namespaces isolés, la haute disponibilité active-active entre plusieurs datacenters et certaines fonctionnalités de fédération d'identité avancées. Pour un premier déploiement sur un seul cluster, la version Community suffit largement.
Comment savoir si mon cluster utilise déjà le chiffrement au repos pour etcd ?
Vérifiez la configuration EncryptionConfiguration de l'API server. Sans cette configuration, les objets Secret Kubernetes sont stockés en clair (base64) dans etcd, quel que soit le fournisseur cloud utilisé.
Peut-on utiliser Vault pour gérer des certificats TLS en plus des mots de passe ?
Oui, via le moteur PKI de Vault, qui peut émettre des certificats à courte durée de vie et servir d'autorité de certification interne pour le cluster.
Que se passe-t-il si tous les pods Vault redémarrent en même temps ?
Ils redémarrent scellés. Sans processus de descellement automatisé (via un mécanisme d'auto-unseal cloud comme AWS KMS ou Azure Key Vault), un opérateur humain doit fournir manuellement les clés de descellement, ce qui peut interrompre l'accès aux secrets pendant plusieurs minutes selon la disponibilité de cet opérateur. C'est pourquoi la plupart des déploiements de production configurent l'auto-unseal dès l'installation initiale plutôt que d'attendre un premier incident pour s'en préoccuper.
La CVE-2026-39829 affecte-t-elle cette installation ?
Non, elle est corrigée dans Vault 2.1.1, la version installée dans ce tutoriel. Elle concernait une limite de taille de clé RSA insuffisante dans le moteur de secrets SSH.
Vault ralentit-il les applications qui lisent des secrets à chaque requête ?
Les identifiants dynamiques sont mis en cache localement par le Vault Agent jusqu'à leur expiration. Seule la première lecture, ou le renouvellement, entraîne un appel réseau vers Vault. Pour aller plus loin sur les bonnes pratiques générales de gestion de clés, voir les recommandations du NIST SP 800-57 et les bonnes pratiques officielles Kubernetes sur les secrets.




