Déploiement centralisé des serveurs MCP dans Kubernetes : Architecture, authentification et gestion des secrets
L'exécution de serveurs MCP localement via des gestionnaires de paquets ou des conteneurs devient rapidement un goulot d'étranglement lors de la mise à l'échelle de l'infrastructure IA à travers une équipe. Des environnements d'exécution fragmentés, une propagation incontrôlée des identifiants et l'absence d'un point d'entrée unique entravent l'intégration sécurisée des modèles de langage dans l'environnement d'entreprise. Cet article décrit un chemin de migration pratique des instances isolées vers une architecture Kubernetes centralisée utilisant un proxy sidecar, la validation JWT et l'orchestration des secrets.
Évolution de l'architecture : Des processus locaux à la conteneurisation
Au stade initial d'adoption du Model Context Protocol, l'utilisation d'endpoints distants prêts à l'emploi fournis par les éditeurs suffit. La configuration se limite simplement à spécifier une URL dans l'application cliente, le fournisseur gérant l'authentification et la mise à l'échelle. Cependant, l'intégration de systèmes internes (Kubernetes, Grafana, bases de données) nécessite de lancer les serveurs de manière indépendante.
L'approche standard avec des appels npx, uvx locaux ou des binaires compilés crée des maux de tête en gestion de dépendances. Chaque intégration requiert son propre environnement d'exécution, entraînant des conflits de versions et compliquant l'intégration des nouveaux membres de l'équipe. Stocker les jetons d'accès à la production dans des fichiers de configuration locaux viole également les principes fondamentaux de la sécurité de l'information.
La conteneurisation résout l'isolation des environnements. Lancer chaque serveur MCP dans son propre conteneur avec transmission des variables d'environnement standardise le déploiement au niveau de la station de travail. Exemple de configuration pour un lancement isolé :
{
"mcpServers": {
"grafana": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "GRAFANA_URL",
"-e", "GRAFANA_SERVICE_ACCOUNT_TOKEN",
"grafana/mcp-grafana",
"-t", "stdio"
],
"env": {
"GRAFANA_URL": "https://grafana.example.com",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<token>"
}
}
}
}
Malgré une meilleure isolation, Docker local ne permet pas un accès partagé. Les pipelines automatisés, les systèmes CI/CD et les utilisateurs non techniques ne peuvent pas travailler efficacement avec des conteneurs dispersés. Cela crée un besoin de migrer les serveurs MCP vers une infrastructure partagée avec une gestion centralisée du cycle de vie.
Orchestration dans Kubernetes : Proxying et déploiement universel
La migration des serveurs MCP vers un cluster nécessite de combler les incompatibilités architecturales : la plupart des serveurs utilisent stdio, tandis que le réseau Kubernetes repose sur HTTP/HTTPS. Le motif sidecar avec MCP Gateway comble cette lacune. Le conteneur proxy gère les requêtes HTTP entrantes (Streamable HTTP ou SSE), les transmet vers stdin du processus cible et relaie les réponses via le réseau.
Puisque les serveurs MCP en mode Streamable HTTP sont des services sans état, ils sont parfaits pour une mise à l'échelle horizontale via HPA. Pour éviter de dupliquer les manifestes par intégration, utilisez un chart Helm universel supportant deux modes :
- proxy — lancement de conteneur sidecar pour la traduction HTTP vers stdio.
- native — exposition directe des services supportant déjà le transport HTTP.
La configuration de déploiement via values.yaml offre un contrôle flexible sur le réseau, l'injection de secrets et le routage :
mode: proxy
proxy:
image:
repository: node
tag: "20-bookworm"
pullPolicy: IfNotPresent
gateway:
package: "@michlyn/mcpgateway"
stdioCommand: "npx -y @digitalocean/mcp --services apps,droplets,doks,networking"
outputTransport: streamable-http
port: 8080
httpPath: /mcp
vault:
enabled: true
role: "mcp"
path: "kubernetes_dev-fra1-01"
env:
- name: DIGITALOCEAN_API_TOKEN
value: vault:devops/data/ai/mcp/digitalocean#token
ingress:
enabled: true
className: "internal"
annotations:
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
L'intégration avec HashiCorp Vault ou External Secrets Operator maintient les identifiants hors du contrôle de version. Les contrôleurs Ingress ou Gateway API gèrent le routage, tandis que la désactivation du tamponnage et l'extension des délais d'attente assurent un support approprié pour les connexions longues et les données en streaming.
Sécurité et authentification : JWT, Envoy et gestion des accès
Le protocole MCP manque d'authentification intégrée, la protection doit donc être implémentée au niveau de la passerelle d'infrastructure. L'authentification basique est insuffisante pour la sécurité d'entreprise, rendant la validation JWT via Envoy Gateway la meilleure option. La passerelle vérifie la signature du jeton, l'émetteur et le public avant que les requêtes n'atteignent le pod du serveur MCP.
La génération de clés et de jetons utilise des outils crypto standards. La clé publique est packagée sous forme de JWKS dans un ConfigMap pour qu'Envoy la charge et la vérifie :
# Generate RSA keys and form JWT
openssl genrsa -out mcp-jwt-private.pem 4096
openssl rsa -in mcp-jwt-private.pem -pubout -out mcp-jwt-public.pem
KID=$(openssl rand -hex 16)
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT","kid":"${KID}"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')
PAYLOAD=$(echo -n '{"sub":"claude-desktop","aud":"mcp-servers","iss":"https://your-domain.com","iat":$(date +%s),"exp":$(( $(date +%s) + 31536000 ))}' | base64 -w0 | tr '+/' '-_' | tr -d '=')
SIGNATURE=$(echo -n "${HEADER}.${PAYLOAD}" | openssl dgst -sha256 -sign mcp-jwt-private.pem | base64 -w0 | tr '+/' '-_' | tr -d '=')
echo "${HEADER}.${PAYLOAD}.${SIGNATURE}"
À ce stade de maturité du protocole, des limitations architecturales persistent. L'accès aux systèmes cibles utilise des comptes de service partagés — acceptable pour les lectures, risqué pour les écritures. L'absence de transmission de contexte utilisateur bloque l'autorisation par utilisateur et l'audit détaillé des appels d'outils. Les logs Envoy ne capturent que les métadonnées réseau, pas les paramètres spécifiques des méthodes MCP.
Points clés
- Les lancements locaux de serveurs MCP ne s'étendent pas à l'échelle d'une équipe en raison des conflits d'environnements d'exécution et des risques de fuite d'identifiants.
- Le motif sidecar avec MCP Gateway relie le transport stdio et les protocoles réseau Kubernetes.
- L'architecture Streamable HTTP sans état supporte HPA standard pour une mise à l'échelle horizontale automatique.
- Déléguez la validation JWT et le routage à une API Gateway, car le protocole n'a pas d'authentification native.
- L'absence de contexte utilisateur dans MCP limite l'autorisation granulaire et l'audit de bout en bout pour l'instant.
— Editorial Team
Aucun commentaire pour le moment.