The universal Kubernetes ingress migration tool — scan, analyze, and migrate in minutes.
ing-switch scans your cluster for ingress resources across all 5 major controllers (NGINX, Traefik, Kong, HAProxy, Istio), maps 119+ annotations with impact ratings, and generates migration manifests for 3 targets — with a visual UI or pure CLI.
Ingress NGINX was archived on March 24, 2026. If you're still running it, migrate now. Running Kong, HAProxy, or Istio? ing-switch has you covered too.
ing-switch doctor # quick health check — migration readiness at a glance
ing-switch scan # detect controller + list all ingresses, IngressRoutes, VirtualServices
ing-switch analyze # map every annotation to the target controller
ing-switch diff # visual before/after diff per resource
ing-switch migrate # generate ready-to-apply manifests
ing-switch apply # apply manifests directly (--dry-run, --category)
ing-switch report # generate shareable HTML report
ing-switch ui # open the visual migration dashboard at :8080
| Step | What you get |
|---|---|
| Scan | Detects controller (NGINX, Traefik, Kong, HAProxy, Istio), finds all Ingresses + IngressRoutes + VirtualServices |
| Analyze | Per-ingress annotation compatibility table: ✅ supported / --ci flag for pipeline gating |
| Migrate | Complete output directory — Middlewares, HTTPRoutes, Gateway, policies, verify script, DNS guide, cleanup scripts |
| Apply | Apply manifests directly via kubectl — --dry-run for preview, --category for step-by-step |
| Report | Self-contained HTML report with readiness score — shareable with non-technical stakeholders |
| UI | 4-page dashboard: Detect → Analyze → Migrate → Validate |
| Source | What's scanned |
|---|---|
| Kubernetes Ingress (NGINX) | Standard kind: Ingress with nginx.ingress.kubernetes.io/* annotations |
| Traefik IngressRoute | kind: IngressRoute CRDs + referenced Middleware CRDs (rate limit, auth, CORS, IP filtering, rewrites) |
| Kong Ingress | Standard kind: Ingress with konghq.com/* annotations + referenced KongPlugin / KongClusterPlugin CRDs (rate-limiting, cors, ip-restriction, basic-auth, request-transformer, etc.) |
| HAProxy Ingress | Standard kind: Ingress with haproxy-ingress.github.io/* and haproxy.org/* annotations (SSL, CORS, auth, rate-limit, timeouts, affinity, rewrites, load-balancing) |
| Istio VirtualService | networking.istio.io VirtualService CRDs — HTTP routes, TLS, CORS policy, retries, timeouts, fault injection, traffic mirroring, weighted routing, header manipulation |
The scanner auto-detects all 5 source types in a single ing-switch scan — no flags needed. Controller detection works for NGINX, Traefik, Kong, HAProxy, and Istio.
| Target | What's generated |
|---|---|
| Traefik v3 | Traefik Middleware CRDs + updated Ingress resources (stays on kind: Ingress) |
| Gateway API (Envoy) | GatewayClass + Gateway + HTTPRoutes + BackendTrafficPolicy + SecurityPolicy |
| Gateway API (Traefik) | Standard HTTPRoutes + Gateway resources with traefik.io/gateway-controller. Advanced features use Traefik Middleware CRDs as extension policies. Ideal for Rancher / k3s. |
119 nginx.ingress.kubernetes.io/* annotations mapped for all targets:
| Category | Examples |
|---|---|
| SSL/TLS | ssl-redirect, force-ssl-redirect, ssl-passthrough, ssl-ciphers, auth-tls-* |
| CORS | All 7 cors-* fields — native Gateway API v1.5 CORS filter |
| Auth | auth-url, auth-response-headers, auth-signin, auth-cache-*, ForwardAuth |
| Rate limiting | limit-rps, limit-rpm, limit-connections, limit-burst-multiplier |
| Session affinity | All 9 session-cookie-* fields, affinity-mode |
| Canary | weight, header, header-value, header-pattern, cookie |
| Proxy/Timeouts | proxy-read/send/connect-timeout, proxy-body-size, proxy-ssl-* |
| Routing | rewrite-target, use-regex, app-root, permanent/temporal-redirect |
| IP access | whitelist-source-range, denylist-source-range |
| Protocol | WebSocket, gRPC, backend-protocol |
| Observability | enable-access-log, enable-opentelemetry |
| WAF | enable-modsecurity, modsecurity-snippet, OWASP CRS |
| Mirroring | mirror-target, mirror-request-body |
Every unsupported annotation includes an impact rating (NONE / LOW / MEDIUM / VARIES) so you know what's safe to ignore vs what needs a workaround.
# macOS arm64
curl -L https://github.com/saiyam1814/ing-switch/releases/latest/download/ing-switch-darwin-arm64 -o ing-switch
chmod +x ing-switch
sudo mv ing-switch /usr/local/bin/
# macOS amd64
curl -L https://github.com/saiyam1814/ing-switch/releases/latest/download/ing-switch-darwin-amd64 -o ing-switch
chmod +x ing-switch && sudo mv ing-switch /usr/local/bin/
# Linux amd64
curl -L https://github.com/saiyam1814/ing-switch/releases/latest/download/ing-switch-linux-amd64 -o ing-switch
chmod +x ing-switch && sudo mv ing-switch /usr/local/bin/git clone https://github.com/saiyam1814/ing-switch.git
cd ing-switch
make build # builds UI then Go binary
./ing-switch --helpRequirements: Go 1.22+, Node.js 20.19+ (for UI build only)
# Point at your cluster
export KUBECONFIG=~/.kube/config
# 1. Scan — see what you have
ing-switch scan
# 2. Analyze — understand compatibility
ing-switch analyze --target gateway-api
# 3. Migrate — generate all manifests
ing-switch migrate --target gateway-api --output-dir ./migration
# 4. Review then apply (dry-run first)
ing-switch apply --target gateway-api --dry-run
ing-switch apply --target gateway-api
# 5. Or apply step-by-step
ing-switch apply --target gateway-api --category gateway
ing-switch apply --target gateway-api --category httproute
# 6. Open the visual UI (optional)
ing-switch uiing-switch migrate --target traefik --output-dir ./migration
# Apply directly (dry-run first)
ing-switch apply --target traefik --dry-run
ing-switch apply --target traefik --category middleware
ing-switch apply --target traefik --category ingressing-switch migrate --target gateway-api-traefik --output-dir ./migration
# Standard Gateway API resources + Traefik Middleware extensions
kubectl apply -f ./migration/03-gateway/
kubectl apply -f ./migration/04-httproutes/
kubectl apply -f ./migration/05-policies/migration/
├── 00-migration-report.md # Full annotation analysis + compatibility summary
├── 01-install-gateway-api-crds/ # install.sh for Gateway API CRDs
├── 02-install-envoy-gateway/ # Helm install script + values.yaml
├── 03-gateway/
│ ├── gatewayclass.yaml # GatewayClass (Envoy Gateway)
│ └── gateway.yaml # Gateway with HTTP + HTTPS listeners
├── 04-httproutes/ # One HTTPRoute per ingress
│ ├── <ns>-<name>-redirect.yaml # HTTP→HTTPS redirect route (sectionName: http)
│ └── <ns>-<name>.yaml # Backend route (sectionName: https-N)
├── 05-policies/ # BackendTrafficPolicy, SecurityPolicy (Envoy ext)
├── 06-verify.sh # Test script per hostname
└── 07-cleanup/
└── remove-nginx.sh # Remove NGINX after cutover
migration/
├── 00-migration-report.md
├── 01-install-traefik/ # Helm install script + values.yaml
├── 02-middlewares/ # Traefik Middleware CRDs (one file per ingress)
├── 03-ingresses/ # Updated Ingress resources (traefik ingressClassName)
├── 04-verify.sh
├── 05-dns-migration.md
└── 06-cleanup/
├── 01-preserve-ingressclass.yaml
└── 02-remove-nginx.sh
Flags (global):
--kubeconfig string Path to kubeconfig (default: ~/.kube/config)
--context string kubeconfig context to use
--namespace string Limit to one namespace (default: all)
ing-switch doctor Quick health check + migration readiness score
ing-switch scan
--output table|json Output format (default: table)
ing-switch analyze
--target string traefik | gateway-api | gateway-api-traefik (required)
--output table|json
--ci Exit 1 on unsupported, exit 2 on partial (for CI/CD pipelines)
ing-switch diff
--target string traefik | gateway-api | gateway-api-traefik (required)
--name string Filter to a specific resource name
ing-switch migrate
--target string traefik | gateway-api | gateway-api-traefik (required)
--output-dir string Output directory (default: ./migration)
ing-switch apply
--target string traefik | gateway-api | gateway-api-traefik (required)
--category string middleware | ingress | gateway | httproute | policy (omit for all)
--dry-run Preview with kubectl --dry-run=server
ing-switch report
--target string traefik | gateway-api | gateway-api-traefik (required)
--output string Output HTML file (default: migration-report.html)
ing-switch ui
--port int Port for the web UI (default: 8080)
The examples/ directory contains 11 production-realistic NGINX Ingress configurations covering every major annotation category:
| File | Covers |
|---|---|
01-basic-routing.yaml |
Path routing, TLS termination |
02-ssl-tls.yaml |
SSL redirect, HSTS, force-ssl |
03-auth-external.yaml |
External auth (auth-url, auth-response-headers) |
04-session-affinity.yaml |
Sticky cookies (all 8 session-cookie-* fields) |
05-canary.yaml |
Canary by weight, header, cookie |
06-cors.yaml |
Full CORS (all 6 cors-* annotations) |
07-path-rewrite-regex.yaml |
Regex routing, rewrite-target capture groups |
08-rate-limit-ip.yaml |
Rate limiting, IP allowlist/denylist |
09-websocket.yaml |
WebSocket upgrade |
10-grpc.yaml |
gRPC passthrough |
11-full-featured.yaml |
All of the above combined |
# Migrate all examples
kubectl apply -f examples/
ing-switch migrate --target gateway-api --output-dir ./migration-examplesThe tool generates two separate HTTPRoutes per ingress (not two rules in one route, which causes redirect loops):
# <name>-redirect (attached to HTTP listener only via sectionName: http)
# → returns 301/302 for all HTTP requests
# <name> (attached to HTTPS listener via sectionName: https-N)
# → routes HTTPS requests to backendsPaths with regex characters ((, ), |, [, ]) are automatically detected and converted to PathPrefix → RegularExpression type, even when the use-regex annotation is absent.
proxy-read-timeout → backendRequest only. proxy-connect-timeout is intentionally omitted to avoid the Gateway API constraint backendRequest ≤ request being violated by typical nginx configs (read=300s, connect=5s).
ing-switch/
├── cmd/ # Cobra CLI commands (scan, analyze, migrate, apply, report, diff, doctor, ui)
├── pkg/
│ ├── scanner/ # cluster.go, ingress.go, ingressroute.go, kong.go, haproxy.go, istio.go
│ ├── analyzer/ # annotations.go, compatibility.go (119+ annotation mappings)
│ ├── migrator/
│ │ ├── traefik/ # middleware.go, mappings.go
│ │ └── gatewayapi/ # httproute.go, gateway.go, migrator.go
│ ├── generator/ # output.go, htmlreport.go, ZIP generation
│ └── server/ # HTTP server, REST API, embedded React UI
└── web/ # React 18 + TypeScript + Tailwind CSS + Vite
└── src/
├── pages/ # Detect, Analyze, Migrate, Validate
└── components/ # IngressTable, AnnotationMatrix, MigrationGaps, FileViewer
March 2026: Ingress NGINX was archived. ~50% of Kubernetes clusters depend on it. And Traefik IngressRoute users want to modernize to Gateway API.
Existing tools (ingress2gateway v1.0) handle 30+ annotations with basic conversion. ing-switch goes further: 5 source controllers (NGINX + Traefik + Kong + HAProxy + Istio), 119+ annotations, impact ratings for every unsupported one, 3 migration targets, a web UI with dry-run support, CI pipeline gating, and HTML reports for stakeholders.
Full migration lifecycle: scan → analyze → generate → apply → verify → cutover → cleanup.
- ing-switch: Migrate from Ingress NGINX to Traefik or Gateway API in Minutes, Not Days -- Introduction, architecture, and walkthrough
- The Ingress NGINX Migration Just Got Easier: 119 Annotations, 3 Targets, Impact Ratings -- Gateway API with Traefik, impact ratings, end-to-end vCluster demo
Issues and PRs welcome. The annotation mapping database lives in:
pkg/analyzer/compatibility.go— status + target resource per annotationpkg/server/guides.go— human-readable what/fix/example per annotation
MIT



