Cloud Native 31 min read

Comparing Kubernetes Ingress Controllers: Nginx, Traefik, and Envoy Features & Performance

This article provides a detailed comparison of the three leading Kubernetes Ingress Controllers—Nginx, Traefik, and Envoy—covering their architecture, configuration methods, feature sets, performance benchmarks, and practical selection guidance for various deployment scenarios.

Raymond Ops
Raymond Ops
Raymond Ops
Comparing Kubernetes Ingress Controllers: Nginx, Traefik, and Envoy Features & Performance

Introduction

Kubernetes uses Ingress as the standard way to expose services externally. An Ingress resource defines HTTP/HTTPS routing rules, while an Ingress Controller implements those rules by translating them into reverse‑proxy configurations and updating them dynamically.

The three mainstream Ingress Controllers are Nginx Ingress Controller, Traefik, and Envoy (via Contour). Each has distinct characteristics that affect cluster stability, performance, and maintainability.

Chapter 1 – Ingress Basics

1.1 Kubernetes Network Model

Pods receive unique IP addresses and can communicate directly without NAT. Services abstract a group of Pods and provide load‑balancing and discovery. ClusterIP is the default Service type, accessible only inside the cluster. To expose services externally you can use NodePort, LoadBalancer, or Ingress (layer‑7 routing).

1.2 Ingress Resource Definition

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
  ingressClassName: nginx
  rules:
  - host: demo.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 8080
  tls:
  - hosts:
    - demo.example.com
    secretName: demo-tls-secret

The ingressClassName field (supported from Kubernetes 1.18) selects the controller that will handle the resource.

Chapter 2 – Nginx Ingress Controller

2.1 Architecture & Principles

Nginx Ingress runs either as a Deployment (suitable for large clusters with HPA) or as a DaemonSet (one pod per node for low‑latency use cases).

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
    spec:
      containers:
      - name: controller
        image: registry.k8s.io/ingress-nginx/controller:v1.9.4
        args:
        - /nginx-ingress-controller
        - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
        - --election-id=ingress-controller-leader
        - --controller-class=k8s.io/ingress-nginx
        - --ingress-class=nginx
        - --configmap=$(POD_NAMESPACE)/nginx-configuration
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        livenessProbe:
          httpGet:
            path: /healthz
            port: 10254
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /healthz
            port: 10254
          periodSeconds: 5
        resources:
          requests:
            cpu: 100m
            memory: 90Mi
          limits:
            cpu: 1
            memory: 1Gi

2.2 Configuration Methods

Configuration can be done via Ingress annotations or a global ConfigMap. Common annotations include SSL redirect, rate limiting, request body size, timeouts, and canary deployment flags.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cafe-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/limit-rps: "100"
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "30"
spec:
  ingressClassName: nginx
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        pathType: Exact
        backend:
          service:
            name: tea-svc
            port:
              number: 80
      - path: /coffee
        pathType: Prefix
        backend:
          service:
            name: coffee-svc
            port:
              number: 80

2.3 Global ConfigMap Example

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
data:
  proxy-body-size: "50m"
  proxy-connect-timeout: "30"
  proxy-read-timeout: "60"
  enable-brotli: "true"
  enable-gzip: "true"
  gzip-level: "6"

2.4 TLS Configuration

Both simple TLS (single secret) and self‑signed certificate creation are demonstrated.

2.5 Canary Release

Canary can be weight‑based or header‑based using annotations nginx.ingress.kubernetes.io/canary and related keys.

Chapter 3 – Traefik

3.1 Architecture & Principles

Traefik is a cloud‑native reverse proxy that watches the Kubernetes API (or other providers) and updates routing without process reloads. It separates Provider, Router, Middleware, and Service components.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik
  namespace: ingress
spec:
  replicas: 2
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      containers:
      - name: traefik
        image: traefik:v3.0.4
        args:
        - --api.insecure
        - --accesslog
        - --entrypoints.http.address=:80
        - --entrypoints.https.address=:443
        - --providers.kubernetesingress
        - --log.level=INFO
        - --metrics.prometheus
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        - name: admin
          containerPort: 8080
        livenessProbe:
          httpGet:
            path: /ping
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ping
            port: 8080
          periodSeconds: 5
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi

3.2 IngressRoute CRD

Traefik introduces its own IngressRoute CRD, which offers richer routing options.

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: demo-ingressroute
  namespace: default
spec:
  entryPoints:
  - web
  - websecure
  routes:
  - match: Host(`demo.example.com`) && PathPrefix(`/api`)
    kind: Rule
    services:
    - name: api-service
      port: 80
    middlewares:
    - name: strip-api-prefix
    - name: rate-limit
  - match: Host(`demo.example.com`) && PathPrefix(`/`)
    kind: Rule
    services:
    - name: frontend-service
      port: 80

3.3 Middleware

Traefik uses Middleware objects for authentication, rate limiting, retries, redirects, and more.

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: basic-auth
  namespace: default
spec:
  basicAuth:
    secret: basic-auth-secret
---
apiVersion: v1
kind: Secret
metadata:
  name: basic-auth-secret
  namespace: default
type: Opaque
stringData:
  users: |
    admin:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/

3.4 Dynamic Service Discovery

Traefik can pull services from Consul, Etcd, ZooKeeper, etc., in addition to Kubernetes.

3.5 TCP/UDP Support

Traefik also supports TCP and UDP entry points via dedicated CRDs.

Chapter 4 – Envoy (via Contour)

4.1 Architecture & Principles

Envoy is a high‑performance edge and service proxy written in C++. It uses the xDS API for dynamic configuration. Core concepts include Listeners, Routes, Clusters, Endpoints, Filters, and Health Checks.

4.2 Contour Deployment

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: contour
  namespace: projectcontour
spec:
  replicas: 2
  selector:
    matchLabels:
      app: contour
  template:
    metadata:
      labels:
        app: contour
    spec:
      containers:
      - name: contour
        image: ghcr.io/projectcontour/contour:v1.28.2
        command:
        - contour
        - serve
        - --xds-address=0.0.0.0
        - --xds-port=8001
        - --envoy-http-port=8080
        - --envoy-https-port=8443
        - --config-path=/config/contour.yaml
        ports:
        - name: xds
          containerPort: 8001
        - name: http
          containerPort: 8080
        - name: https
          containerPort: 8443
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8001
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8001
          periodSeconds: 5
      - name: envoy
        image: ghcr.io/projectcontour/contour:v1.28.2
        command:
        - envoy
        - -c
        - /config/envoy.json
        - --service-cluster
        - projectcontour
        - --service-node
        - $(NODE_NAME)
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        ports:
        - name: http
          containerPort: 8080
        - name: https
          containerPort: 8443

4.3 HTTPProxy CRD

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: demo-proxy
  namespace: default
spec:
  virtualhost:
    fqdn: demo.example.com
    cors:
      allow-credentials: true
      allow-headers:
      - X-Custom-Header
      allow-methods:
      - GET
      - POST
      - PUT
      - DELETE
      allow-origin:
      - "https://allowed.example.com"
      max-age: "86400"
  routes:
  - conditions:
    - prefix: /api
    services:
    - name: api-service
      port: 80
    healthcheck:
      path: /health
      interval: 10s
      timeout: 5s
      unhealthyThreshold: 3
      healthyThreshold: 2
    loadBalancerPolicy:
      strategy: WeightedLeastRequest
    retryPolicy:
      retryOn: gateway-error,connect-failure,reset
      numRetries: 3
      perTryTimeout: 10s
  - conditions:
    - prefix: /
    services:
    - name: frontend-service
      port: 80
    rateLimit:
      global:
        descriptors:
        - entries:
          - key: remote_addr
            rateLimitValue:
              requests: 100
              unit: minute
    tcpproxy:
      services:
      - name: tcp-service
        port: 9000
        weight: 1

4.4 Rate Limiting

Envoy supports global token‑bucket rate limiting via TLSPolicy resources and per‑service annotations.

apiVersion: projectcontour.io/v1
kind: TLSPolicy
metadata:
  name: ratelimit-policy
  namespace: default
spec:
  limits:
  - units: second
    requests: 100
    condition:
    - requestHeader:
        headerName: X-Forwarded-For
        count: 1

4.5 Health Checks & Load Balancing

Envoy provides active and passive health checks and supports multiple load‑balancing strategies (RoundRobin, WeightedLeastRequest, Random, Cookie, Header).

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: healthcheck-proxy
  namespace: default
spec:
  virtualhost:
    fqdn: api.example.com
  routes:
  - services:
    - name: api-service
      port: 80
    healthcheck:
      path: /healthz
      interval: 10s
      timeout: 5s
      expectedStatus: "200-299"
      unhealthyThreshold: 3
      healthyThreshold: 2

Chapter 5 – Comprehensive Comparison

5.1 Performance

Solution      QPS      P99 Latency   Memory
Nginx Ingress 50,000+   5ms          150MB
Traefik v3    35,000+   8ms          200MB
Envoy (Contour)40,000+ 6ms          300MB

5.2 Feature Matrix

Feature               Nginx   Traefik   Envoy (Contour)
Layer‑7 routing      ✔       ✔         ✔
Layer‑4 proxy        ✔       ✔         ✔
WebSocket            ✔       ✔         ✔
gRPC                 ✔       ✔         ✔
TLS termination      ✔       ✔         ✔
Auto‑HTTPS           Cert‑Mgr ✔       Cert‑Mgr
Rate limiting        Annotations/ConfigMap Middleware Global
Authentication       Annotations Middleware CRD
Retry/Timeout        Annotations Middleware CRD
Canary release       Annotations  –        HTTPProxy
Circuit breaking      –       –        ✔
Dynamic config       reload   hot‑reload hot‑reload
Metrics               Prometheus Prometheus/Datadog Prometheus
Tracing               Zipkin/Jaeger OpenTelemetry Zipkin/OTel

5.3 Configuration Complexity

Nginx offers a familiar, annotation‑driven approach for engineers experienced with Nginx. Traefik provides the most concise declarative syntax via CRDs and Middleware. Envoy delivers the richest feature set but requires deeper understanding; Contour mitigates some complexity.

5.4 Ecosystem & Community

Nginx has the most mature enterprise ecosystem and commercial support. Traefik is backed by an active open‑source community and offers an enterprise edition. Envoy is a CNCF project, integral to service‑mesh solutions like Istio and Linkerd.

Chapter 6 – Selection Guidance & Best Practices

6.1 Scenario‑Based Selection

Small‑to‑medium clusters (<1000 Pods): Nginx or Traefik – simple config, strong docs.

Large, high‑traffic clusters: Nginx for raw performance or Envoy for fine‑grained traffic control.

Fine‑grained traffic management (canary, fault injection, circuit breaking): Envoy (Contour).

Service‑mesh integration: Envoy.

6.2 Deployment Architecture

For production, deploy the controller as a DaemonSet to guarantee an ingress point on every node.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ingress
  namespace: ingress-nginx
spec:
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
    spec:
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: controller
        image: registry.k8s.io/ingress-nginx/controller:v1.9.4
        args:
        - /nginx-ingress-controller
        - --configmap=$(POD_NAMESPACE)/nginx-configuration
        - --report-node-internal-ip-address
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        ports:
        - name: http
          hostPort: 80
          containerPort: 80
        - name: https
          hostPort: 443
          containerPort: 443

Scale the controller with a HorizontalPodAutoscaler based on CPU and memory utilization.

6.3 Security Hardening

Example TLS configuration with HSTS and security headers for Nginx.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
    nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
    nginx.ingress.kubernetes.io/server-snippet: |
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-XSS-Protection "1; mode=block" always;
      add_header Referrer-Policy "no-referrer-when-downgrade" always;
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80

6.4 Monitoring

Expose Prometheus metrics and use community dashboards.

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller-metrics
  namespace: ingress-nginx
  annotations:
    prometheus.io/port: "10254"
    prometheus.io/scrape: "true"
spec:
  ports:
  - name: metrics
    port: 10254
  selector:
    app: nginx-ingress
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: nginx-ingress
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: nginx-ingress
  endpoints:
  - port: metrics
    interval: 15s
  namespaceSelector:
    matchNames:
    - ingress-nginx

Chapter 7 – Troubleshooting Guide

7.1 Checking Controller Status

# View controller logs
kubectl logs -n ingress-nginx -l app=nginx-ingress -f
# Recent events
kubectl get events -n ingress-nginx --sort-by='.lastTimestamp'
# Show current controller configuration
kubectl exec -n ingress-nginx deploy/nginx-ingress-controller -- nginx-ingress-controller --show-config

7.2 Common Issues

Ingress returns 404 : Verify Ingress existence, host rules, Service endpoints, and Pod readiness.

TLS not working : Ensure the TLS Secret exists, contains valid cert/key, and is referenced correctly. Check Cert‑Manager status if used.

Rate limiting ineffective : Confirm annotation values or ConfigMap entries, and inspect controller logs for rate‑limit processing.

7.3 Performance Diagnosis

# Resource usage
kubectl top pods -n ingress-nginx
# Active connections (Nginx)
kubectl exec -it nginx-ingress-controller-xxx -n ingress-nginx -- wget -qO- http://localhost:10254/status
# Upstream status inspection
kubectl exec -it nginx-ingress-controller-xxx -n ingress-nginx -- cat /etc/nginx/nginx.conf | grep -A 50 "upstream"

7.4 Log Analysis

# Extract slow requests (response time > 1s)
kubectl logs -n ingress-nginx -l app=nginx-ingress | \
  awk '{if($NF > 1) print}' | sort -k9 -nr | head -20

Conclusion

Nginx Ingress Controller, Traefik, and Envoy each excel in different areas: Nginx offers the highest raw performance and a mature ecosystem; Traefik provides the simplest configuration and hot‑reload capabilities; Envoy delivers the richest feature set and seamless integration with service‑mesh platforms. Selecting the right controller should consider team expertise, performance requirements, feature needs, and operational maturity. Regardless of the choice, implement robust monitoring, alerting, and disaster‑recovery procedures to ensure reliable production operation.

References

Kubernetes Ingress documentation: https://kubernetes.io/docs/concepts/services-networking/ingress/

Nginx Ingress Controller docs: https://kubernetes.github.io/ingress-nginx/

Traefik documentation: https://doc.traefik.io/traefik/

Contour (Envoy) documentation: https://projectcontour.io/docs/

Envoy documentation: https://www.envoyproxy.io/docs/envoy/latest/

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Performancecloud nativekubernetesConfigurationNginxEnvoyIngress ControllerTraefik
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.