Route to external services

You can use the routing and traffic management capabilities in Gloo Gateway to route incoming requests to an endpoint that is outside your cluster, such as an on-prem database, by using Gloo ExernalService and ExternalEndpoint custom resources.

In this guide, you can choose between allowing traffic routing to an IP address, CIDR, or hostname directly or configuring an internal DNS entry to group multiple external endpoints behind one common IP address or hostname. The solution that is right for you depends on your use case. Make sure to review the Routing to external services concept doc for more information.

For additional information about the Gloo custom resources, see the following resources:

Gloo Gateway uses plaintext to route the request to your external endpoint. To secure communications with mTLS instead, consider using Gloo Mesh Enterprise alongside Gloo Gateway. With Gloo Mesh, you can onboard external endpoints, such as VMs, to an Istio service mesh and secure connections via mTLS.

Before you begin

  1. Install Gloo Gateway.
  2. Configure an HTTP or HTTPS listener on your ingress gateway.
  3. Follow the other guides in this routing section to plan your routing table setup. For example, you might check out the path matching guide to decide how to match the incoming requests to your service paths, the redirect guide to set up any path or host rewrites, or the sub-table delegation guide to nest and sort multiple route tables. Note: Be sure that each route for one host is unique, such as by using prefix matching to determine which requests to the host should be forwarded to which destinations.
  4. Decide on the approach to allow routing to an external service. You can choose between the following options:
    1. Allow routing to an IP address, CIDR, or hostname directly.
    2. Create internal DNS entries for multiple external endpoints.

Allow routing to an IP address, CIDR, or hostname directly

You can allow routing to an external static IP address, CIDR range, or hostname from services in your mesh by using an ExternalService Gloo custom resource.

  1. Get the addresses and ports that your external resources listen on. For example, the address might be a static IP address, a CIDR range, or a registered hostname.

  2. Create an external service resource with either the addresses or hostname option. Note that you cannot specify a hostname and an IP address or CIDR in the same external service resource.

    kubectl apply -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: ExternalService
    metadata:
      name: db-external-service
      namespace: global
    spec:
      addresses:
      # Static IP address or CIDR
      - 123.221.3.0
      - 144.222.1.6/16
      ports:
      - name: http
        number: 80
        protocol: HTTP
      selector: {}
    EOF
    
    kubectl apply -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: ExternalService
    metadata:
      name: db-external-service
      namespace: global
    spec:
      hosts:
      - "my-remote-db.com"
      ports:
      - name: http
        number: 80
        protocol: HTTP
      selector: {}
    EOF
    

  3. Create a route table to allow routing to the external service.

    kubectl apply -n global -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: RouteTable
    metadata:
      name: db-routes
      namespace: global
    spec:
      hosts:
        - '*'
      virtualGateways:
        - name: istio-ingressgateway
          namespace: bookinfo
          cluster: ${CLUSTER_NAME}
      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 resource exposing your external endpoints
            - ref:
                name: db-external-service
                cluster: $CLUSTER_NAME
              kind: EXTERNAL_SERVICE
            pathRewrite: /
    EOF
    
  4. Save the external address of the ingress gateway.

    export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo $INGRESS_GW_IP
    
    export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    echo $INGRESS_GW_IP
    

  5. Test the route to your external resource by curling the ingress gateway address and path. For example, the following command appends /db/ to the ingress gateway IP address.

    curl http://$INGRESS_GW_IP/db/
    

Create internal DNS entries for multiple external endpoints

Instead of allowing specific IP addresses, CIDR ranges, or hostnames directly, you can set up an internal hostname or IP address that serves multiple external endpoints and therefore works similarly to setting up a CNAME or A record in your DNS provider. To do that, you use ExternalEndpoint custom resources to define the external endpoints. Then, you define the internal hostname or IP address that Gloo Gateway uses to route traffic to any of these endpoints in the ExternalService resource.

  1. 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.

  2. Create an external endpoint for each address and an external service. The external endpoint represents the server or service outside of your cluster that you want to reach. By using a Gloo Gateway external service, you can then assign a unique hostname to this external endpoint that Gloo Gateway can use to route incoming requests 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 -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 1
        address: 123.45.67.8
        ports:
          - name: myport
            number: 9080
      EOF
       
      kubectl apply -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 2
        address: 123.45.67.9
        ports:
          - name: myport
            number: 9080
      EOF
      
    2. Create an external service resource to expose the external endpoint inside your Gateway clusters. 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 Gloo Gateway.
      kubectl apply -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:
            number: 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 -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 Gateway clusters. 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 Gloo Gateway.

      kubectl apply -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
      

  3. Create a route table to route requests to the external service.

    In this example route table, all requests to the /db/ path are routed to the endpoints that back the db-external-service.

    kubectl apply -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: istio-ingressgateway
          namespace: bookinfo
          cluster: ${CLUSTER_NAME}
      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 resource exposing your external endpoints
            - ref:
                name: db-external-service
                cluster: $CLUSTER_NAME
              kind: EXTERNAL_SERVICE
            pathRewrite: /
    EOF
    

    In this example route table, all requests to the /httpbin/ path are routed to the endpoints that back the httpbin-external-service.

    kubectl apply -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: istio-ingressgateway
          namespace: bookinfo
          cluster: ${CLUSTER_NAME}
      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 resource exposing your external endpoints
            - ref:
                name: httpbin-external-service
                cluster: $CLUSTER_NAME
              kind: EXTERNAL_SERVICE
            pathRewrite: /
    EOF
    

  4. Save the external address of the ingress gateway.

    export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo $INGRESS_GW_IP
    
    export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    echo $INGRESS_GW_IP
    

  5. 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://$INGRESS_GW_IP/httpbin
    

Next steps