Kubernetes Ingress Controller Comparison for Production

Head-to-head comparison of NGINX, Traefik, HAProxy, Istio, and Envoy Gateway ingress controllers with benchmarks on throughput, latency, and resource usage

#kubernetes#ingress#networking#comparison
Cover image for the article: Kubernetes Ingress Controller Comparison for Production

Introduction

Choosing a Kubernetes ingress controller is one of the most impactful infrastructure decisions for any cluster. The ingress controller handles every external request, making it the performance bottleneck, the security boundary, and the observability chokepoint all at once. With over a dozen production-grade options available, the decision requires data-driven comparison.

This article presents benchmark results from testing five popular ingress controllers under identical load conditions, comparing throughput, latency, resource consumption, and operational complexity.

Controller Overview

ControllerProxy EngineLicenseGateway APIConfig ReloadMarket Share
NGINX IngressNGINXApache 2.0PartialConfig reload (brief drop)~45%
TraefikGo (native)MITFullDynamic (zero downtime)~20%
HAProxy IngressHAProxyApache 2.0PartialReload or dynamic~10%
Istio (Envoy)EnvoyApache 2.0FullxDS (zero downtime)~15%
Envoy GatewayEnvoyApache 2.0Full (native)xDS (zero downtime)~5%

Chart

Benchmark Setup

Test Environment

ComponentSpecification
ClusterEKS 1.29, 6x m6i.2xlarge worker nodes
Load generator3x c6i.4xlarge running k6
Backend10 replicas of echo server (Go, ~0.1ms response)
Test duration5 minutes per test after 30s warmup
TLSTLS 1.3, RSA 2048 certificate
ProtocolHTTPS with keep-alive

k6 Load Script

import http from 'k6/http';
import { check } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 100 },   // warmup
    { duration: '5m', target: 1000 },   // sustained load
  ],
  thresholds: {
    http_req_duration: ['p(99)<100'],
    http_req_failed: ['rate<0.01'],
  },
};

export default function () {
  const res = http.get('https://test-ingress.example.com/echo');
  check(res, {
    'status is 200': (r) => r.status === 200,
  });
}

Throughput Benchmarks (RPS)

Requests Per Second at Various Concurrency Levels

ConcurrencyNGINXTraefikHAProxyIstio (Envoy)Envoy Gateway
10045,00038,00052,00042,00044,000
50082,00065,00095,00078,00080,000
1,000105,00078,000120,00098,000102,000
2,000115,00082,000130,000108,000112,000
5,000118,00085,000135,000112,000115,000

Winner: HAProxy consistently delivers 15-25% higher throughput than alternatives due to its highly optimized event-driven architecture.

Latency Benchmarks

Latency at 1,000 Concurrent Connections (HTTPS)

PercentileNGINXTraefikHAProxyIstioEnvoy Gateway
p502.1ms3.5ms1.8ms2.4ms2.2ms
p905.2ms8.1ms4.5ms5.8ms5.4ms
p958.4ms12.3ms7.1ms9.2ms8.8ms
p9915.2ms22.5ms12.8ms16.5ms15.8ms
p99.935ms55ms28ms38ms36ms

Chart

Analysis: HAProxy leads on latency across all percentiles. Traefik has consistently higher latency due to Go's garbage collection pauses affecting tail latency. NGINX and Envoy-based solutions cluster together.

Resource Consumption

Idle Resource Usage (No Traffic)

ControllerCPU (idle)Memory (idle)PodsNotes
NGINX10m90 MB1Single pod default
Traefik15m120 MB1Includes dashboard
HAProxy8m80 MB1Minimal idle footprint
Istio150m600 MB4istiod + gateways
Envoy Gateway50m200 MB3Controller + Envoy

Under Load (50,000 RPS)

ControllerCPU (loaded)Memory (loaded)Scaling Model
NGINX2.5 cores350 MBHorizontal (replicas)
Traefik3.2 cores450 MBHorizontal (replicas)
HAProxy2.0 cores280 MBHorizontal + vertical
Istio4.5 cores1.2 GBComplex (data + control plane)
Envoy Gateway3.0 cores500 MBHorizontal (Envoy fleet)

Feature Comparison

FeatureNGINXTraefikHAProxyIstioEnvoy Gateway
Rate limitingAnnotationMiddlewareACLEnvoyFilterPolicy
mTLSManualYesManualAutomaticPolicy
Canary/traffic splitAnnotationWeightedACLVirtualServiceHTTPRoute
Circuit breakingNoYesBackend checkYesYes
WASM extensionsNoPlugin (Go)NoYesYes
OpenTelemetryPartialYesPartialYesYes
HTTP/3 (QUIC)ExperimentalYesNoYesYes
Web Application FirewallModSecurityPluginNoExternalExternal
Auto TLS (Let's Encrypt)cert-managerBuilt-incert-managercert-managercert-manager
Config complexityLowLowMediumHighMedium

Configuration Comparison

NGINX Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  tls:
    - hosts: ["api.example.com"]
      secretName: api-tls
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80

Gateway API (Envoy Gateway / Istio / Traefik)

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
spec:
  parentRefs:
    - name: production-gateway
  hostnames:
    - "api.example.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api/v2
      backendRefs:
        - name: api-v2
          port: 80
          weight: 90
        - name: api-v2-canary
          port: 80
          weight: 10
      filters:
        - type: RequestHeaderModifier
          requestHeaderModifier:
            add:
              - name: X-Request-Start
                value: "%START_TIME%"
    - matches:
        - path:
            type: PathPrefix
            value: /api/v1
      backendRefs:
        - name: api-v1
          port: 80

Decision Framework

If You Need...ChooseReason
Maximum throughputHAProxyBest raw performance
Simplest setupNGINXMost documentation, lowest learning curve
Gateway API (future-proof)Envoy GatewayNative Gateway API implementation
Full service meshIstiomTLS, observability, traffic management
Zero-downtime configTraefikDynamic config without reloads
Cost efficiency (small cluster)NGINX or HAProxyLowest resource usage
Enterprise features (WAF, OIDC)NGINX Plus or IstioBuilt-in security features

By Cluster Size

Cluster SizeRecommendedReasoning
< 10 servicesNGINX IngressSimple, well-documented, low overhead
10-50 servicesTraefik or Envoy GatewayGateway API, dynamic config, good observability
50-200 servicesEnvoy Gateway or IstioAdvanced routing, traffic management
200+ services (mesh)IstioFull mesh features, mTLS everywhere

Migration Path

For teams currently on NGINX wanting to migrate to Gateway API:

# Step 1: Install Gateway API CRDs
# Step 2: Deploy Envoy Gateway alongside NGINX
# Step 3: Gradually move routes from Ingress to HTTPRoute
# Step 4: Decommission NGINX once migration complete

# Both can coexist using different ingressClassNames/gateway names
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: legacy-routes
spec:
  ingressClassName: nginx  # Old routes stay on NGINX
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: new-routes
spec:
  parentRefs:
    - name: envoy-gateway  # New routes on Envoy Gateway

Key Takeaways

  • HAProxy delivers the highest throughput and lowest latency at 130K+ RPS with sub-2ms p50 latency, making it ideal for performance-critical workloads.
  • NGINX remains the safe default with the largest community, most documentation, and lowest learning curve for teams new to Kubernetes ingress.
  • Gateway API is the future and should be adopted for new clusters; Envoy Gateway and Traefik have the most complete implementations.
  • Istio is justified only when you need full service mesh including automatic mTLS, distributed tracing, and complex traffic policies; its resource overhead (600MB+ idle) is significant.
  • Traefik trades performance for operational simplicity with zero-downtime configuration changes and built-in Let's Encrypt, suitable for teams prioritizing developer experience.
  • Resource cost varies 10x between options from 80MB (HAProxy) to 1.2GB (Istio under load), impacting node sizing and cluster costs.
  • Plan for Gateway API migration even if using Ingress today, as all major controllers are converging on this standard.

Comments

    No comments yet. Be the first to share your thoughts.