Deployment Guide#
This guide covers various deployment strategies and best practices for Cloud Native MCP Server.
Table of Contents#
Prerequisites#
System Requirements#
- Operating System: Linux, macOS, or Windows
- CPU: Minimum 1 core, recommended 2+ cores
- Memory: Minimum 512MB, recommended 1GB+
- Disk: Minimum 100MB
- Network: Access to Kubernetes cluster and configured services
Software Requirements#
- Go: 1.25+ (building from source)
- Docker: 20.10+ (containerized deployment)
- kubectl: Configured cluster access
- Helm: 3.0+ (Helm deployment)
Service Dependencies#
Optional services to connect to:
- Grafana (optional)
- Prometheus (optional)
- Kibana (optional)
- Elasticsearch (optional)
- Alertmanager (optional)
- Jaeger (optional)
- OpenTelemetry (optional)
Quick Deployment#
Binary Deployment#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # Download the latest version
wget https://github.com/mahmut-Abi/cloud-native-mcp-server/releases/latest/download/cloud-native-mcp-server-linux-amd64
chmod +x cloud-native-mcp-server-linux-amd64
# Create configuration
cat > config.yaml << EOF
server:
mode: "sse"
addr: "0.0.0.0:8080"
logging:
level: "info"
kubernetes:
kubeconfig: ""
EOF
# Run
./cloud-native-mcp-server-linux-amd64
|
Docker Quick Start#
1
2
3
4
5
| docker run -d \
--name cloud-native-mcp-server \
-p 8080:8080 \
-v ~/.kube:/root/.kube:ro \
mahmutabi/cloud-native-mcp-server:latest
|
Kubernetes Deployment#
Basic Deployment#
Create deployment manifest:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-native-mcp-server
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: cloud-native-mcp-server
template:
metadata:
labels:
app: cloud-native-mcp-server
spec:
serviceAccountName: cloud-native-mcp-server
containers:
- name: cloud-native-mcp-server
image: mahmutabi/cloud-native-mcp-server:latest
ports:
- containerPort: 8080
env:
- name: MCP_MODE
value: "sse"
- name: MCP_ADDR
value: "0.0.0.0:8080"
- name: MCP_LOG_LEVEL
value: "info"
volumeMounts:
- name: kubeconfig
mountPath: /root/.kube
readOnly: true
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: kubeconfig
configMap:
name: kubeconfig
|
Service Account and RBAC#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| apiVersion: v1
kind: ServiceAccount
metadata:
name: cloud-native-mcp-server
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cloud-native-mcp-server
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch", "describe"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cloud-native-mcp-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cloud-native-mcp-server
subjects:
- kind: ServiceAccount
name: cloud-native-mcp-server
namespace: default
|
Service#
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: v1
kind: Service
metadata:
name: cloud-native-mcp-server
namespace: default
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
protocol: TCP
selector:
app: cloud-native-mcp-server
|
Ingress#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cloud-native-mcp-server
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: k8s-mcp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cloud-native-mcp-server
port:
number: 8080
|
Deployment#
1
2
3
4
5
6
7
8
9
10
| # Apply all manifests
kubectl apply -f deploy/kubernetes/
# Verify deployment
kubectl get pods -l app=cloud-native-mcp-server
kubectl logs -l app=cloud-native-mcp-server
# Test connection
kubectl port-forward svc/cloud-native-mcp-server 8080:8080
curl http://localhost:8080/health
|
Docker Deployment#
Docker Compose#
Create docker-compose.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| version: '3.8'
services:
cloud-native-mcp-server:
image: mahmutabi/cloud-native-mcp-server:latest
container_name: cloud-native-mcp-server
ports:
- "8080:8080"
volumes:
- ~/.kube:/root/.kube:ro
- ./config.yaml:/app/config.yaml:ro
environment:
- MCP_MODE=sse
- MCP_ADDR=0.0.0.0:8080
- MCP_LOG_LEVEL=info
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- monitoring
networks:
monitoring:
external: true
|
Running with Docker Compose#
1
2
3
4
5
6
7
8
9
10
11
| # Start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
# Restart
docker-compose restart
|
Custom Docker Image#
Build your own image:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o cloud-native-mcp-server ./cmd/server
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/cloud-native-mcp-server .
EXPOSE 8080
CMD ["./cloud-native-mcp-server"]
|
Build and push:
1
2
3
4
5
| # Build
docker build -t your-registry/cloud-native-mcp-server:latest .
# Push
docker push your-registry/cloud-native-mcp-server:latest
|
Helm Deployment#
Install from Chart Repository#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Add repository
helm repo add k8s-mcp https://mahmut-Abi.github.io/cloud-native-mcp-server
# Update repository
helm repo update
# Install
helm install cloud-native-mcp-server k8s-mcp/cloud-native-mcp-server
# Upgrade
helm upgrade cloud-native-mcp-server k8s-mcp/cloud-native-mcp-server
# Uninstall
helm uninstall cloud-native-mcp-server
|
Custom Values#
Create values.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| replicaCount: 2
image:
repository: mahmutabi/cloud-native-mcp-server
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
ingress:
enabled: true
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: k8s-mcp.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: k8s-mcp-tls
hosts:
- k8s-mcp.example.com
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
config:
server:
mode: "sse"
addr: "0.0.0.0:8080"
logging:
level: "info"
format: "json"
kubernetes:
kubeconfig: ""
grafana:
enabled: true
url: "http://grafana:3000"
apiKey: "${GRAFANA_API_KEY}"
prometheus:
enabled: true
address: "http://prometheus:9090"
rbac:
create: true
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch", "describe"]
serviceAccount:
create: true
name: ""
nodeSelector: {}
tolerations: []
affinity: {}
|
Install with Custom Values#
1
| helm install cloud-native-mcp-server ./deploy/helm/cloud-native-mcp-server -f values.yaml
|
Production Considerations#
High Availability#
Deploy multiple replicas with appropriate resource limits:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| replicaCount: 3
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
|
Resource Optimization#
Tune supported server and service parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| config:
server:
readTimeoutSec: 30
writeTimeoutSec: 0
idleTimeoutSec: 60
kubernetes:
timeoutSec: 30
qps: 100.0
burst: 200
ratelimit:
enabled: true
requests_per_second: 100
burst: 200
|
Security#
1. Enable Authentication#
1
2
3
4
5
| config:
auth:
enabled: true
mode: "apikey"
apiKey: "${MCP_AUTH_API_KEY}"
|
2. Use Secrets#
1
2
3
4
5
6
7
8
| apiVersion: v1
kind: Secret
metadata:
name: k8s-mcp-secrets
type: Opaque
stringData:
mcp-api-key: "your-secret-key"
grafana-api-key: "your-grafana-key"
|
3. Network Policies#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: cloud-native-mcp-server
spec:
podSelector:
matchLabels:
app: cloud-native-mcp-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
|
Logging and Monitoring#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| config:
logging:
level: "info"
json: true
audit:
enabled: true
storage: "file"
format: "json"
file:
path: "/var/log/cloud-native-mcp-server/audit.log"
maxSizeMB: 100
maxBackups: 10
maxAgeDays: 30
compress: true
|
Add Prometheus monitoring:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| apiVersion: v1
kind: Service
metadata:
name: cloud-native-mcp-server
namespace: default
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
selector:
app: cloud-native-mcp-server
|
Monitoring and Observability#
Health Checks#
The server provides health check endpoints:
1
2
3
4
5
6
7
8
| # Basic health check
curl http://localhost:8080/health
# Detailed health information
curl http://localhost:8080/health/detailed
# Readiness check
curl http://localhost:8080/ready
|
Metrics#
Prometheus metrics are available at the /metrics endpoint:
1
| curl http://localhost:8080/metrics
|
Key metrics:
mcp_requests_total - Total number of requestsmcp_request_duration_seconds - Request durationmcp_cache_hits_total - Cache hitsmcp_cache_misses_total - Cache missesmcp_active_connections - Active connections
Logs#
Structured JSON logs:
1
2
3
4
5
6
7
| {
"level": "info",
"timestamp": "2024-01-01T00:00:00Z",
"message": "Starting Cloud Native MCP Server",
"version": "1.0.0",
"mode": "sse"
}
|
Audit Logs#
Audit logs track all operations:
1
2
3
4
5
6
7
8
| {
"timestamp": "2024-01-01T00:00:00Z",
"request_id": "abc123",
"tool": "kubernetes_list_resources_summary",
"params": {"kind": "Pod"},
"duration_ms": 123,
"status": "success"
}
|
Security Best Practices#
1. Least Privilege RBAC#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cloud-native-mcp-server
rules:
# Allow read-only access to most resources
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
# Allow describe for troubleshooting
- apiGroups: ["*"]
resources: ["*"]
verbs: ["describe"]
|
2. Secret Management#
Use Kubernetes secrets to store sensitive data:
1
2
3
| kubectl create secret generic k8s-mcp-secrets \
--from-literal=mcp-api-key='your-key' \
--from-literal=grafana-api-key='your-grafana-key'
|
Mount secrets as environment variables:
1
2
3
4
5
6
| env:
- name: MCP_AUTH_API_KEY
valueFrom:
secretKeyRef:
name: k8s-mcp-secrets
key: mcp-api-key
|
3. Network Security#
- Use TLS for external access
- Implement network policies
- Restrict ingress/egress traffic
- Use service mesh for mTLS
4. Pod Security#
1
2
3
4
5
6
7
8
| securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
|
5. Image Security#
- Use signed images
- Scan images for vulnerabilities
- Keep images updated
- Use specific version tags
Troubleshooting#
Common Issues#
1. Connection Refused#
Problem: Cannot connect to server
Solution:
1
2
3
4
5
6
7
8
9
10
11
12
| # Check pod status
kubectl get pods -l app=cloud-native-mcp-server
# Check logs
kubectl logs -l app=cloud-native-mcp-server
# Check service
kubectl get svc cloud-native-mcp-server
# Port forward test
kubectl port-forward svc/cloud-native-mcp-server 8080:8080
curl http://localhost:8080/health
|
2. Authentication Failed#
Problem: 401 Unauthorized
Solution:
1
2
3
4
5
6
7
8
| # Check authentication configuration
kubectl get configmap k8s-mcp-config -o yaml
# Verify secrets
kubectl get secret k8s-mcp-secrets -o yaml
# Test with correct header
curl -H "X-API-Key: your-key" http://localhost:8080/health
|
3. Kubernetes API Access Denied#
Problem: Cannot access Kubernetes API
Solution:
1
2
3
4
5
6
7
8
9
10
11
| # Check RBAC
kubectl get clusterrole cloud-native-mcp-server -o yaml
# Check service account
kubectl get sa cloud-native-mcp-server
# Verify cluster role binding
kubectl get clusterrolebinding cloud-native-mcp-server
# Test permissions
kubectl auth can-i list pods --as=system:serviceaccount:default:cloud-native-mcp-server
|
4. High Memory Usage#
Problem: Pod OOMKilled
Solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # Increase memory limits
resources:
limits:
memory: "1Gi"
# Smooth burst traffic
config:
ratelimit:
enabled: true
requests_per_second: 80
burst: 120
# Reduce audit overhead
audit:
sampling:
enabled: true
rate: 0.3
|
5. Slow Response#
Problem: Request timeout
Solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Increase service timeout
kubernetes:
timeoutSec: 60
qps: 120
burst: 240
# Tune HTTP timeouts
server:
readTimeoutSec: 60
writeTimeoutSec: 0
idleTimeoutSec: 90
# Use summary tools
# Replace kubernetes_list_resources with kubernetes_list_resources_summary
|
Debug Mode#
Enable debug logging:
1
2
| logging:
level: "debug"
|
Or via environment variable:
1
| export MCP_LOG_LEVEL=debug
|
Health Check Script#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| #!/bin/bash
echo "Checking Cloud Native MCP Server health..."
# Check endpoint
curl -f http://localhost:8080/health || exit 1
# Check metrics
curl -f http://localhost:8080/metrics > /dev/null || exit 1
# Check readiness
curl -f http://localhost:8080/ready || exit 1
echo "All checks passed!"
|