Predominantly, Kubernetes has used an Ingress controller to handle the traffic that enters the cluster from the outside. Istio has replaced all the familiar Ingress resource with new Gateway and VirtualServices resources. They work in sync to route all the traffic into the mesh. Inside the mesh there is no requirement for Gateways since the services can access each other by a cluster local service name.

Let’s understand the working with a representation

Istio Ingress Gateway in Kubernetes No Title

  • Firstly A request is made by a client on a specific port
  • Then a load balancer on this port listens and forwards the request to one of the workers in theh cluster on same or a new port
  • Inside the cluster the request is routed to the Istio Ingress Gateway which is listened on the port of the load balancer
  • The Service forwards the requestto an Istio Ingress Gateway Pod which is managed by a deployment
  • The Ingress Gateway Pod is configured by a Gateway and a VirtualService.
  • The Gateway configures all the ports, protocol, and certificates.
  • The Virtual Service configures all the routing information to find the correct Servicein it.
  • The Istio Ingress Gateway Pod routes the request to the application Service.
  • And lastly, the application Service routes the request to an application Pod which is managed by a deployment.

    Ingress Gateway Service

    The Ingress Gateway Service must listen to all the ports to be able to forward the traffic to the Ingress Gateway pods. Here we will be using routing to bring all the port numbers back to their initial state.

    Note that a Kubernetes Service is not a real service, but, since we are using type: "NodePort", all the request will be handled by the kube-proxy provided by Kubernetes and forwarded to a node with a current running pod. Once on the node, an IP-tables is configured a request will be forwarded to the appropriate pod.

    1# From the istio-ingressgateway service
    2 ports:
    3 - name: http2
    4 nodePort: 30000
    5 port: 80
    6 protocol: TCP
    7 - name: https
    8 nodePort: 30443
    9 port: 443
    10 protocol: TCP
    11 - name: mysql
    12 nodePort: 30306
    13 port: 3306
    14 protocol: TCP

    If we inspect the service, we will see that it defines more ports than we have describe above. So these ports will be used for all the internal Istio communication.

    Ingress Gateway Deployment

    It's a wrapper around the Envoy proxy and it is configured as the sidecars used inside the service mesh. When a Gateway or VirtualService gets changed, they are detected by the Istio Pilot controller and converts this information to an Envoy configuration and sends it to all the proxies, including the Envoy inside the IngressGateway.

    Since container ports are not supposed to be declared in Kubernetes pods, we don't have to declare the ports in the Ingress Gateway Deployment. If we look inside the deployment we can see that there are a number of ports that are already declared anyway. We have to take care about the Ingress Gateway Deployment in SSL certificates. To access the certificates inside the Gateway resources, make sure that we have mounted all the required certificates properly.

    1# Example represents volume mounts
    2volumeMounts:
    3- mountPath: /etc/istio/ingressgateway-certs
    4 name: ingressgateway-certs
    5 readOnly: true
    6- mountPath: /etc/istio/ingressgateway-ca-certs
    7 name: ingressgateway-ca-certs
    8 readOnly: true
    9
    10# Example represents volumes
    11volumes:
    12- name: ingressgateway-certs
    13 secret:
    14 defaultMode: 420
    15 optional: true
    16 secretName: istio-ingressgateway-certs
    17- name: ingressgateway-ca-certs
    18 secret:
    19 defaultMode: 420
    20 optional: true
    21 secretName: istio-ingressgateway-ca-certs

    The Gateway

    The Gateway resources are used to configure the ports for Envoy and also support for the Kubernetes Ingress. Since all the three ports are exposed with the servies, we need these ports to be handled by the Envoy. It can be handled by declaring one or more Gateways.

    1apiVersion: networking.istio.io/v1alpha3
    2kind: Gateway
    3metadata:
    4 name: default-gateway
    5 namespace: istio-system
    6spec:
    7 selector:
    8 istio: ingressgateway
    9 servers:
    10
    11 - hosts:
    12 - '*'
    13 port:
    14 name: http
    15 number: 80
    16 protocol: HTTP
    17
    18 - hosts:
    19 - '*'
    20 port:
    21 name: https
    22 number: 443
    23 protocol: HTTPS
    24 tls:
    25 mode: SIMPLE
    26 privateKey: /etc/istio/ingressgateway-certs/tls.key
    27 serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
    28
    29 - hosts: # For all the TCP routing this fields will be ignored, but it will be matched
    30 - '*' # with the VirtualService, We use * since it will match anything.
    31 port:
    32 name: mysql
    33 number: 3306
    34 protocol: TCP

    VirtualService

    The last interesting resource we have is the VirtualService, it used in concert with the Gateway to configure Envoy.

    A general configuration for an HTTP(s) service

    1apiVersion: networking.istio.io/v1alpha3
    2kind: VirtualService
    3metadata:
    4 name: counter
    5spec:
    6 gateways:
    7 - default-gateway.istio-system.svc.cluster.local
    8 hosts:
    9 - counter.lab.example.com
    10 http:
    11 - match:
    12 - uri:
    13 prefix: /
    14 route:
    15 - destination:
    16 host: counter
    17 port:
    18 number: 80

    Application Service and Deployment

    The request have now reached the application service and deployment. These are normal Kubernetes resources.

    Extras:

    Debugging Istio Gateway

    First we will use istioctl to check the configuration status of Istio Ingress Gateway:

    1# istioctl proxy-status istio-ingressgateway-5586f47659-r64lb.istio-system
    2Clusters Match
    3Listeners Match
    4Routes Match

    If anything does not get synced with it, try restarting the ingress gateway pod once - it may be possible that it somehow an update got missed. If RDS looked good, we can check access logs of it.

    1#kubectl get configmap istio -n istio-system -o yaml | grep "accessLogFile: "
    2disable access log.\naccessLogFile: \"/dev/stdout\"\n\n# If accessLogEncoding

    Once all the access logs are enabled, we can try torequest a few more times and check the logs on the Ingress Gateway:

    1# kubectl logs -n istio-system istio-ingressgateway-5586f47659-r64lb | grep -v deprecated

    Related Resources

    Layer5, the cloud native management company

    An empowerer of engineers, Layer5 helps you extract more value from your infrastructure. Creator and maintainer of service mesh standards. Maker of Meshery, the cloud native management plane.