Route to services external to the mesh

After you configure your route table, you can use it to forward requests to services or resources that are external to the service mesh.

In some cases, one of your Istio-managed apps might need to communicate with services that are external to the service mesh. For example, your app might need to contact a public API or an on-prem database. To route requests to services that are external to your service mesh, you assign a unique internal hostname to your external endpoint that your in-mesh services use to send requests to.

In this guide, you create Gloo Mesh ExternalEndpoint and ExternalService resources. Gloo Mesh translates these resources into an Istio ServiceEntry.

Routing to external services based on locality

For more information, see the following resources:

Before you begin

Route to external services

  1. Create a virtual gateway that selects the default Istio ingress gateway, which routes incoming traffic (north-south) to your service mesh.

    kubectl apply --context $REMOTE_CONTEXT1 -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: VirtualGateway
    metadata:
      name: ingress-gateway
      namespace: gloo-mesh
    spec:
      workloads:
        # Selects the istio ingress gateway in workload cluster 1
        - selector:
            labels:
              istio: ingressgateway
            cluster: ${REMOTE_CLUSTER1}
      listeners:
        # The port the ingress gateway listens on for incoming requests to route
        - port:
            number: 80
          http: {}
    EOF
    
  2. Save the public address of the Istio ingress gateway.

    
       export CLUSTER_1_INGRESS_ADDRESS=$(kubectl --context $REMOTE_CONTEXT1 get svc -n istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
       echo $CLUSTER_1_INGRESS_ADDRESS
       
    
       export CLUSTER_1_INGRESS_ADDRESS=$(kubectl --context $REMOTE_CONTEXT1 get svc -n istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
       echo $CLUSTER_1_INGRESS_ADDRESS
       

  3. Get the address and ports that your external resource listens on. For example, the address might be a static IP address or a registered URL.

  4. Create an external endpoint for each address and an external service. The external endpoint represents the server or service outside of your service mesh that you want to reach. By using a Gloo Mesh external service, you can then assign a unique hostname to this external endpoint that services in your mesh can use to send requests. You can also use this service to route incoming requests from your ingress gateway directly to your external endpoint.

    1. Use the address and ports to create an external endpoint resource. In these examples, two external endpoints are created for two static IP addresses that an on-prem database is exposed by.
      kubectl apply --context $REMOTE_CONTEXT1 -f- <<EOF
      apiVersion: networking.gloo.solo.io/v2
      kind: ExternalEndpoint
      metadata:
        name: db1-external-endpoint
        namespace: global
        labels:
          # Label that the external service will select
          external-endpoint: db
      spec:
        # Static IP address for on-prem service
        address: 123.45.67.8
        ports:
          - name: myport
            number: 9080
      EOF
       
      kubectl apply --context $REMOTE_CONTEXT1 -f- <<EOF
      apiVersion: networking.gloo.solo.io/v2
      kind: ExternalEndpoint
      metadata:
        name: db2-external-endpoint
        namespace: global
        labels:
          # Label that the external service will select
          external-endpoint: db
      spec:
        # Static IP address for on-prem service
        address: 123.45.67.9
        ports:
          - name: myport
            number: 9080
      EOF
      
    2. Create an external service resource to expose the external endpoint inside your mesh. In this example, you select all endpoints with the external-endpoint: db label. Note that the hosts field is not required to match the address that you specified in the external endpoint, because this host is an internal address that is used only by the gateways and services within your service mesh.
      kubectl apply --context $REMOTE_CONTEXT1 -f- <<EOF
      apiVersion: networking.gloo.solo.io/v2
      kind: ExternalService
      metadata:
        name: db-external-service
        namespace: global
      spec:
        hosts:
        # Arbitrary, internal-only hostname assigned to the endpoint
        - "my-remote-db.com"
        ports:
        - name: http
          number: 80
          protocol: HTTP
          targetPort: 9080
        selector:
          # Selects the endpoint label
          external-endpoint: db
       EOF
      
    1. Use the address and ports to create an external endpoint resource. In this example, the external endpoint can be reached by using the httpbin.org address, and the ports 80 and 443.

      kubectl apply --context $REMOTE_CONTEXT1 -f- <<EOF
      apiVersion: networking.gloo.solo.io/v2
      kind: ExternalEndpoint
      metadata:
        name: httpbin-external-endpoint
        namespace: global
        labels:
          # Label that the external service will select
          external-endpoint: httpbin
      spec:
        # Registered URL for external service
        address: httpbin.org
        ports:
          - name: http
            number: 80
          - name: https
            number: 443
      EOF
      
    2. Create an external service resource to expose the external endpoint inside your mesh. In this example, you select all external endpoints with the external-endpoint: httpbin label. Note that the hosts field is not required to match the address that you specified in the external endpoint, because this host is an internal address that is used only by the gateways and services within your service mesh.

      kubectl apply --context $REMOTE_CONTEXT1 -f- <<EOF
      apiVersion: networking.gloo.solo.io/v2
      kind: ExternalService
      metadata:
        name: httpbin-external-service
        namespace: global
      spec:
        hosts:
        # Arbitrary, internal-only hostname assigned to the endpoint
        - "my-remote-svc.com"
        ports:
        - name: http
          number: 80
          protocol: HTTP
        selector:
          # Selects the endpoint label
          external-endpoint: httpbin
       EOF
      

  5. Create a route table to route requests to the external service. A route table allows you to define how requests to endpoints should be routed, and is translated to the Istio VirtualService resource. In this example route table, all requests to the /httpbin path are routed to the endpoints that back the httpbin-external-service.

    
       kubectl apply --context $REMOTE_CONTEXT1 -n global -f- <<EOF
       apiVersion: networking.gloo.solo.io/v2
       kind: RouteTable
       metadata:
         name: db-routes
         namespace: global
       spec:
         # Applies to any host; can indicate a specific host
         hosts:
           - '*'
         # Selects the virtual gateway you previously created
         virtualGateways:
           - name: ingress-gateway
             namespace: gloo-mesh
             cluster: ${REMOTE_CLUSTER1}
         http:
           # Route for the db-external-service
           - name: db-app
             # Prefix matching
             matchers:
             - uri:
                 prefix: /db
             # Forwarding directive
             forwardTo:
               destinations:
                 # Reference to the external service exposing your external endpoints
                 - ref:
                     name: db-external-service
                   kind: EXTERNAL_SERVICE
       EOF
       
    
       kubectl apply --context $REMOTE_CONTEXT1 -n global -f- <<EOF
       apiVersion: networking.gloo.solo.io/v2
       kind: RouteTable
       metadata:
         name: httpbin-routes
         namespace: global
       spec:
         hosts:
           - '*'
         # Selects the virtual gateway you previously created
         virtualGateways:
           - name: ingress-gateway
             namespace: gloo-mesh
             cluster: ${REMOTE_CLUSTER1}
         http:
           # Route for the httpbin-external-service
           - name: httpbin-app
             # Prefix matching
             matchers:
             - uri:
                 prefix: /httpbin
             # Forwarding directive
             forwardTo:
               destinations:
                 # Reference to the external service exposing your external endpoints
                 - ref:
                     name: httpbin-external-service
                   kind: EXTERNAL_SERVICE
       EOF
       

  6. Test the route to your external resource by curling the ingress gateway address and path. For example, the following command appends /httpbin for the external httpbin app.

    curl http://$CLUSTER_1_INGRESS_ADDRESS/httpbin
    

Next steps