Original link: Gateways in Istio service grid

In a typical grid, there is usually one or more load balancers (we call them gateways) that are used to terminate external TLS links and bring traffic to the grid. The traffic then flows through the internal service through the Sidecar gateway. It is also common for applications to use external services (such as accessing the Google Maps API), and in some cases these external services may be invoked directly; However, in some deployments, all traffic in the grid that accesses external services may be forced through a dedicated Egress Gateway. The following diagram depicts the use of gateways in a grid.

Gateway is a platform-independent abstraction for modeling the traffic flowing into a dedicated intermediate device. The following figure describes the control flow across multiple configured resources.

1.The Gateway is introduced

Gateway is used to configure a load balancer for HTTP/TCP traffic, regardless of where the load balancer will run. Any number of gateways can exist in the grid, and multiple different Gateway implementations can coexist. In fact, by specifying a set of workload (Pod) tags in the configuration, you can bind the Gateway configuration to a specific workload, allowing users to reuse off-the-shelf network devices by writing simple Gateway Controllers.

For inbound traffic management, you might ask: why not just use the Kubernetes Ingress API? The reason is that the Ingress API cannot express Istio routing requirements. Ingress tries to get a common intersection between different HTTP proxies, so it can only support the most basic HTTP routing, which ultimately results in the need to put other advanced features of the proxy into annotations that are incompatible and not portable across multiple proxies.

Istio Gateway overcomes these disadvantages of Ingress by separating the L4-L6 configuration from the L7 configuration. Gateway is only used to configure L4-L6 functions (for example, public ports, TLS configurations), which are implemented in a uniform manner by all major L7 agents. You can then use standard Istio rules to control HTTP and TCP traffic into the Gateway by binding VirtualService to the Gateway.

For example, the following simple Gateway configures a Load Balancer to allow HTTPS external traffic to host bookinfo.com to enter the grid:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - bookinfo.com
Copy the code

To configure a route for the traffic entering the Gateway, you must define a VirtualService for the same host (refer to the previous blog) and use the Gateways field in the configuration to bind it to the Gateway defined above:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
    - bookinfo.com
  gateways:
  - bookinfo-gateway # <---- bind to gateway
    http:
  - match:
    - uri:
        prefix: /reviews
    route:
    .
Copy the code

The Gateway can be used to model edge agents or purely internal agents, as shown in the first figure. All gateways can be configured and controlled the same way, regardless of location.

An example shows how to configure Istio to expose services outside the service grid using the Istio Gateway.

2.Configure the Ingress using the Istio gateway

Let’s look at how to configure traffic for the Gateway on HTTP 80 port.

  1. Create an Istio Gateway

    $ cat <<EOF | istioctl create -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: httpbin-gateway
    spec:
      selector:
        istio: ingressgateway # use Istio default gateway implementation
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "httpbin.example.com"
    EOF    
    Copy the code
  2. Configure routes for incoming traffic through the Gateway

    $ cat <<EOF | istioctl create -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
    spec:
      hosts:
      - "httpbin.example.com"
      gateways:
      - httpbin-gateway
      http:
      - match:
        - uri:
            prefix: /status
        - uri:
            prefix: /delay
        route:
        - destination:
            port:
              number: 8000
            host: httpbin
    EOF
    Copy the code

    Here, we create a VirtualService configuration httpbin for the service, which contains two routing rules that allow path /status and path traffic /delay.

    The list of gateways specifies that only httpbin-gateway is allowed by our request. All other external requests will be rejected and a 404 response will be returned.

    Note that in this configuration, internal requests from other services in the grid are not subject to these rules and simply default to circular routing. To apply these (and other rules) to internal calls, we can add the special value mesh to the gateways list.

  3. Use curl to access the httpbin service.

    First get the IP address and port of the Ingress Gateway. Refer to the previous article: Istio Traffic Management

    $ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/status/200 HTTP/1.1 200 OK server: Envoy Date: Thu, 02 Aug 2018 04:18:41 GMT Content-type: text/ HTML; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials:true
    content-length: 0
    x-envoy-upstream-service-time: 9
    Copy the code

    Notice that we use the -h flag to set the Host HTTP Header to “httpbin.example.com”. This was necessary because our ingress Gateway was configured to handle “httpbin.example.com”, but in our test environment we did not have a DNS binding for that host and simply sent our requests to the Ingress IP.

  4. Access any other URL that is not explicitly exposed. You should see an HTTP 404 error:

    $ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
    
    HTTP/1.1 404 Not Found
    date: Thu, 02 Aug 2018 04:21:39 GMT
    server: envoy
    transfer-encoding: chunked
    Copy the code

3.Use a browser to access the Ingress service

If you want to enter the URL of the httpbin service in the browser to access it, it won’t work because there is no way to tell the browser to pretend to access httpbin.example.com like using curl, You can only solve this problem by adding hosts to the /etc/hosts file.

However, in this case, even if you add hosts, you still cannot access it, because the Istio Gateway uses NodePort mode, instead of exposing ports 80 and 443, and if we want to access the service by domain name, The Gateway must be required to expose ports 80 and 443.

Therefore, we can only save the country by modifying the Deployment of Ingress Gateway, configure ports 80 and 443 as hostPort mode, and then dispatch Gateway to a fixed host through Node affinity.

$ kubectl -n istio-system edit deployment istio-ingressgateway
Copy the code
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: istio-ingressgateway
  namespace: istio-system
  .
spec:
  .
  template:
    .
    spec:
      affinity:
        nodeAffinity:
          .
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - 192.168123.248.   Let's say you want to schedule to this host
      containers:
        - name: ISTIO_META_POD_NAME
        .
        - containerPort: 80
          hostPort: 80
          protocol: TCP
        - containerPort: 443
          hostPort: 443
          protocol: TCP
        .
Copy the code

Save and exit, wait for the Gateway Pod to reschedule, and then add a hosts to your browser’s local computer:

192.168.123.248 httpbin.example.com
Copy the code

Reconfigure VirtualService:

$  cat <<EOF | istioctl replace -f -
 apiVersion: networking.istio.io/v1alpha3
 kind: VirtualService
 metadata:
   name: httpbin
 spec:
   hosts:
   - "httpbin.example.com"
     gateways:
   - httpbin-gateway
     http:
   - match:
     - uri:
         prefix: /status
     - uri:
         prefix: /delay
     - uri:
         prefix: /headers
     route:
     - destination:
         port:
           number: 8000
         host: httpbin
 EOF
Copy the code

You can input URL:http://httpbin.example.com/headers in the browser to access the service!

4.Clean up the

Delete Gateway, VirtualService, and Httpbin services:

$ istioctl delete gateway httpbin-gateway
$ istioctl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml
Copy the code

5.reference

  • Control Ingress traffic
  • Gateway