traefik/docs/content/routing/providers/kubernetes-gateway.md

26 KiB

title description
Traefik Kubernetes Gateway The Kubernetes Gateway API can be used as a provider for routing and load balancing in Traefik Proxy. View examples in the technical documentation.

Traefik & Kubernetes with Gateway API

When using the Kubernetes Gateway API provider, Traefik leverages the Gateway API Custom Resource Definitions (CRDs) to obtain its routing configuration. For detailed information on the Gateway API concepts and resources, refer to the official documentation.

The Kubernetes Gateway API provider supports version v1.2.0 of the specification.

It fully supports all HTTPRoute core and some extended features, like GRPCRoute, as well as the TCPRoute and TLSRoute resources from the Experimental channel.

For more details, check out the conformance report.

Deploying a Gateway

A Gateway is a core resource in the Gateway API specification that defines the entry point for traffic into a Kubernetes cluster. It is linked to a GatewayClass, which specifies the controller responsible for managing and handling the traffic, ensuring that it is directed to the appropriate Kubernetes backend services.

The GatewayClass is a cluster-scoped resource typically defined by the infrastructure provider. The following GatewayClass defines that gateways attached to it must be managed by the Traefik controller.

---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: traefik
spec:
  controllerName: traefik.io/gateway-controller

Next, the following Gateway manifest configures the running Traefik controller to handle the incoming traffic.

!!! info "Listener ports"

Please note that `Gateway` listener ports must match the configured [EntryPoint ports](../entrypoints.md) of the Traefik deployment. 
In case they do not match, an `ERROR` message is logged, and the resource status is updated accordingly.
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: traefik
  namespace: default
spec:
  gatewayClassName: traefik
  
  # Only Routes from the same namespace are allowed.
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same 

    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: secret-tls
            namespace: default

      allowedRoutes:
        namespaces:
          from: Same

    - name: tcp
      protocol: TCP
      port: 3000
      allowedRoutes:
        namespaces:
          from: Same

    - name: tls
      protocol: TLS
      port: 3443
      tls:
        mode: Terminate
        certificateRefs:
          - name: secret-tls
            namespace: default
            
      allowedRoutes:
        namespaces:
          from: Same
---
apiVersion: v1
kind: Secret
metadata:
  name: secret-tls
  namespace: default
type: kubernetes.io/tls
data:
  # Self-signed certificate for the whoami.localhost domain.
  tls.crt: |
    LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZWakNDQXo2Z0F3SUJBZ0lVZUUrZG94aTUrMTBMVi9DaUdTMkt2Q1dJR1dZd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1JERUxNQWtHQTFVRUJoTUNSbEl4RFRBTEJnTlZCQWNNQkV4NWIyNHhGVEFUQmdOVkJBb01ERlJ5WVdWbQphV3NnVEdGaWN6RVBNQTBHQTFVRUF3d0dWMmh2WVcxcE1DQVhEVEkwTURjeE1ERTFNRGt3TjFvWUR6SXhNalF3Ck5qRTJNVFV3T1RBM1dqQkVNUXN3Q1FZRFZRUUdFd0pHVWpFTk1Bc0dBMVVFQnd3RVRIbHZiakVWTUJNR0ExVUUKQ2d3TVZISmhaV1pwYXlCTVlXSnpNUTh3RFFZRFZRUUREQVpYYUc5aGJXa3dnZ0lpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQ0R3QXdnZ0lLQW9JQ0FRQ1pNNm1WNUJkV2V0QzZtdnp0YVBobFNjZ0ljbnd6Z3NsOEFxendEMk05ClJWVkZwRUxBbTh2OTNlRWtMZEY2ZnNkY0FhUXQxWlFDSFdYby9mTHBRNVVrUHh1djZNUCt2NG1KMHY4ZEtGWjcKUjcwaTVud1lCMkVlVkw2RUNZaWlxNmZ6VEtsa3F6U0QvNW93elN3L3pqa0dUYTBJdy92SDlhc0g3NEhqM1d0QQo3RythenZjaVlhQTZxK1dWYlZxNlBIanF6em9obEFuMkh1ano2aERqYWllc3ZMbHdBL0IvcmhEc0FLaCtpMHI4CkFKUTFqM0JiTGJuYkJyWmZqYnBJUjNhYVh5amkwK3RQWENnVTkzQmU5dm1LZTZTY0dSNy82T25tYmtTc0xjZFcKaFpVNzcrL2c4WllsZGhwS01nczc4ekJYUlh4bHlzSThHRUtqU1hud3k5WmZNT2RJNEpBTWNtT0lOaVlBY21abgpJTUJIa0xacFl3aUl0eFdseXVJcWxoZFpkSHNrTFdNSjBSTHUxRmhTMnBFV0NOZTM3VDBiOWhtNFg0OXJ1QWJ6Ckl1M01xSmczcXFIdGRMNGRkZ1JZRHNjMXd0cDJrR2dBZGxDaXJIclF6K1l4MEJNT1ZsZEczaG1SUUh5ZHEySHIKWW0xeEFDNWpMZ3FvaVZhY09wd0xKY21PcGsrZWVNQkNZNVo0ekNYN1hXeXdhVmNtMnN2aGlPMThCZFIraDloWQpiMkRNZDFCendDbE95endQcUlvQy9uNGRURG96Ry9GT3NySzgvNEZ4dzY2Q1ZmM3E4MzBNUHdSd2xDSzFDQjdGCjNQK3lKWkpPelRuK05QZ2dGQW9NaGZUYXBQWTFhUGlWajBzVG9vQjBaOGNFV1RkTnJxQU5tUGs5aDNoQjJwbjgKSndJREFRQUJvejR3UERBYkJnTlZIUkVFRkRBU2doQjNhRzloYldrdWJHOWpZV3hvYjNOME1CMEdBMVVkRGdRVwpCQlNGSjF4N01xdG9zQ3UwQmFWbEs1U054K2djampBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVdCOVc1eWkzClRpTWpmSThhSCtMZW1wZjc4clhyeWJ6UXJvSXdEazhqQXhnc3Nrc2V2ZEtIaXJIZGJMZ0RoS2krbkJLeEQ5S2QKNWM4RS9VL1VHWUhxaUowTVUzYkpoeTVNM3oyaklKd1hFa3FuVVhRd0dBNzVyU0QxWVBkOTlWeVpuNEJVRlEwdwpCT3loOU5DS3Z3ZTgycUVlOWZmeU5iem5JUEMrNS9pekhaYlNQMEpwRzdtNFQ5TXljdHV1OTlsaVhmSVlCMU1PCkRFRUdpamxhZ3JvdTliVlpsNmovR2xCaVZpU0JVQXhaRlNqdFErV2RFODJaZlFRUFVWdXQrUEY0SEl0N1dmYlgKaUpZbjRsMytJSVczNStvbUZ5QjR5WUJNdU9SVWRsZ3V5N1ZieEU5OTdPdHYzTnpDOGJYcGtaQVM0TkVzQVVFdwpJZ3lOcTFCdExsb3dZdjZXY05HbkJ5RE1NRUMzdUYzNEcxQkJCTzFDRHUrYXBVdW5NbVhUWmU5WlkrbXh4U2Z2CnBZclhHTHBoT2t4ZitQalpMbEpqQVFlcTNxblMvWWtLQmtYQi9zb282ZVVLTTlybyt5RTVMbnFrV20wZXpQWmwKc2Z5NGpqZ0lJUHlUMHhhZ0YyWExzUSs0M3N4aDRYTEhmc3Z3Zis2QnJVK2trTnoydmc2M3duLzJDQUNVVms3bgphSDdwZzZyZGt4T2pOTDJjUGd6ZzhWaExXbkVYYjhhUVJlVjY1WnlRc0xta21oOXBlSFRpYXBUb2xWa0d6TDIwCm9pdExZc3ZUcnhUR2NRd3Jpd3FaT1I3WjEvVEJLVnVoYnp0emxlRjFHRk9LdE52UmNSREVBeWVlbnJDRzRRMmgKMnFNNFh1RFFKcjJrR095OEV0dnlYTitENkNZUkg0ck5vZUk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K    

  tls.key: |
    LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRQ1pNNm1WNUJkV2V0QzYKbXZ6dGFQaGxTY2dJY253emdzbDhBcXp3RDJNOVJWVkZwRUxBbTh2OTNlRWtMZEY2ZnNkY0FhUXQxWlFDSFdYbwovZkxwUTVVa1B4dXY2TVArdjRtSjB2OGRLRlo3UjcwaTVud1lCMkVlVkw2RUNZaWlxNmZ6VEtsa3F6U0QvNW93CnpTdy96amtHVGEwSXcvdkg5YXNINzRIajNXdEE3RythenZjaVlhQTZxK1dWYlZxNlBIanF6em9obEFuMkh1anoKNmhEamFpZXN2TGx3QS9CL3JoRHNBS2graTByOEFKUTFqM0JiTGJuYkJyWmZqYnBJUjNhYVh5amkwK3RQWENnVQo5M0JlOXZtS2U2U2NHUjcvNk9ubWJrU3NMY2RXaFpVNzcrL2c4WllsZGhwS01nczc4ekJYUlh4bHlzSThHRUtqClNYbnd5OVpmTU9kSTRKQU1jbU9JTmlZQWNtWm5JTUJIa0xacFl3aUl0eFdseXVJcWxoZFpkSHNrTFdNSjBSTHUKMUZoUzJwRVdDTmUzN1QwYjlobTRYNDlydUFiekl1M01xSmczcXFIdGRMNGRkZ1JZRHNjMXd0cDJrR2dBZGxDaQpySHJReitZeDBCTU9WbGRHM2htUlFIeWRxMkhyWW0xeEFDNWpMZ3FvaVZhY09wd0xKY21PcGsrZWVNQkNZNVo0CnpDWDdYV3l3YVZjbTJzdmhpTzE4QmRSK2g5aFliMkRNZDFCendDbE95endQcUlvQy9uNGRURG96Ry9GT3NySzgKLzRGeHc2NkNWZjNxODMwTVB3UndsQ0sxQ0I3RjNQK3lKWkpPelRuK05QZ2dGQW9NaGZUYXBQWTFhUGlWajBzVApvb0IwWjhjRVdUZE5ycUFObVBrOWgzaEIycG44SndJREFRQUJBb0lDQUVCa2dKRXA3ODAvamVBQktQSTR2cjhFCkJmblc5UEZKdFpwVUhaQkJSM3NIVzFJTU9xcHVVWTJBNXhLbjEzWmZOemdxMEhFYlpqeUZVc0pkaXU0VW8razYKUlU3b3pRaVVSU0VTK0h1dTZycWlhcEx5d1pIditCZ2hrbm80NzU4Lyt6VytNU3pJOFNmU0ZXTVJ1ZG1QdWxRMQo3ZGJUV1U2d3FaU0tUTlFUeXZMYzdnUHBuZUpybWtkTzNRNnppZ0RoVGdtVDFHRXNzZ3NxN3NzbXhMWnhkZithCnkyNlRtVkJ4UDFlUzV6OVpHTWxYRFBSK044RjdOTFVrMng3S21WT3NCZVBZdjN5bmlpNHZGQUhNQndWRFZadXAKWUlUajRpMjZIaVhtanlLM2t5T0F2anNWSElRMXh1QTBCZFROdC84WXRtYllJL005QitydVg0UDJiRFNUMktRKwo4TlN2Uk9wbVppcnBHZkY3bExMSGpJUjlTMFhCWDd6VDRoWnBRWnpqK3NEWnhDM2Y3TGIwRFlKYkp0TmlDYTQxCmNpTjhNUlNldzNneHZ0RVk0RzdnN3hjbkJNdjdNT3RwQTE3d2gvMHdLd0h0amYzSWh2TmIzdkZwT0k5d1FqSzYKSlRQMng4bENJV0tyalpObVN0UksreHJTN3hTOUZVdnBhSVlyclRLQkZWSmcyMURCYWI1L3hqRlBlQWxXejczSwpvVkhsa0hLdXNMSjZLczZzcXo0ZG9mbzg3dkFsUFJzTXRkZ1ZnZFIzNXhLTGtEWXNIbGxML3Z5dE9oSkNieXB5CkJqQm1TR0RMdzBDdWplaHVtU2czYjdSUGVTNk5rbHNqUEIrMVpzRjhpVGdCcjMyM1hvTmNha2dhWWVYQlg4NFAKaE1WZHUxWk1rbXJZMWhXTzEydnhBb0lCQVFEWU5Vb2xCMkhsdWlDcVFqdmU4UFNhV0YxRmhwNUlOMGJIZEppeApIdkhqMkplVHJ6V1pUZFlIdFNJR2RzalhTOTBESXo2bXJhMW9YZXFRYlgrODVlOUFQQkZnRTJmNU5uTzBCSVVJCk5hMXRiVGpIOUhjRGRzQmJKUkZwYnk1ODZUb3lhdFY3bS9zcjVpQUZlZFMyenFOTm1XUmZOdllZS2xselZoSEUKdUd4ZjZxMHJTWktVQUhja2s1bU5Yais3WFhZaTgyemErVEE3ZjBDVm5OamR3OXFpd3B2aTJKTFB2SnA0bWt6KwpyMEN1RW9yV2NhMUdTL2hTVWdXemw3NzhQdlRpZFI2RW4zMDB2ZlIyTE84aG1xRjhVL3Bpb2UrTDVjSllRNnNKCk1YMngrYThzWFFpZ3dwdG02aUNxQ2FuS3ExN3NUZS9RTmQ1czdwb3ZOaHVKOHd3dEFvSUJBUUMxWmM5ZktPUFgKVzZSN1VoaHRRcmhIc3htQnRIQ1BuNWRLbjN5MElNNWRBaEFSdFZDV1U0M0hOTHpCNW1LbjU2dnZrSVNFaXdBbAoxTGhuY2I3YXQ2cHpTSlZtMm5oTDhjeUZrdGQrNzVyL1FHNFlpNnZQbHNBODV5ZXZpZDhZcWswaHdaZXExY05xCmxETUN3NWsrV0drckM2VW5jZXNIc2FWbDJTUGdZV1c1L3I1NnVxUnBsaVFka1EyZmlEYWRyblVueU8ycHg3bFMKVG1HemZaNmtzTWh2MlZFR1NPRm05aUo0dWlPb0xyZVhoU1RQRmxTdjdZUTZSWWtSaGgwT0tqdXM5bXZacEIxWApjcytYN0UyVTNlM0RZelpCR0NFdmxxaFNWTFRScjdIN21pMWxUMEozR0RzbDdiUk9xOE50WVdQa3hhSlNCUnQ5Ck9TcTlkTm9CcGRvakFvSUJBQ2lQdnN3NW1WVW0yUS80QXhGdE5RWnJ3M3ZTcUlrMXpaS0h2a21rVzQ3NlNGMk4KaGttdmY1TE1tWWlLNmx6eHY1SGlIOVBYUzJ3RUNvaHo4bjMyeVM3TTFobW5LbDlucHNkRC9jMHZmTXpGcTl4ZgpjYUIxdTlxZGxxbW9FUm1nQzZuL3Z2TkVyUmRzUWQrbEhwSDVMRXZYbGl3Q3ZLS0Y5MmdhNHBSOFlPQ1J2MUVhCnFXUVl2a0ZmYTNSSkZUM0taK3BncnJCYUJZRnoreUxXWFIwbHJEUFN2TG9QRldQaHB6MHUvWGplV2cwT0wzdlIKc2NjNVkybldOM21jNDFpaFd3SE5KUitPYUVmbnh5QVFpQUJPNlRMUThtMWtvZk1sOUpMb2h3TGZoUXhKb21KNQpSYkFiTWxwWlhDMXFTSzliL1IvcDh5NmxuSWZsTDRuaDVjSzRsVFVDZ2dFQUpSSHVSQU1tTksrTXVJcjVaUEs2Cm1DUjR0UEg4QXMzWmJDMlZuWFlLMWlVQ3hhdXBFVjkzM05yaExEcjV0Rmg2NFpWR0Q1UWNicDYvSkp5eEpSOWQKblB1YlZJNlhBT1lrSnJQd2lBZE5SSmFWS1R6NTJvMXpNYjhIZEM4WHdZR2tDNTcxY0xzSW1YSTV6bm5NaWxvaworK0FBVzBSRGhLb0FKQVV3K0x6T3ZpamFJbGljR3R2TSs2SFdCK0VkVURJRHpTS1p0eFdTd01nMTNTbHh6elExCmNlNFdTZE9CQkxxT0p0L2JRNVp3ZkcyQUxUWGlEcVhhWE5JekJickRtMDUwTFkrYVVMcmlLQ25WVkxXODBReGQKZDQyQjIrR2pmb2NxVk5Ec3R1RlIzUm9QNXVGQXN2Zm50b09TVW5WMWxaZk9nMFVFUEFEQk1tRUpZL2hLU1FYcwp3d0tDQVFBNWQya2hFQ1c1V3QrMzRYWnl1b3NFTjZ4UDExbC96VDRBZjhGSWtQLzlkb0JXRnBhc28zbG1NcXZHCmhPeFErbnZBSjFhNzhZRjA4N3p1UC9DZkQ0UElOUTV4YzZHMDNQdG5JOVNVT0dpMDB4Zlg5MU5NMHBHYWJqb0QKZ0RqVzJxSkJDaVB5N0RIR1RlZkU5eUNUbkhrY1NBbWllVGc3aGFyeEZPOUREZTJKbzhKQXV2SHI1aGVxazVIcgpLYlgzTy9vNUMwcWVnYW1rWVRLcHZzV2VFdXhkY2l5LzFQd3NnV3BuV1JPWllQNENrSkJweEx1bDNVamVSY3dkCnRhcjBJYU52WlV2NFd4U0JZdWVHMDFyYUd2SDZtTTcyTEExR3MrMytwTnZwUVo3bGo2S09tcFlhQUlhemVxY2MKTjJjT2R5U1RqZmQ5OFlNVFAxbmIyK3N1Yy91VAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==    

Exposing a Route

Once a Gateway is deployed (see Deploying a Gateway) HTTPRoute, TCPRoute, and/or TLSRoute resources must be deployed to forward some traffic to Kubernetes backend services.

!!! info "Attaching to Gateways"

As demonstrated in the following examples, a Route resource must be configured with `ParentRefs` that reference the parent `Gateway` it should be associated with.

HTTP/HTTPS

The HTTPRoute is a core resource in the Gateway API specification, designed to define how HTTP traffic should be routed within a Kubernetes cluster. It allows the specification of routing rules that direct HTTP requests to the appropriate Kubernetes backend services.

For more details on the resource and concepts, check out the Kubernetes Gateway API documentation.

For example, the following manifests configure a whoami backend and its corresponding HTTPRoute, reachable through the deployed Gateway at the http://whoami.localhost address.

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
     - matches:
        - path:
            type: PathPrefix
            value: /

       backendRefs:
        - name: whoami
          namespace: default
          port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoami

  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami

  ports:
    - port: 80

To secure the connection with HTTPS and redirect non-secure request to the secure endpoint, we will update the above HTTPRoute manifest to add a RequestRedirect filter, and add a new HTTPRoute which binds to the https Listener and forward the traffic to the whoami backend.

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-https
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: https
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /

      backendRefs:
        - name: whoami
          namespace: default
          port: 80

Once everything is deployed, sending a GET request to the HTTP and HTTPS endpoints should return the following responses:

$ curl -I http://whoami.localhost

HTTP/1.1 302 Found
Location: https://whoami.localhost/
Date: Thu, 11 Jul 2024 15:11:31 GMT
Content-Length: 5

$ curl -k https://whoami.localhost
 
Hostname: whoami-697f8c6cbc-2krl7
IP: 127.0.0.1
IP: ::1
IP: 10.42.1.5
IP: fe80::60ed:22ff:fe10:3ced
RemoteAddr: 10.42.2.4:44682
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.87.1-DEV
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.1.0
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: traefik-6b66d45748-ns8mt
X-Real-Ip: 10.42.1.0

GRPC

The GRPCRoute is an extended resource in the Gateway API specification, designed to define how GRPC traffic should be routed within a Kubernetes cluster. It allows the specification of routing rules that direct GRPC requests to the appropriate Kubernetes backend services.

For more details on the resource and concepts, check out the Kubernetes Gateway API documentation.

For example, the following manifests configure an echo backend and its corresponding GRPCRoute, reachable through the deployed Gateway at the echo.localhost:80 address.

---
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: echo
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - echo.localhost

  rules:
    - matches:
        - method:
            type: Exact
            service: grpc.reflection.v1alpha.ServerReflection

        - method:
            type: Exact
            service: gateway_api_conformance.echo_basic.grpcecho.GrpcEcho
            method: Echo

      backendRefs:
        - name: echo
          namespace: default
          port: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
  namespace: default
spec:
  selector:
    matchLabels:
      app: echo

  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
        - name: echo-basic
          image: gcr.io/k8s-staging-gateway-api/echo-basic
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: GRPC_ECHO_SERVER
              value: "1"

---
apiVersion: v1
kind: Service
metadata:
  name: echo
  namespace: default
spec:
  selector:
    app: echo

  ports:
    - port: 3000

Once everything is deployed, sending a GRPC request to the HTTP endpoint should return the following responses:

$ grpcurl -plaintext echo.localhost:80 gateway_api_conformance.echo_basic.grpcecho.GrpcEcho/Echo

{
  "assertions": {
    "fullyQualifiedMethod": "/gateway_api_conformance.echo_basic.grpcecho.GrpcEcho/Echo",
    "headers": [
      {
        "key": "x-real-ip",
        "value": "10.42.2.0"
      },
      {
        "key": "x-forwarded-server",
        "value": "traefik-74b4cf85d8-nkqqf"
      },
      {
        "key": "x-forwarded-port",
        "value": "80"
      },
      {
        "key": "x-forwarded-for",
        "value": "10.42.2.0"
      },
      {
        "key": "grpc-accept-encoding",
        "value": "gzip"
      },
      {
        "key": "user-agent",
        "value": "grpcurl/1.9.1 grpc-go/1.61.0"
      },
      {
        "key": "content-type",
        "value": "application/grpc"
      },
      {
        "key": "x-forwarded-host",
        "value": "echo.localhost:80"
      },
      {
        "key": ":authority",
        "value": "echo.localhost:80"
      },
      {
        "key": "accept-encoding",
        "value": "gzip"
      },
      {
        "key": "x-forwarded-proto",
        "value": "http"
      }
    ],
    "authority": "echo.localhost:80",
    "context": {
      "namespace": "default",
      "pod": "echo-78f76675cf-9k7rf"
    }
  }
}

TCP

!!! info "Experimental Channel"

The `TCPRoute` resource described below is currently available only in the Experimental channel of the Gateway API specification. 
To use this resource, the [experimentalChannel](../../providers/kubernetes-gateway.md#experimentalchannel) option must be enabled in the Traefik deployment.

The TCPRoute is a resource in the Gateway API specification designed to define how TCP traffic should be routed within a Kubernetes cluster.

For more details on the resource and concepts, check out the Kubernetes Gateway API documentation.

For example, the following manifests configure a whoami backend and its corresponding TCPRoute, reachable through the deployed Gateway at the localhost:3000 address.

---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: whoami-tcp
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: tcp
      kind: Gateway

  rules:
     - backendRefs:
        - name: whoamitcp
          namespace: default
          port: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoamitcp

  template:
    metadata:
      labels:
        app: whoamitcp
    spec:
      containers:
        - name: whoami
          image: traefik/whoamitcp
          args:
            - --port=:3000

---
apiVersion: v1
kind: Service
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    app: whoamitcp
  ports:
    - port: 3000

Once everything is deployed, sending the WHO command should return the following response:

$ nc localhost 3000

WHO
Hostname: whoamitcp-85d644bfc-ktzv4
IP: 127.0.0.1
IP: ::1
IP: 10.42.1.4
IP: fe80::b89e:85ff:fec2:7d21

TLS

!!! info "Experimental Channel"

The `TLSRoute` resource described below is currently available only in the Experimental channel of the Gateway API. 
Therefore, to use this resource, the [experimentalChannel](../../providers/kubernetes-gateway.md#experimentalchannel) option must be enabled.

The TLSRoute is a resource in the Gateway API specification designed to define how TLS (Transport Layer Security) traffic should be routed within a Kubernetes cluster. It specifies routing rules for TLS connections, directing them to appropriate backend services based on the SNI (Server Name Indication) of the incoming connection.

For more details on the resource and concepts, check out the Kubernetes Gateway API documentation.

For example, the following manifests configure a whoami backend and its corresponding TLSRoute, reachable through the deployed Gateway at the localhost:3443 address via a secure connection with the whoami.localhost SNI.

---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: whoami-tls
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: tls
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - backendRefs:
        - name: whoamitcp
          namespace: default
          port: 3000

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoamitcp

  template:
    metadata:
      labels:
        app: whoamitcp
    spec:
      containers:
        - name: whoami
          image: traefik/whoamitcp
          args:
            - --port=:3000

---
apiVersion: v1
kind: Service
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    app: whoamitcp
  ports:
    - port: 3000

Once everything is deployed, sending the WHO command should return the following response:

$ openssl s_client -quiet -connect localhost:3443 -servername whoami.localhost
Connecting to ::1
depth=0 C=FR, L=Lyon, O=Traefik Labs, CN=Whoami
verify error:num=18:self-signed certificate
verify return:1
depth=0 C=FR, L=Lyon, O=Traefik Labs, CN=Whoami
verify return:1

WHO
Hostname: whoamitcp-85d644bfc-hnmdz
IP: 127.0.0.1
IP: ::1
IP: 10.42.2.4
IP: fe80::d873:20ff:fef5:be86

Using Traefik middleware as HTTPRoute filter

An HTTP filter is an HTTPRoute component which enables the modification of HTTP requests and responses as they traverse the routing infrastructure.

There are three types of filters:

  • Core: Mandatory filters for every Gateway controller, such as RequestHeaderModifier and RequestRedirect.
  • Extended: Optional filters for Gateway controllers, such as ResponseHeaderModifier and RequestMirror.
  • ExtensionRef: Additional filters provided by the Gateway controller. In Traefik, these are the HTTP middlewares supported through the Middleware CRD.

!!! info "ExtensionRef Filters"

To use Traefik middlewares as `ExtensionRef` filters, the Kubernetes IngressRoute provider must be enabled in the static configuration, as detailed in the [documentation](../../providers/kubernetes-crd.md). 

For example, the following manifests configure an HTTPRoute using the Traefik AddPrefix middleware, reachable through the deployed Gateway at the http://whoami.localhost address:

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - backendRefs:
        - name: whoami
          namespace: default
          port: 80

      filters:
        - type: ExtensionRef
          extensionRef:
            group: traefik.io
            kind: Middleware
            name: add-prefix
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: add-prefix
  namespace: default
spec:
  addPrefix:
    prefix: /prefix
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoami

  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami
  ports:
    - port: 80

Once everything is deployed, sending a GET request should return the following response:

$ curl http://whoami.localhost
                                                                                                    
Hostname: whoami-697f8c6cbc-kw954
IP: 127.0.0.1
IP: ::1
IP: 10.42.2.6
IP: fe80::a460:ecff:feb6:3a56
RemoteAddr: 10.42.2.4:54758
GET /prefix/ HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.87.1-DEV
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.2.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-6b66d45748-ns8mt
X-Real-Ip: 10.42.2.1

Native Load Balancing

By default, Traefik sends the traffic directly to the pod IPs and reuses the established connections to the backends for performance purposes.

It is possible to override this behavior and configure Traefik to send the traffic to the service IP. The Kubernetes service itself does the load balancing to the pods. It can be done with the annotation traefik.io/service.nativelb on the backend Service.

By default, NativeLB is false.

!!! info "Default value"

Note that it is possible to override the default value by using the option [`nativeLBByDefault`](../../providers/kubernetes-gateway.md#nativelbbydefault) at the provider level. 
---
apiVersion: v1
kind: Service
metadata:
  name: myservice
  namespace: default
  annotations:
    traefik.io/service.nativelb: "true"
spec:
[...]

{!traefik-for-business-applications.md!}