Executive Summary
CRITICAL UPDATE: Kong Inc. fundamentally changed its business model with Kong Gateway 3.10 (March 2025), discontinuing prebuilt Docker images for Kong OSS and eliminating “free mode” for Kong Gateway Enterprise. Organizations running Kong OSS now face significant operational challenges:
- ❌ No prebuilt Docker images for Kong OSS 3.10+ on Docker Hub
- ❌ Free mode eliminated - running without a license behaves like an expired enterprise license
- ⚠️ Security risks - stuck on 3.9.x or forced to build from source
- 💸 Forced monetization - pushed toward paid Kong Enterprise or Konnect
This strategic shift has left thousands of organizations scrambling for alternatives. Envoy Gateway is the recommended migration path—a truly open-source, Kubernetes Gateway API-compliant API gateway backed by the CNCF with no vendor lock-in.
This comprehensive guide provides step-by-step migration strategies, Kong plugin translation patterns, and production-proven best practices for zero-downtime migration.
If you need expert assistance with your Kong to Envoy migration, our Envoy Gateway enterprise support team (1 of only 2 official partners worldwide) can help ensure a smooth, secure transition.
Table of Contents
- What Changed: Kong’s Business Model Shift
- Why Choose Envoy Gateway
- Pre-Migration Assessment
- Migration Strategy Options
- Step-by-Step Migration Guide
- Plugin Translation Reference
- Testing & Validation
- Rollback Strategy
- Post-Migration Optimization
- Common Migration Challenges
- Production Migration Checklist
What Changed: Kong’s Business Model Shift
Kong Inc. made several strategic changes with Kong Gateway 3.10 (released March 27, 2025) that fundamentally altered the open-source landscape:
1. Discontinued Prebuilt OSS Docker Images
Starting with 3.10, Kong stopped publishing prebuilt Docker images for Kong OSS on Docker Hub. Users must now:
- Build Docker images from source (significant operational overhead)
- Accept increased build times, storage costs, and CI/CD complexity
- Manage their own image security scanning and patching
This change was not prominently announced and caught many organizations by surprise during routine upgrades.
2. Eliminated “Free Mode” for Kong Gateway Enterprise
Kong Gateway Enterprise previously offered a “free mode” that provided limited functionality without a license. Starting with 3.10:
- No free mode - running without a license now behaves identically to an expired enterprise license
- Severe functional limitations and degraded performance
- Forces users toward paid Kong Enterprise or Kong Konnect
3. Security & Compliance Risks
Organizations stuck on Kong OSS 3.9.x face:
- No security updates for newer vulnerabilities
- Compliance violations for regulated industries requiring current software
- Technical debt accumulation from delayed upgrades
- Risk of supply chain attacks via outdated dependencies
4. Community Response
The Kong community reacted strongly:
- Discussion on Kong Nation: “Is Opensource support for Kong ceased?”
- Tetrate launched community-supported Kong OSS Docker images as a stopgap
- Mass migration to alternatives: Apache APISIX, Traefik, Envoy Gateway
Why This Matters
Kong’s shift represents a classic “open-core squeeze” strategy seen across the industry (Elasticsearch, MongoDB, Redis, HashiCorp Terraform). For organizations requiring:
- Vendor independence and avoidance of commercial lock-in
- Predictable costs without surprise licensing changes
- Community-driven development and transparent roadmaps
- Cloud-native architecture with Kubernetes-native APIs
Envoy Gateway is the clear alternative, backed by the CNCF with no commercial entity controlling its direction.
Why Choose Envoy Gateway
Envoy Gateway represents the future of Kubernetes API gateways, built on proven cloud-native technologies with strong CNCF governance.
Comparison: Kong OSS vs. Envoy Gateway
| Feature | Kong OSS (3.9.x) | Envoy Gateway |
|---|---|---|
| Business Model | Open-core (abandoned by vendor) | Fully open-source (CNCF) |
| Docker Images | Discontinued (3.10+) | Official releases on every version |
| Gateway API Compliance | Partial via Kong Ingress Controller | Full native support |
| Configuration Model | Database or declarative YAML | Dynamic xDS API + Gateway API |
| Plugin Ecosystem | 50+ Kong plugins (many enterprise-only) | Envoy filters + Gateway API policies |
| Observability | Prometheus, Datadog, StatsD | Rich metrics, distributed tracing (Jaeger, Zipkin), access logs |
| Multi-tenancy | Kong workspaces (enterprise) | Gateway classes (native Kubernetes) |
| Service Mesh Integration | Kong Mesh (enterprise) | Native integration (Istio, Consul, Linkerd) |
| Protocol Support | HTTP/1.1, HTTP/2, gRPC, WebSocket | HTTP/1.1, HTTP/2, HTTP/3/QUIC, gRPC, WebSocket, TCP, UDP |
| Security Model | Plugin-based, mTLS support | Policy-driven (RBAC, mTLS, external auth) |
| Vendor Lock-in | Kong Inc. dependencies | Vendor-neutral CNCF project |
| Community Support | Declining (focus on enterprise) | Active, growing CNCF community |
| Enterprise Support | Kong Inc. only | Multiple providers (including Tasrie IT as official partner) |
Gateway API Benefits
The Kubernetes Gateway API is the evolution of the Ingress API, offering:
- Role-oriented design: Separate resources for infrastructure (Gateway) vs. application (HTTPRoute) teams
- Stronger typing: Explicit, validated configuration with CRDs
- Extended protocol support: TCP, UDP, gRPC, WebSockets, HTTP/3
- Portable across implementations: Vendor-neutral specification
- Expressive routing: Header-based, query parameter, method-based routing
- Traffic splitting: Native canary, blue-green, A/B testing
- Policy attachment: Security policies, rate limiting, CORS
Envoy Gateway is a reference implementation of Gateway API, making it the natural migration path for Kong users seeking a modern, vendor-neutral solution.
CNCF Governance
Unlike Kong OSS (controlled by Kong Inc.), Envoy Gateway benefits from:
- Neutral governance under the Cloud Native Computing Foundation
- Transparent roadmap driven by community needs
- Multi-vendor collaboration (Google, Microsoft, Red Hat, solo.io, Tetrate)
- Long-term sustainability with no single commercial entity controlling direction
Pre-Migration Assessment
Before starting migration, conduct a thorough assessment of your current Kong OSS deployment.
1. Inventory Your Kong Resources
# List all Kong services
kubectl get services -n kong
# List Kong ingress resources (if using Kong Ingress Controller)
kubectl get ingresses --all-namespaces
# List Kong plugins (CRDs if using KIC)
kubectl get kongplugins --all-namespaces
kubectl get kongclusterplugins
# List Kong consumers
kubectl get kongconsumers --all-namespaces
# Export Kong declarative configuration (if using DB-less mode)
kubectl exec -n kong deployment/kong -- kong config db_export /tmp/kong.yaml
kubectl cp kong/$(kubectl get pod -n kong -l app=kong -o jsonpath='{.items[0].metadata.name}'):/tmp/kong.yaml ./kong-backup.yaml
2. Document Current Architecture
Create a comprehensive inventory:
# kong-inventory.yaml
architecture:
deployment_mode: "DB-less" # or "Database-backed (PostgreSQL)"
kong_version: "3.9.1"
ingress_controller_version: "3.1.3"
namespaces:
- kong
- production
services_count: 45
routes_count: 120
plugins:
authentication:
- name: "key-auth"
routes: 30
- name: "jwt"
routes: 15
- name: "oauth2"
routes: 8
traffic_control:
- name: "rate-limiting"
routes: 80
- name: "request-size-limiting"
routes: 40
security:
- name: "cors"
routes: 50
- name: "ip-restriction"
routes: 12
transformations:
- name: "request-transformer"
routes: 25
- name: "response-transformer"
routes: 18
consumers_count: 250
upstreams_count: 35
integrations:
- Prometheus metrics
- Datadog APM
- External authentication service
- PostgreSQL database (if applicable)
3. Identify Migration Complexity
Assess which features require special attention:
Low Complexity (direct translation):
- Basic HTTP routing
- Path-based routing
- Host-based routing
- TLS termination
- CORS policies
- Rate limiting (basic)
Medium Complexity (requires adaptation):
- Advanced rate limiting (multiple dimensions)
- Request/response transformations
- Custom authentication flows
- Service-level retries and timeouts
- Circuit breaking
High Complexity (requires redesign):
- Kong custom plugins (Lua-based)
- Complex OAuth2 flows
- Kong consumer management
- Multi-database backends
- Kong workspaces (enterprise multi-tenancy)
4. Review Dependencies
# Check Kubernetes version (Gateway API requires 1.25+)
kubectl version --short
# Verify Gateway API CRD availability
kubectl get crd gateways.gateway.networking.k8s.io
# Review current resource utilization
kubectl top pods -n kong
kubectl describe nodes | grep -A 5 "Allocated resources"
5. Backup Current Configuration
Critical: Always maintain backups before migration.
# Backup all Kong resources
kubectl get all -n kong -o yaml > kong-backup-$(date +%F).yaml
# Backup Kong custom resources
kubectl get kongplugins,kongclusterplugins,kongconsumers,kongingresses --all-namespaces -o yaml > kong-crds-backup-$(date +%F).yaml
# Backup Kong declarative config (if DB-less)
# Already covered above
# Backup PostgreSQL database (if database-backed)
kubectl exec -n kong deployment/postgresql -- pg_dump -U kong kong > kong-db-backup-$(date +%F).sql
Migration Strategy Options
Choose the migration strategy that best fits your risk tolerance and operational constraints.
Strategy 1: Parallel Deployment (Recommended)
Deploy Envoy Gateway alongside Kong, gradually shift traffic.
Pros:
- ✅ Zero downtime - both systems run simultaneously
- ✅ Easy rollback - instant traffic shift back to Kong
- ✅ Gradual validation - test in production with real traffic
- ✅ Team learning - operations team learns Envoy before full cutover
Cons:
- ❌ Higher resource usage - both gateways consume cluster resources
- ❌ Longer migration - gradual shift takes time
- ❌ Complexity - managing two systems simultaneously
Best for: Production environments, risk-averse organizations, large-scale deployments.
Timeline: 2-4 weeks
Strategy 2: Blue-Green Deployment
Deploy Envoy in “green” environment, switch all traffic at once.
Pros:
- ✅ Fast rollback - instant switch back to Kong (blue)
- ✅ Complete validation - test entire green environment before cutover
- ✅ Clean cutover - single DNS/load balancer change
Cons:
- ❌ Resource intensive - requires full duplicate environment
- ❌ All-or-nothing - no gradual validation with production traffic
- ❌ Risk concentration - all traffic switches at once
Best for: Staging environments, smaller deployments, organizations with excess capacity.
Timeline: 1-2 weeks
Strategy 3: Canary Migration
Route small percentage of traffic to Envoy, gradually increase.
Pros:
- ✅ Risk mitigation - limited blast radius for issues
- ✅ Real-world testing - production traffic validation
- ✅ Data-driven decisions - metrics guide traffic increase
Cons:
- ❌ Complex routing - requires sophisticated traffic splitting
- ❌ Potential inconsistency - users may hit different gateways
- ❌ Longer migration - gradual ramp takes time
Best for: High-traffic environments, organizations with advanced observability, critical production systems.
Timeline: 3-6 weeks
Recommendation Matrix
| Scenario | Recommended Strategy |
|---|---|
| Production, high availability required | Parallel Deployment |
| Staging or non-critical environments | Blue-Green Deployment |
| High-traffic, mission-critical systems | Canary Migration |
| Small deployment, simple routing | Blue-Green Deployment |
| Complex Kong configuration | Parallel Deployment |
| Limited cluster resources | Blue-Green (in separate cluster) |
Step-by-Step Migration Guide
This section provides a comprehensive, production-ready migration guide using the Parallel Deployment strategy.
Phase 1: Preparation (Week 1)
1.1 Install Gateway API CRDs
# Install Gateway API CRDs (v1.2.1 - latest as of Dec 2025)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
# Verify installation
kubectl get crd gateways.gateway.networking.k8s.io
kubectl get crd httproutes.gateway.networking.k8s.io
kubectl get crd grpcroutes.gateway.networking.k8s.io
1.2 Install Envoy Gateway
# Install Envoy Gateway using Helm
helm repo add envoy-gateway https://gateway.envoyproxy.io
helm repo update
# Create namespace
kubectl create namespace envoy-gateway-system
# Install Envoy Gateway
helm install envoy-gateway envoy-gateway/gateway-helm \
--namespace envoy-gateway-system \
--set config.envoyGateway.gateway.controllerName=gateway.envoyproxy.io/gatewayclass-controller
# Verify installation
kubectl get pods -n envoy-gateway-system
kubectl get gatewayclass
Expected output:
NAME CONTROLLER ACCEPTED AGE
envoy-gateway gateway.envoyproxy.io/gatewayclass-controller True 30s
1.3 Create Gateway Resource
# envoy-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: envoy-gateway
namespace: envoy-gateway-system
spec:
gatewayClassName: envoy-gateway
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: envoy-gateway-tls
namespace: envoy-gateway-system
# Apply Gateway
kubectl apply -f envoy-gateway.yaml
# Verify Gateway status
kubectl get gateway -n envoy-gateway-system
kubectl describe gateway envoy-gateway -n envoy-gateway-system
1.4 Configure TLS Certificates
# If using cert-manager (recommended for automated certificate management)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
# Create Certificate resource
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: envoy-gateway-tls
namespace: envoy-gateway-system
spec:
secretName: envoy-gateway-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- api.yourdomain.com
- "*.api.yourdomain.com"
EOF
Phase 2: Route Translation (Week 1-2)
2.1 Translate Simple HTTP Route
Kong Configuration (via Kong Ingress Controller):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-api
namespace: production
annotations:
konghq.com/strip-path: "true"
spec:
ingressClassName: kong
rules:
- host: api.example.com
http:
paths:
- path: /v1/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
Envoy Gateway Equivalent (Gateway API HTTPRoute):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-api-users
namespace: production
spec:
parentRefs:
- name: envoy-gateway
namespace: envoy-gateway-system
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /v1/users
backendRefs:
- name: user-service
port: 8080
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
2.2 Translate Route with Rate Limiting
Kong Configuration:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limit-users
namespace: production
config:
minute: 100
hour: 5000
policy: local
plugin: rate-limiting
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-api
namespace: production
annotations:
konghq.com/plugins: rate-limit-users
spec:
# ... ingress spec
Envoy Gateway Equivalent (using RateLimitPolicy):
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: rate-limit-users
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
rateLimit:
type: Global
global:
rules:
- clientSelectors:
- headers:
- name: x-user-id
type: Distinct
limit:
requests: 100
unit: Minute
- limit:
requests: 5000
unit: Hour
2.3 Translate CORS Policy
Kong Configuration:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: cors-policy
namespace: production
config:
origins:
- https://app.example.com
- https://dashboard.example.com
methods:
- GET
- POST
- PUT
- DELETE
headers:
- Authorization
- Content-Type
exposed_headers:
- X-Request-ID
credentials: true
max_age: 3600
plugin: cors
Envoy Gateway Equivalent:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: cors-policy
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
cors:
allowOrigins:
- type: Exact
value: "https://app.example.com"
- type: Exact
value: "https://dashboard.example.com"
allowMethods:
- GET
- POST
- PUT
- DELETE
allowHeaders:
- Authorization
- Content-Type
exposeHeaders:
- X-Request-ID
allowCredentials: true
maxAge: 3600s
Phase 3: Traffic Migration (Week 2-3)
3.1 Configure DNS for Gradual Migration
Option A: Weighted DNS (AWS Route 53 example)
# route53-weighted-routing.tf (using Terraform for infrastructure as code)
resource "aws_route53_record" "api_weighted_kong" {
zone_id = aws_route53_zone.main.zone_id
name = "api.example.com"
type = "A"
set_identifier = "kong-gateway"
weighted_routing_policy {
weight = 90 # Start with 90% to Kong
}
alias {
name = data.kubernetes_service.kong_ingress.status.0.load_balancer.0.ingress.0.hostname
zone_id = var.aws_lb_zone_id
evaluate_target_health = true
}
}
resource "aws_route53_record" "api_weighted_envoy" {
zone_id = aws_route53_zone.main.zone_id
name = "api.example.com"
type = "A"
set_identifier = "envoy-gateway"
weighted_routing_policy {
weight = 10 # Start with 10% to Envoy
}
alias {
name = data.kubernetes_service.envoy_gateway.status.0.load_balancer.0.ingress.0.hostname
zone_id = var.aws_lb_zone_id
evaluate_target_health = true
}
}
For organizations needing Terraform consulting to automate this infrastructure migration, our team specializes in declarative infrastructure for Gateway API resources.
Option B: Header-Based Routing (testing with specific users)
# Use Kong to route specific header traffic to Envoy
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: envoy-migration-routing
namespace: production
config:
config:
- condition: "request.headers['X-Gateway-Test'] == 'envoy'"
action:
upstream_url: "http://envoy-gateway.envoy-gateway-system.svc.cluster.local"
plugin: request-transformer-advanced
3.2 Monitor Both Gateways
# prometheus-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: envoy-gateway-metrics
namespace: envoy-gateway-system
spec:
selector:
matchLabels:
app: envoy-gateway
endpoints:
- port: metrics
interval: 30s
path: /stats/prometheus
Key metrics to monitor during migration:
- Request rate: Compare Kong vs. Envoy traffic volume
- Latency (p50, p95, p99): Ensure Envoy matches or improves Kong performance
- Error rate (4xx, 5xx): Watch for configuration issues
- Resource usage: CPU, memory for both gateways
Prometheus queries for comparison:
# Request rate comparison
sum(rate(kong_http_requests_total[5m])) by (service)
sum(rate(envoy_cluster_upstream_rq_total[5m])) by (cluster_name)
# Latency comparison (p95)
histogram_quantile(0.95, sum(rate(kong_latency_bucket[5m])) by (le))
histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket[5m])) by (le))
# Error rate
sum(rate(kong_http_requests_total{code=~"5.."}[5m])) / sum(rate(kong_http_requests_total[5m]))
sum(rate(envoy_cluster_upstream_rq_xx{envoy_response_code_class="5"}[5m])) / sum(rate(envoy_cluster_upstream_rq_total[5m]))
For organizations using Prometheus support for monitoring and alerting, our team can help set up comprehensive gateway migration observability.
3.3 Gradual Traffic Shift Schedule
Week 1: 10% Envoy
# Update Route 53 weights
terraform apply -var="kong_weight=90" -var="envoy_weight=10"
- Monitor for 48 hours
- Validate error rates < baseline
- Check latency p95 < Kong baseline + 10%
Week 2: 25% Envoy
terraform apply -var="kong_weight=75" -var="envoy_weight=25"
- Monitor for 48 hours
- Run load tests at 25% production traffic
- Verify resource scaling
Week 2: 50% Envoy
terraform apply -var="kong_weight=50" -var="envoy_weight=50"
- Monitor for 72 hours
- Business hours + weekend traffic validation
- Perform chaos testing (Kubernetes pod failures)
Week 3: 75% Envoy
terraform apply -var="kong_weight=25" -var="envoy_weight=75"
- Monitor for 48 hours
- Final pre-cutover validation
Week 3: 100% Envoy
terraform apply -var="kong_weight=0" -var="envoy_weight=100"
- Monitor for 1 week before decommissioning Kong
- Keep Kong running in standby for emergency rollback
Phase 4: Monitoring & Validation (Week 3-4)
4.1 Functional Testing
# Test basic HTTP routing
curl -H "Host: api.example.com" http://envoy-gateway-lb.example.com/v1/users
# Test HTTPS with TLS
curl https://api.example.com/v1/users
# Test rate limiting
for i in {1..150}; do
curl -H "X-User-ID: test-user" https://api.example.com/v1/users
done
# Expect HTTP 429 after 100 requests
# Test CORS preflight
curl -X OPTIONS -H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
https://api.example.com/v1/users
4.2 Load Testing
# k6-load-test.js (using k6 for load testing)
import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp up to 100 users
{ duration: '5m', target: 100 }, // Stay at 100 users
{ duration: '2m', target: 200 }, // Ramp up to 200 users
{ duration: '5m', target: 200 }, // Stay at 200 users
{ duration: '2m', target: 0 }, // Ramp down to 0 users
],
thresholds: {
'http_req_duration': ['p(95)<500'], // 95% of requests under 500ms
'http_req_failed': ['rate<0.01'], // Error rate < 1%
},
};
export default function () {
let response = http.get('https://api.example.com/v1/users');
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
# Run load test
k6 run --vus 100 --duration 10m k6-load-test.js
4.3 Distributed Tracing
Enable Jaeger tracing for end-to-end request visibility:
# envoy-gateway-tracing.yaml
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ProxyConfig
metadata:
name: tracing-config
namespace: envoy-gateway-system
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: envoy-gateway
telemetry:
tracing:
provider:
type: OpenTelemetry
openTelemetry:
host: jaeger-collector.observability.svc.cluster.local
port: 4317
customTags:
environment:
literal:
value: production
gateway:
literal:
value: envoy-gateway
Plugin Translation Reference
This section provides detailed translation patterns for common Kong plugins to Envoy Gateway equivalents.
Authentication & Authorization
Kong: Key Authentication
Kong Plugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: key-auth
config:
key_names:
- apikey
- x-api-key
hide_credentials: true
plugin: key-auth
Envoy Gateway Equivalent:
# Use external authentication with a custom auth service
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: api-key-auth
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
extAuth:
grpc:
backendRef:
name: api-key-auth-service
port: 9001
Auth Service (example implementation):
# Deploy a custom auth service that validates API keys
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-key-auth-service
namespace: production
spec:
replicas: 2
selector:
matchLabels:
app: api-key-auth
template:
metadata:
labels:
app: api-key-auth
spec:
containers:
- name: auth-service
image: your-registry/api-key-auth:v1.0.0
ports:
- containerPort: 9001
env:
- name: REDIS_URL
value: redis://redis.production.svc.cluster.local:6379
Kong: JWT Authentication
Kong Plugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: jwt-auth
config:
uri_param_names:
- jwt
cookie_names:
- jwt_token
claims_to_verify:
- exp
- nbf
plugin: jwt
Envoy Gateway Equivalent:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-auth
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
jwt:
providers:
- name: auth0-provider
issuer: https://your-tenant.auth0.com/
audiences:
- https://api.example.com
remoteJWKS:
uri: https://your-tenant.auth0.com/.well-known/jwks.json
claimToHeaders:
- claim: sub
header: x-user-id
- claim: email
header: x-user-email
Traffic Control
Kong: Rate Limiting (Advanced)
Kong Plugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: advanced-rate-limit
config:
limit:
- 100
- 5000
window_size:
- 60
- 3600
identifier: consumer
sync_rate: 10
plugin: rate-limiting-advanced
Envoy Gateway Equivalent:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: advanced-rate-limit
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
rateLimit:
type: Global
global:
rules:
# 100 requests per minute per user
- clientSelectors:
- headers:
- name: x-user-id
type: Distinct
limit:
requests: 100
unit: Minute
# 5000 requests per hour per user
- clientSelectors:
- headers:
- name: x-user-id
type: Distinct
limit:
requests: 5000
unit: Hour
Kong: Request Size Limiting
Kong Plugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-size-limit
config:
allowed_payload_size: 10
size_unit: megabytes
require_content_length: true
plugin: request-size-limiting
Envoy Gateway Equivalent:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: request-size-limit
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
clientIPDetection:
xForwardedFor:
numTrustedHops: 1
# Note: Request size limiting in Envoy Gateway is configured via Envoy filters
# Requires custom EnvoyPatchPolicy for max_request_bytes
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: request-size-limit-patch
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
type: JSONPatch
jsonPatches:
- type: "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
name: "envoy.filters.network.http_connection_manager"
operation:
op: add
path: "/route_config/virtual_hosts/0/routes/0/route/max_stream_duration"
value:
max_stream_duration: 0s
grpc_timeout_header_max: 0s
- type: "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
name: "envoy.filters.network.http_connection_manager"
operation:
op: add
path: "/common_http_protocol_options"
value:
max_request_headers_kb: 60
Simpler approach: Use a Lua filter or external processing for request size validation.
Transformations
Kong: Request Transformer
Kong Plugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-transformer
config:
add:
headers:
- "X-Gateway: Kong"
- "X-Request-ID: $(uuid)"
querystring:
- "client_id: mobile-app"
remove:
headers:
- "X-Internal-Secret"
replace:
headers:
- "User-Agent: Kong-Gateway"
plugin: request-transformer
Envoy Gateway Equivalent:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-api-users
namespace: production
spec:
parentRefs:
- name: envoy-gateway
namespace: envoy-gateway-system
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /v1/users
filters:
# Add headers
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Gateway
value: Envoy-Gateway
- name: X-Request-ID
value: "%REQ_ID%" # Envoy variable for request ID
remove:
- X-Internal-Secret
set:
- name: User-Agent
value: Envoy-Gateway
backendRefs:
- name: user-service
port: 8080
Note: For query string manipulation, Envoy Gateway requires custom Lua filters or external processing.
Kong: Response Transformer
Kong Plugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: response-transformer
config:
add:
headers:
- "X-Response-Time: $(latency)"
- "X-Served-By: Kong"
remove:
headers:
- "X-Internal-Version"
plugin: response-transformer
Envoy Gateway Equivalent:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-api-users
namespace: production
spec:
parentRefs:
- name: envoy-gateway
namespace: envoy-gateway-system
rules:
- matches:
- path:
type: PathPrefix
value: /v1/users
filters:
- type: ResponseHeaderModifier
responseHeaderModifier:
add:
- name: X-Served-By
value: Envoy-Gateway
remove:
- X-Internal-Version
backendRefs:
- name: user-service
port: 8080
Note: Envoy Gateway doesn’t support dynamic response headers like $(latency) directly. Use observability backends (Prometheus, Jaeger) for latency tracking.
Reliability
Kong: Circuit Breaker (Upstream Healthcheck)
Kong Configuration:
apiVersion: configuration.konghq.com/v1
kind: KongUpstreamPolicy
metadata:
name: user-service-upstream
config:
healthchecks:
active:
healthy:
interval: 10
successes: 2
unhealthy:
interval: 5
http_failures: 3
tcp_failures: 3
Envoy Gateway Equivalent:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: circuit-breaker-policy
namespace: production
spec:
targetRef:
group: ""
kind: Service
name: user-service
circuitBreaker:
maxConnections: 1024
maxPendingRequests: 1024
maxRequests: 1024
maxRetries: 3
healthCheck:
active:
type: HTTP
http:
path: /health
expectedStatuses:
- 200
- 204
timeout: 1s
interval: 10s
unhealthyThreshold: 3
healthyThreshold: 2
Kong: Retries
Kong Configuration:
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: retry-config
route:
retries: 5
Envoy Gateway Equivalent:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: retry-policy
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
retry:
numRetries: 5
perRetry:
timeout: 2s
backOff:
baseInterval: 100ms
maxInterval: 10s
retryOn:
httpStatusCodes:
- 502
- 503
- 504
triggers:
- connect-failure
- refused-stream
Testing & Validation
Functional Testing
Create a comprehensive test suite covering all migrated routes:
#!/bin/bash
# test-envoy-migration.sh
set -e
GATEWAY_URL="https://api.example.com"
FAILED_TESTS=0
# Test 1: Basic routing
echo "Test 1: Basic HTTP GET routing..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" ${GATEWAY_URL}/v1/users)
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ PASSED"
else
echo "❌ FAILED (got $RESPONSE)"
FAILED_TESTS=$((FAILED_TESTS+1))
fi
# Test 2: CORS preflight
echo "Test 2: CORS preflight request..."
RESPONSE=$(curl -s -X OPTIONS \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-o /dev/null -w "%{http_code}" \
${GATEWAY_URL}/v1/users)
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ PASSED"
else
echo "❌ FAILED (got $RESPONSE)"
FAILED_TESTS=$((FAILED_TESTS+1))
fi
# Test 3: Rate limiting
echo "Test 3: Rate limiting enforcement..."
for i in {1..110}; do
RESPONSE=$(curl -s -H "X-User-ID: test-user" \
-o /dev/null -w "%{http_code}" \
${GATEWAY_URL}/v1/users)
done
if [ "$RESPONSE" -eq 429 ]; then
echo "✅ PASSED (rate limit triggered)"
else
echo "❌ FAILED (expected 429, got $RESPONSE)"
FAILED_TESTS=$((FAILED_TESTS+1))
fi
# Test 4: Authentication
echo "Test 4: JWT authentication..."
RESPONSE=$(curl -s -H "Authorization: Bearer ${TEST_JWT_TOKEN}" \
-o /dev/null -w "%{http_code}" \
${GATEWAY_URL}/v1/users/me)
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ PASSED"
else
echo "❌ FAILED (got $RESPONSE)"
FAILED_TESTS=$((FAILED_TESTS+1))
fi
# Test 5: TLS termination
echo "Test 5: HTTPS/TLS termination..."
RESPONSE=$(curl -s -v https://api.example.com/v1/users 2>&1 | grep "SSL connection")
if [ -n "$RESPONSE" ]; then
echo "✅ PASSED"
else
echo "❌ FAILED"
FAILED_TESTS=$((FAILED_TESTS+1))
fi
echo ""
echo "========================================="
if [ $FAILED_TESTS -eq 0 ]; then
echo "✅ All tests passed!"
exit 0
else
echo "❌ $FAILED_TESTS test(s) failed"
exit 1
fi
Performance Testing
# k6-performance-comparison.js
import http from 'k6/http';
import { check, group } from 'k6';
import { Rate, Trend } from 'k6/metrics';
let errorRate = new Rate('errors');
let latencyTrend = new Trend('latency');
export let options = {
scenarios: {
baseline_load: {
executor: 'constant-vus',
vus: 50,
duration: '5m',
},
spike_test: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '1m', target: 100 },
{ duration: '3m', target: 500 },
{ duration: '1m', target: 0 },
],
startTime: '6m',
},
},
thresholds: {
'http_req_duration': ['p(95)<500', 'p(99)<1000'],
'errors': ['rate<0.01'],
},
};
export default function () {
group('API Endpoints', function () {
let res = http.get('https://api.example.com/v1/users');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
}) || errorRate.add(1);
latencyTrend.add(res.timings.duration);
});
}
Chaos Engineering
Use Chaos Mesh to validate resilience:
# chaos-pod-failure.yaml
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: envoy-gateway-pod-kill
namespace: chaos-testing
spec:
action: pod-kill
mode: one
selector:
namespaces:
- envoy-gateway-system
labelSelectors:
app: envoy-gateway
scheduler:
cron: "@every 5m"
Run chaos tests and verify:
- Gateway recovers within SLA (e.g., < 30s)
- No request failures during pod restart
- Metrics return to baseline after recovery
Rollback Strategy
Always maintain an emergency rollback plan.
Immediate Rollback (DNS-based)
# Shift 100% traffic back to Kong
terraform apply -var="kong_weight=100" -var="envoy_weight=0"
Rollback time: 5-10 minutes (DNS TTL dependent)
Application-Level Rollback
If using header-based routing:
# Remove X-Gateway-Test header routing
kubectl delete kongplugin envoy-migration-routing -n production
Rollback time: < 1 minute
Gateway Resource Rollback
# Disable Envoy Gateway routes
kubectl delete httproute --all -n production
# Traffic automatically falls back to Kong Ingress
Rollback time: < 2 minutes
Rollback Decision Criteria
Trigger rollback if:
- Error rate > 1% sustained for > 5 minutes
- Latency p95 > 2x baseline sustained for > 10 minutes
- Availability < 99.9% in any 15-minute window
- Critical business functionality fails (payments, authentication, etc.)
Post-Migration Optimization
After successful migration, optimize Envoy Gateway for production performance.
1. Resource Tuning
# Adjust Envoy Proxy resource limits based on observed usage
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: production-proxy-config
namespace: envoy-gateway-system
spec:
provider:
type: Kubernetes
kubernetes:
envoyDeployment:
replicas: 3
pod:
resources:
limits:
cpu: "2000m"
memory: "2Gi"
requests:
cpu: "1000m"
memory: "1Gi"
autoscaling:
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
2. Connection Pooling
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: connection-pool-optimization
namespace: production
spec:
targetRef:
group: ""
kind: Service
name: user-service
loadBalancer:
type: RoundRobin
proxyProtocol:
version: V1
tcpKeepalive:
idleTime: 7200s
interval: 75s
probes: 9
3. Caching (if applicable)
For read-heavy APIs, consider implementing response caching:
# Note: Envoy Gateway doesn't have built-in HTTP caching yet
# Use a caching layer like Varnish or CDN (CloudFront, Cloudflare)
# Or implement application-level caching
4. Decommission Kong
After 1-2 weeks of stable Envoy operation:
# Scale down Kong deployment
kubectl scale deployment kong -n kong --replicas=0
# Wait 1 week for final validation
# Remove Kong resources
kubectl delete namespace kong
# Remove Kong CRDs
kubectl delete crd kongplugins.configuration.konghq.com
kubectl delete crd kongclusterplugins.configuration.konghq.com
kubectl delete crd kongconsumers.configuration.konghq.com
kubectl delete crd kongingresses.configuration.konghq.com
# Remove DNS records
terraform destroy -target=aws_route53_record.api_weighted_kong
Common Migration Challenges
Challenge 1: Kong Custom Plugins (Lua)
Problem: Custom Lua plugins have no direct Envoy equivalent.
Solution:
- Rewrite as Envoy Wasm filter (Rust, C++, Go)
- Use External Processing API (gRPC service for custom logic)
- Move logic to application layer (sidecar, service code)
Example: External Processing for custom authentication
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyExtensionPolicy
metadata:
name: custom-auth-processor
namespace: production
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: example-api-users
extProc:
- backendRefs:
- name: custom-auth-service
port: 9002
processingMode:
requestHeaderMode: SEND
responseHeaderMode: SKIP
Challenge 2: Kong Consumer Management
Problem: Kong consumers (API key/JWT credential storage) don’t map to Envoy.
Solution:
- Migrate to external IdP (Keycloak, Auth0, Okta)
- Use Kubernetes Secrets for API keys with external auth service
- Implement custom credential service (Redis-backed auth)
# Example: Migrate Kong consumers to Keycloak
# 1. Export Kong consumers
# 2. Import to Keycloak as users/clients
# 3. Configure Envoy Gateway JWT auth with Keycloak JWKS
Challenge 3: Database-Backed Kong Configuration
Problem: Kong using PostgreSQL for config; Envoy Gateway is declarative only.
Solution:
- Export Kong config to declarative YAML (
deck dump) - Translate to Gateway API resources (HTTPRoute, SecurityPolicy, etc.)
- Store in Git for GitOps with ArgoCD/Flux
# Export Kong config
deck dump --output-file kong-config.yaml
# Use translation scripts or manual conversion
# Store in Git repository
git add manifests/envoy-gateway/
git commit -m "Migrate Kong routes to Envoy Gateway"
git push
Challenge 4: Multi-Workspace Kong (Enterprise)
Problem: Kong workspaces provide multi-tenancy; Envoy Gateway uses Kubernetes namespaces.
Solution:
- Map Kong workspaces → Kubernetes namespaces
- Use Gateway API
ReferenceGrantfor cross-namespace routing - Implement RBAC for namespace isolation
# ReferenceGrant for cross-namespace backend access
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-production-to-shared-services
namespace: shared-services
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: production
to:
- group: ""
kind: Service
Challenge 5: Kong Admin API Usage
Problem: Automation scripts using Kong Admin API need replacement.
Solution:
- Use
kubectlfor Gateway API resources (declarative YAML) - Implement GitOps (ArgoCD, Flux) for automated deployments
- Use Kubernetes API directly for programmatic access
For organizations needing CI/CD consulting to automate Gateway API deployments, our team specializes in GitOps workflows for Kubernetes infrastructure.
Production Migration Checklist
Use this checklist to ensure a complete, safe migration:
Pre-Migration
- Inventory complete: All Kong routes, plugins, consumers documented
- Gateway API CRDs installed (v1.2.1+)
- Envoy Gateway installed and verified
- TLS certificates migrated to Kubernetes Secrets
- Monitoring configured: Prometheus, Grafana dashboards
- Distributed tracing enabled: Jaeger/Zipkin
- Backup created: Kong config, database (if applicable)
- Test environment validated: Successful migration in staging
- Rollback plan documented and tested
- Stakeholders notified: Teams aware of migration schedule
During Migration
- HTTPRoutes created for all Kong routes
- SecurityPolicies applied: CORS, authentication, authorization
- BackendTrafficPolicies configured: Rate limiting, retries, circuit breakers
- DNS configured for gradual traffic shift
- Monitoring dashboards active: Kong vs. Envoy comparison
- Alert rules updated: Envoy-specific alerts configured
- Load testing completed: Performance validated at each traffic percentage
- Functional testing passed: All critical user journeys validated
- Chaos testing performed: Pod failures, network partitions tested
- Runbook updated: Troubleshooting steps for Envoy Gateway
Post-Migration
- 100% traffic on Envoy: Kong fully deprecated
- Performance validated: Latency, throughput meet SLAs
- Error rates normal: < baseline for 1 week
- Resource usage optimized: HPA configured, limits tuned
- Documentation updated: Architecture diagrams, runbooks
- Team training completed: Operations team comfortable with Envoy
- Kong decommissioned: Resources deleted (after 2-week stabilization)
- Cost analysis: Resource usage, licensing costs compared
- Lessons learned: Post-mortem completed, improvements documented
- Celebration: Team recognized for successful migration! 🎉
Migration Timeline Example
Small Deployment (< 50 routes)
- Week 1: Assessment, planning, Envoy Gateway installation
- Week 2: Route translation, testing in staging
- Week 3: Production migration (gradual traffic shift)
- Week 4: Monitoring, optimization, Kong decommissioning
Total: 4 weeks
Medium Deployment (50-200 routes)
- Weeks 1-2: Assessment, inventory, planning
- Weeks 3-4: Envoy Gateway installation, route translation
- Weeks 5-7: Staging validation, production migration
- Week 8: Monitoring, optimization, Kong decommissioning
Total: 8 weeks
Large Deployment (200+ routes, complex plugins)
- Weeks 1-3: Comprehensive assessment, custom plugin analysis
- Weeks 4-6: Envoy Gateway setup, route translation, custom filter development
- Weeks 7-10: Staging validation, gradual production migration (10% increments)
- Weeks 11-12: Monitoring, optimization, Kong decommissioning
Total: 12 weeks
Need Expert Help with Your Kong to Envoy Migration?
Migrating from Kong OSS to Envoy Gateway is a critical project that requires deep expertise in Kubernetes networking, Gateway API, and production migration strategies. Mistakes can lead to downtime, security vulnerabilities, or performance degradation.
Tasrie IT is 1 of only 2 official Envoy Gateway enterprise support partners worldwide, recognized by the Envoy Gateway project. Our team has successfully migrated hundreds of production API gateways with zero downtime.
Our Migration Services Include:
✅ Pre-migration assessment - Comprehensive inventory, complexity analysis, timeline estimation ✅ Custom plugin translation - Lua → Wasm filters, external processing services ✅ Zero-downtime migration execution - Gradual traffic shift with 24/7 monitoring ✅ Performance optimization - Load testing, resource tuning, autoscaling configuration ✅ 24/7 post-migration support - Incident response, troubleshooting, optimization ✅ Team training - Hands-on workshops for operations and development teams
Whether you’re managing a simple Kong deployment or a complex multi-cluster, multi-tenant architecture, we can help ensure a smooth, successful migration to Envoy Gateway.
Additional Services
- Kubernetes Consulting - Architecture design, cluster optimization, security hardening
- Cloud Migration Services - End-to-end cloud migration strategy and execution
- DevOps Consulting - CI/CD pipelines, GitOps, infrastructure automation
- Terraform Consulting - Infrastructure as Code for Gateway API resources
- Prometheus Support - Observability, monitoring, and alerting for API gateways
- AWS Managed Services - EKS optimization, load balancer integration
- Cloud Native Consulting - CNCF ecosystem expertise
Schedule a free 30-minute consultation to discuss your Kong to Envoy migration strategy, or contact our team for a detailed migration assessment.
Don’t let Kong’s business model change disrupt your operations. Migrate to Envoy Gateway with confidence.