# Centralizowane wdrażanie serwerów MCP w Kubernetes: architektura, uwierzytelnianie i zarządzanie sekretami
Lokalne uruchamianie serwerów MCP za pomocą menedżerów pakietów lub kontenerów szybko staje się wąskim gardłem przy skalowaniu infrastruktury AI na cały zespół. Rozproszone środowiska uruchomieniowe, niekontrolowane rozprzestrzenianie danych logowania i brak jednolitego punktu dostępu blokują bezpieczną integrację modeli językowych w środowisku firmowym. W artykule przedstawiono praktyczną ścieżkę migracji od izolowanych instancji do scentralizowanej architektury w Kubernetes z wykorzystaniem wzorca sidecar-proxy, walidacji JWT i orkiestracji sekretów.
Ewolucja architektury: od lokalnych procesów do konteneryzacji
Na początkowym etapie wdrożenia Model Context Protocol wystarczy korzystać z gotowych zdalnych endpointów od dostawców. Konfiguracja sprowadza się do podania URL w aplikacji klienckiej, a kwestie uwierzytelniania i skalowania przejmuje dostawca. Jednak przy podłączaniu wewnętrznych systemów (Kubernetes, Grafana, bazy danych) pojawia się potrzeba samodzielnego uruchamiania serwerów.
Standardowe podejście z lokalnym wywołaniem npx, uvx lub skompilowanych plików binarnych powoduje problemy z zarządzaniem zależnościami. Każda integracja wymaga osobnego środowiska uruchomieniowego, co prowadzi do konfliktów wersji i komplikuje onboarding nowych pracowników. Ponadto przechowywanie tokenów dostępu do środowisk produkcyjnych w lokalnych plikach konfiguracyjnych narusza podstawowe zasady bezpieczeństwa informacji.
Konteneryzacja rozwiązuje problem izolacji środowiska. Uruchamianie każdego serwera MCP w osobnym kontenerze z przekazywaniem zmiennych środowiskowych pozwala na standaryzację wdrożeń na poziomie jednej stacji roboczej. Przykładowa konfiguracja dla izolowanego uruchomienia:
{
"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>"
}
}
}
}
Mimo poprawy izolacji lokalny Docker nie rozwiązuje problemu współdzielonego dostępu. Zautomatyzowane potoki, systemy CI/CD i specjaliści nietechniczni nie mogą efektywnie współpracować z rozproszonymi kontenerami. Pojawia się potrzeba przeniesienia serwerów MCP do wspólnej infrastruktury ze scentralizowanym zarządzaniem cyklem życia.
Orkiestracja w Kubernetes: proxy i uniwersalne wdrażanie
Przeniesienie serwerów MCP do klastra wymaga rozwiązania niezgodności architektonicznej: większość serwerów działa przez stdio, podczas gdy interakcje sieciowe w Kubernetes opierają się na HTTP i HTTPS. Aby zniwelować tę lukę, stosuje się wzorzec sidecar z MCP Gateway. Kontener proxy odbiera przychodzące żądania HTTP (Streamable HTTP lub SSE), przekłada je na standardowy strumień wejściowy docelowego procesu i zwraca odpowiedź z powrotem do sieci.
Ponieważ serwery MCP w trybie Streamable HTTP są usługami stateless, idealnie nadają się do poziomego skalowania za pomocą HPA. Aby uniknąć dublowania manifestów dla każdej integracji, warto użyć uniwersalnego Helm charta obsługującego dwa tryby pracy:
- proxy — uruchomienie kontenera sidecar do translacji HTTP na stdio.
- native — bezpośrednie eksponowanie usług już obsługujących transport HTTP.
Konfiguracja wdrożenia przez values.yaml pozwala elastycznie zarządzać ustawieniami sieciowymi, przekazywaniem sekretów i routingiem:
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"
Integracja z HashiCorp Vault lub External Secrets Operator zapewnia, że dane logowania nie trafiają do systemu kontroli wersji. Kontroler Ingress lub Gateway API obsługuje routing, a wyłączenie buforowania oraz zwiększenie timeoutów jest niezbędne dla poprawnego działania długotrwałych połączeń i transmisji strumieniowej danych.
Bezpieczeństwo i uwierzytelnianie: JWT, Envoy i zarządzanie dostępem
Brak wbudowanych mechanizmów uwierzytelniania w samym protokole MCP wymaga wdrożenia ochrony na poziomie infrastrukturalnej bramy. Podstawowe uwierzytelnianie nie zapewnia wystarczającego poziomu bezpieczeństwa w środowisku korporacyjnym, dlatego optymalnym rozwiązaniem jest walidacja JWT przez Envoy Gateway. Brama weryfikuje podpis tokena, wydawcę i odbiorcę, zanim żądanie dotrze do poda z serwerem MCP.
Generowanie kluczy i tokenów odbywa się za pomocą standardowych narzędzi kryptograficznych. Klucz publiczny jest pakowany w format JWKS i umieszczany w ConfigMap, skąd Envoy pobiera go do weryfikacji:
# Generate RSA keys and create a 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}"
Na obecnym etapie rozwoju protokołu pozostaje kilka ograniczeń architektonicznych. Dostęp do systemów docelowych odbywa się za pośrednictwem jednolitych kont serwisowych, co jest akceptowalne dla operacji odczytu, ale stwarza ryzyka przy operacjach zapisu. Protokół nie przekazuje kontekstu użytkownika końcowego, co uniemożliwia wdrożenie autoryzacji użytkownika i szczegółowego audytu wywołań narzędzi. Logowanie na poziomie Envoy rejestruje tylko metadane sieciowe, ale nie parametry wywołań konkretnych metod MCP.
Co ważne
- Lokalne uruchamianie serwerów MCP nie skaluje się na zespół z powodu konfliktów środowisk uruchomieniowych i ryzyka wycieku danych logowania.
- Wzorzec sidecar z MCP Gateway rozwiązuje problem niezgodności transportu stdio i protokołów sieciowych Kubernetes.
- Architektura stateless Streamable HTTP pozwala na użycie standardowego HPA do automatycznego poziomego skalowania.
- Walidację JWT i routing należy przenosić na poziom API Gateway, ponieważ sam protokół nie zawiera mechanizmów uwierzytelniania.
- Brak przekazywania kontekstu użytkownika w MCP na razie ogranicza możliwości granularnej autoryzacji i audytu end-to-end.
— Editorial Team
Brak komentarzy.