kubernetesmicroservicesistioistio-gateway

Expose multiple microservices with same host without LB


I have a 'UI' and an 'API' microservice that I'm deploying on k8s default namespace with Istio enabled. My k8s environment is a dev box and doesn't have an External Load Balancer.

The UI's port configuration is 80(service port):80(container port in pod).
The API's port configuration is 8000(service port):80(container port in pod)

I have to expose both these microservices for external traffic, since some people might use the 'UI' and some people might directly call the 'API' (via postman) for their requests.

When these microservices were running as simple docker containers without the k8s layer, users directly used the host.example.com for UI and host.example.com:8000/api for API calls (API calls are JSON-RPC).

I have a Gateway and VirtualService set up for both these microservices:

For UI:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: ui-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
servers:
- port:
    number: 80
    name: http
    protocol: HTTP
  hosts:
    - host.example.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ui-vs
spec:
  hosts:
  - host.example.com
  gateways:
  - ui-gateway
  http:
  - route:
    - destination:
      port:
        number: 80
      host: ui --> name of k8s svc

For API:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: api-gateway
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - host.example.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: api-vs
spec:
  hosts:
  - host.example.com
  gateways:
  - api-gateway
http:
- route:
  - destination:
      host: api -> name of api service
      port:
        number: 8000

Now going by the Istio documentation (accessing on browser) to access this UI in the browser I need to access it via ${INGRESS_HOST}:${INGRES_PORT}. In my case:

INGRESS_HOST=host.example.com
INGRESS_PORT=31165

So accessing http://host.example.com:31165 loads the UI, how do I now access the API microservice externally on host.example.com via Postman etc? The 8000 API port is not accessible from outside. I guess it all has to go via 31165, but what route do I need to use to access the API directly? What changes do I need to do for this, if any, in my set-up? I have just started with Istio.


Solution

  • Simplest solution is to combine both into one VirtualService and work with something like a path + a rewrite:

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: my-vs
    spec:
      hosts:
        - host.example.com
      gateways:
        - my-gateway
      http:
        - match:
          - uri:
              prefix: /api
          rewrite:
            uri: /
          route:
          - destination:
              host: api # -> name of api service
              port:
                number: 8000
        - match:
          - uri:
              prefix: /ui
          rewrite:
            uri: /
          route:
          - destination:
              port:
                number: 80
              host: ui # --> name of k8s svc
    

    If you query host.example.com:<nodePort>/api you'll end up at the api host, and with host.example.com:<nodePort>/ui the the ui.

    You could also use subdomains (ui.example.com:<nodePort> and api.example.com:<nodePort>) or route based on headers. Check out the docs for more examples.