Understanding Traffic Routing

    This document describes low level implementation details. For a higher level overview, check out the traffic management Concepts or .

    Unlike Kubernetes, Istio has the ability to process application level protocols such as HTTP and TLS. In general, there are three classes of protocols Istio understands:

    • HTTP, which includes HTTP/1.1, HTTP/2, and gRPC. Note that this does not include TLS encrypted traffic (HTTPS).
    • TLS, which includes HTTPS.
    • Raw TCP bytes.

    The document describes how Istio decides which protocol is used.

    The use of “TCP” can be confusing, as in other contexts it is used to distinguish between other L4 protocols, such as UDP. When referring to the TCP protocol in Istio, this typically means we are treating it as a raw stream of bytes, and not parsing application level protocols such as TLS or HTTP.

    When an Envoy proxy receives a request, it must decide where, if anywhere, to forward it to. By default, this will be to the original service that was requested, unless . How this works depends on the protocol used.

    When processing TCP traffic, Istio has a very small amount of useful information to route the connection - only the destination IP and Port. These attributes are used to determine the intended Service; the proxy is configured to listen on each service IP (<Kubernetes ClusterIP>:<Port>) pair and forward traffic to the upstream service.

    For customizations, a TCP VirtualService can be configured, which allows and routing it to different upstream services than requested.

    TLS

    When processing TLS traffic, Istio has slightly more information available than raw TCP: we can inspect the field presented during the TLS handshake.

    Additionally, custom routing can be configured with a TLS VirtualService to match on SNI and route requests to custom destinations.

    HTTP allows much richer routing than TCP and TLS. With HTTP, you can route individual HTTP requests, rather than just connections. In addition, a number of rich attributes are available, such as host, path, headers, query parameters, etc.

    While TCP and TLS traffic generally behave the same with or without Istio (assuming no configuration has been applied to customize the routing), HTTP has significant differences.

    • Requests are routed based on the port and Host header, rather than port and IP. This means the destination IP address is effectively ignored. For example, curl 8.8.8.8 -H "Host: productpage.default.svc.cluster.local", would be routed to the productpage Service.

    If traffic cannot be matched using one of the methods described above, it is treated as passthrough traffic. By default, these requests will be forwarded as-is, which ensures that traffic to services that Istio is not aware of (such as external services that do not have ServiceEntrys created) continues to function. Note that when these requests are forwarded, mutual TLS will not be used and telemetry collection is limited.

    Along with standard Services, Istio supports the full range of Kubernetes Services, with some caveats.

    LoadBalancer and NodePort Services

    These Services are supersets of ClusterIP Services, and are mostly concerned with allowing access from external clients. These service types are supported and behave exactly like standard ClusterIP Services.

    A headless Service is a Service that does not have a ClusterIP assigned. Instead, the DNS response will contain the IP addresses of each endpoint (i.e. the Pod IP) that is a part of the Service.

    In general, Istio does not configure listeners for each Pod IP, as it works at the Service level. However, to support headless services, listeners are set up for each IP:Port pair in the headless service.

    ExternalName Services

    An ExternalName Service is essentially just a DNS alias.

    Because there is no ClusterIP nor pod IPs to match on, for TCP ExternalName Services, all IPs on the port will be matched. This may prevent on the same port from being forwarded correctly. As such, it is best to avoid these where possible, or use dedicated ports when needed. HTTP and TLS do not share this constraint, as routing is done based on the hostname/SNI.

    Without Istio, the ports field of an ExternalName service is not required because the Service only represents a DNS entry. However, with Istio the port must be declared in the Service, or it will not be matched.

    In addition to Kubernetes Services, Service Entries can be created to extend the set of services known to Istio. This can be useful to ensure that traffic to external services, such as , get the functionality of Istio.

    A ServiceEntry with addresses set will perform routing just like a ClusterIP Service.

    However, for Service Entries without any addresses, all IPs on the port will be matched. This may prevent on the same port from being forwarded correctly. As such, it is best to avoid these where possible, or use dedicated ports when needed. HTTP and TLS do not share this constraint, as routing is done based on the hostname/SNI.

    The addresses field and endpoints field are often confused. addresses refers to IPs that will be matched against, while endpoints refer to the set of IPs we will send traffic to.

    For example, the Service entry below would match traffic for 1.1.1.1, and send the request to 2.2.2.2 and following the configured load balancing policy: