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 services in the mesh use to route traffic to these endpoints in the ExternalService resource.

The example in this guide assumes that you want to make www.solo.io available to the services in the service mesh by using a common internal hostname, www.example.com.

Before you begin

  1. Complete the multicluster getting started guide to set up the following testing environment.

    • Three clusters along with environment variables for the clusters and their Kubernetes contexts.
    • The Gloo meshctl CLI, along with other CLI tools such as kubectl and istioctl.
    • The Gloo management server in the management cluster, and the Gloo agents in the workload clusters.
    • Istio installed in the workload clusters.
    • A simple Gloo workspace setup.
  2. Install Bookinfo and other sample apps.
  3. Decide on the outbound traffic policy for your service mesh. If you followed the steps to install Istio with the Istio lifecycle manager, the outbound traffic policy for your service mesh is set to ALLOW_ANY by default and allows your services in the mesh to reach any external endpoint. You can change this setting and instead block all egress traffic to hosts that are not part of your service mesh by changing the outbound traffic policy to REGISTRY_ONLY as shown in the following steps. Note that if you manually installed Istio, follow the steps in Upgrade Istio to update that setting.

    1. Open the gm-istiod-values.yaml file that you used to create the istiod control plane.
    2. Change the outboundTrafficPolicy field to REGISTRY_ONLY.
    3. Apply your changes by using the following command.
        kubectl apply -f gm-istiod-values.yaml --context $MGMT_CONTEXT
        

Create an internal DNS entry for external endpoints

  1. Log in to the reviews app and verify that you cannot reach www.solo.io.

      kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=reviews -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -vik www.solo.io
      

    Example output:

      * Mark bundle as not supporting multiuse
    < HTTP/1.1 502 Bad Gateway
    HTTP/1.1 502 Bad Gateway
    < date: Thu, 11 May 2023 17:07:43 GMT
    date: Thu, 11 May 2023 17:07:43 GMT
    < server: envoy
    server: envoy
    < content-length: 0
    content-length: 0
      
  2. Create the global namespace in the management cluster.

      kubectl create namespace global --context $MGMT_CONTEXT
      
  3. Create an external endpoint resource for www.solo.io. The external endpoint represents the server or service outside of your service mesh that you want to reach. You later use the external service to assign a unique hostname to this external endpoint that services in your mesh can use to send requests to. For more information, see the API reference for ExternalEndpoint.

      kubectl apply --context $MGMT_CONTEXT -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: ExternalEndpoint
    metadata:
      name: solo
      namespace: global
      labels:
        # Label that the external service will select
        external-endpoint: solo
    spec:
      # Hostname address of the external service
      address: www.solo.io
      ports:
        - name: http
          number: 80
    EOF
      
  4. Create an external service resource to expose the external endpoint inside your mesh. In this example, you select all endpoints with the external-endpoint: solo 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 proxies and services within your service mesh. For more information, see the API reference for ExternalService.

      kubectl apply --context $MGMT_CONTEXT -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: ExternalService
    metadata:
      name: solo-service
      namespace: global
    spec:
      hosts:
      # Arbitrary, internal-only hostname assigned to the endpoint
      - "www.example.com"
      ports:
      - name: http
        number: 80
        protocol: HTTP
        targetPort: 
          number: 80
      selector:
        # Selects the endpoint label
        external-endpoint: solo
    EOF
      
  5. Log in to the reviews app again and verify that you are now able to reach www.solo.io via the internal www.example.com domain name.

      kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=reviews -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -vik www.example.com
      

    Example output:

      * Connected to www.example.com (240.240.105.9) port 80 (#0)
    > GET / HTTP/1.1
    > Host: www.example.com
    > User-Agent: curl/8.0.1-DEV
    > Accept: */*
    > 
    < HTTP/1.1 200 OK
    < content-length: 4815
    < content-type: text/html; charset=UTF-8
    < server: envoy
    < x-pantheon-styx-hostname: styx-fe4-a-65bfb7c97b-2dqwz
    < x-styx-req-id: 4957c993-f323-11ed-ad4c-9a97f73604cc
    < date: Mon, 15 May 2023 13:20:39 GMT
    < x-served-by: cache-chi-kigq8000059-CHI, cache-iad-kcgs7200147-IAD
    < x-cache: MISS, MISS
    < x-cache-hits: 0, 0
    < x-timer: S1684156840.809399,VS0,VE83
    < vary: Accept-Encoding, Cookie, Cookie
    < age: 0
    < accept-ranges: bytes
    < via: 1.1 varnish, 1.1 varnish
    < x-envoy-upstream-service-time: 86
    ...
      
  6. Optional: Remove the resources that you created as part of this guide.

      kubectl delete externalendpoint solo -n global --context $MGMT_CONTEXT
    kubectl delete externalservice solo-service -n global --context $MGMT_CONTEXT
    kubectl delete ns global --context $MGMT_CONTEXT