Skip to main content

Traffic Splitting: Weighted Routing and Canary Deployments

Intermediate
  • Weighted Routing
  • Nginx Ingress - Canary Annotations
  • Gateway API - Native Weighted Routing
  • +34 more sections...

Traffic Splitting: Weighted Routing and Canary Deployments

Traffic splitting is a powerful feature for gradual rollouts, A/B testing, and canary deployments. Gateway API provides native support for weighted routing, making it much easier than Nginx Ingress.

Weighted Routing

Weighted routing allows you to split traffic between multiple backend services based on percentages.

Nginx Ingress - Canary Annotations

Nginx Ingress requires annotations for canary deployments:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: canary-service
                port:
                  number: 80

You need two separate Ingress resources - one for stable and one for canary!

Gateway API - Native Weighted Routing

Gateway API has native weighted routing in a single HTTPRoute:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: weighted-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: stable-service
          port: 80
          weight: 90
        - name: canary-service
          port: 80
          weight: 10

Single resource, native support!

Traffic Splitting Visualization

How Gateway API splits traffic between backends using weights

Nginx Ingress: Requires two separate Ingress resources with canary annotations

Gateway API: Single HTTPRoute with native weighted routing

Incoming Traffic
Gateway

Routes based on weights

Stable Service
Weight: 90
90% of traffic
stable-service:80
Production-ready version
Canary Service
Weight: 10
10% of traffic
canary-service:80
New version being tested

How weights work:

Stable: 90 / (90 + 10) = 90%
Canary: 10 / (90 + 10) = 10%
backendRefs:
  - name: stable-service
    port: 80
    weight: 90
  - name: canary-service
    port: 80
    weight: 10

How Weights Work

Weights are relative percentages. The Gateway API implementation calculates the actual percentage based on the total weight.

Example: 90/10 Split

backendRefs:
  - name: stable-service
    port: 80
    weight: 90
  - name: canary-service
    port: 80
    weight: 10
  • Stable service gets: 90 / (90 + 10) = 90% of traffic
  • Canary service gets: 10 / (90 + 10) = 10% of traffic

Example: 50/50 Split

backendRefs:
  - name: service-a
    port: 80
    weight: 50
  - name: service-b
    port: 80
    weight: 50

Both services get 50% of traffic.

Example: Three Services

backendRefs:
  - name: service-a
    port: 80
    weight: 60
  - name: service-b
    port: 80
    weight: 30
  - name: service-c
    port: 80
    weight: 10
  • Service A: 60%
  • Service B: 30%
  • Service C: 10%

Canary Deployments

Canary deployments gradually roll out new versions to a small percentage of users.

Nginx Ingress Canary Pattern

You need two Ingress resources:

Stable Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: stable-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: stable-service
                port:
                  number: 80

Canary Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: canary-service
                port:
                  number: 80

Gateway API Canary Pattern

Single HTTPRoute with weights:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: canary-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: stable-service
          port: 80
          weight: 90
        - name: canary-service
          port: 80
          weight: 10

Progressive Canary Rollout

With Gateway API, you can easily adjust weights for progressive rollouts:

Phase 1: 5% Canary

backendRefs:
  - name: stable-service
    port: 80
    weight: 95
  - name: canary-service
    port: 80
    weight: 5

Phase 2: 25% Canary

backendRefs:
  - name: stable-service
    port: 80
    weight: 75
  - name: canary-service
    port: 80
    weight: 25

Phase 3: 50% Canary

backendRefs:
  - name: stable-service
    port: 80
    weight: 50
  - name: canary-service
    port: 80
    weight: 50

Phase 4: 100% Canary (Complete Rollout)

backendRefs:
  - name: canary-service
    port: 80
    weight: 100

A/B Testing

Weighted routing is perfect for A/B testing different versions of your application.

Example: UI A/B Test

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: ab-test-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: ui-version-a
          port: 80
          weight: 50
        - name: ui-version-b
          port: 80
          weight: 50

Traffic Mirroring

Traffic mirroring sends a copy of traffic to a secondary service without affecting the primary response. This is useful for testing new services with production traffic.

Nginx Ingress - Traffic Mirroring

Requires annotations:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mirror-ingress
  annotations:
    nginx.ingress.kubernetes.io/mirror-target: "https://mirror.example.com"
    nginx.ingress.kubernetes.io/mirror-request-body: "always"

Gateway API - Request Mirror Filter

Native support via filters:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mirror-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      filters:
        - type: RequestMirror
          requestMirror:
            backendRef:
              name: mirror-service
              port: 80
      backendRefs:
        - name: primary-service
          port: 80

Note: The primary service still handles the request and responds. The mirror service receives a copy asynchronously.

Combining Traffic Splitting with Other Features

Weighted Routing + Header Matching

Route canary traffic based on headers:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: header-weighted-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    # Force canary for specific users
    - matches:
        - headers:
            - name: X-Canary-User
              value: "true"
      backendRefs:
        - name: canary-service
          port: 80
          weight: 100
    # Weighted routing for everyone else
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: stable-service
          port: 80
          weight: 90
        - name: canary-service
          port: 80
          weight: 10

Weighted Routing + Path Matching

Different weights for different paths:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: path-weighted-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    # API endpoints - 20% canary
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-stable
          port: 80
          weight: 80
        - name: api-canary
          port: 80
          weight: 20
    # Web endpoints - 10% canary
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: web-stable
          port: 80
          weight: 90
        - name: web-canary
          port: 80
          weight: 10

Complete Examples

Example 1: Simple Canary Deployment

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: canary-deployment
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - app.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: stable-app
          port: 80
          weight: 90
        - name: canary-app
          port: 80
          weight: 10

Example 2: Multi-Version Rollout

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: multi-version-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - api.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: v1-service
          port: 80
          weight: 60
        - name: v2-service
          port: 80
          weight: 30
        - name: v3-service
          port: 80
          weight: 10

Example 3: Blue-Green with Weights

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: blue-green-route
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: blue-service
          port: 80
          weight: 100
        - name: green-service
          port: 80
          weight: 0  # Gradually increase to 100

Comparison Table

FeatureNginx IngressGateway API
Weighted RoutingCanary annotationsNative weight field
Multiple BackendsTwo Ingress resourcesSingle HTTPRoute
Traffic MirroringAnnotationsNative RequestMirror filter
A/B TestingComplex setupSimple weights
Progressive RolloutManual annotation updatesUpdate weights in HTTPRoute

Best Practices

  1. Start Small: Begin with 5-10% canary traffic
  2. Monitor Closely: Watch metrics during canary rollouts
  3. Gradual Increase: Increase canary percentage gradually (5% → 25% → 50% → 100%)
  4. Quick Rollback: Keep stable service ready for quick rollback
  5. Use Headers for Testing: Combine with header matching for internal testing
  6. Document Weights: Keep track of weight changes for audit purposes

Common Patterns

Pattern 1: Gradual Canary Rollout

# Day 1: 5%
weight: 5

# Day 2: 10%
weight: 10

# Day 3: 25%
weight: 25

# Day 4: 50%
weight: 50

# Day 5: 100%
weight: 100

Pattern 2: Feature Flag Canary

rules:
  # Force canary for feature flag
  - matches:
      - headers:
          - name: X-Feature-NewAPI
            value: "true"
      backendRefs:
        - name: new-api-service
          port: 80
          weight: 100
    # Gradual rollout for others
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: old-api-service
          port: 80
          weight: 90
        - name: new-api-service
          port: 80
          weight: 10

Troubleshooting

Weights Not Working?

  1. Verify all backendRefs have valid weights
  2. Check that backend services are healthy
  3. Ensure weights sum to a reasonable total (not required, but recommended)
  4. Check Gateway status for route acceptance

Canary Traffic Too High/Low?

  1. Verify weight calculations (weight / total weight)
  2. Check for other HTTPRoutes affecting the same hostname
  3. Ensure no header-based routing is interfering

Next Steps

Now that you understand traffic splitting, let's learn about TLS/SSL configuration:

👉 Next: TLS/SSL Configuration →

Sources & References

Version Compatibility: This content is based on Gateway API v1 and NGINX Gateway Fabric 2.2.1. Please verify compatibility with your cluster's Gateway API implementation and version.