Getting Started

Path Routing

API Gateways can route incoming traffic to backend services. Gloo can automatically discover backend services based on plugins that it uses that know intimate details about the platform or environment on which it’s running. In this tutorial we look at Gloo’s basic upstream discovery and routing capabilities. For more advanced function routing, take a look at the function routing tutorial.

If a gateway has no routes, Gloo will not listen on the gateway’s port.

What you’ll need

Steps

  1. The Gloo Gateway installed and running on Kubernetes.

  2. Next, deploy the Pet Store app to kubernetes:

    kubectl apply \
      --filename https://raw.githubusercontent.com/solo-io/gloo/master/example/petstore/petstore.yaml
  3. The discovery services should have already created an Upstream for the petstore service. Let’s verify this:

    glooctl get upstreams
    +--------------------------------+------------+----------+------------------------------+
    |            UPSTREAM            |    TYPE    |  STATUS  |           DETAILS            |
    +--------------------------------+------------+----------+------------------------------+
    | default-kubernetes-443         | Kubernetes | Pending  | svc name:      kubernetes    |
    |                                |            |          | svc namespace: default       |
    |                                |            |          | port:          8443          |
    |                                |            |          |                              |
    | default-petstore-8080          | Kubernetes | Accepted | svc name:      petstore      |
    |                                |            |          | svc namespace: default       |
    |                                |            |          | port:          8080          |
    |                                |            |          | REST service:                |
    |                                |            |          | functions:                   |
    |                                |            |          | - addPet                     |
    |                                |            |          | - deletePet                  |
    |                                |            |          | - findPetById                |
    |                                |            |          | - findPets                   |
    |                                |            |          |                              |
    | gloo-system-gateway-proxy-8080 | Kubernetes | Accepted | svc name:      gateway-proxy |
    |                                |            |          | svc namespace: gloo-system   |
    |                                |            |          | port:          8080          |
    |                                |            |          |                              |
    | gloo-system-gloo-9977          | Kubernetes | Accepted | svc name:      gloo          |
    |                                |            |          | svc namespace: gloo-system   |
    |                                |            |          | port:          9977          |
    |                                |            |          |                              |
    +--------------------------------+------------+----------+------------------------------+

    The upstream we want to see is default-petstore-8080. Digging a little deeper, we can verify that Gloo’s function discovery populated our upstream with the available rest endpoints it implements. Note: the upstream was created in the gloo-system namespace rather than default because it was created by a discovery service. Upstreams and virtualservices do not need to live in the gloo-system namespace to be processed by Gloo.

  4. Let’s take a closer look at the functions that are available on this upstream:

    glooctl get upstream default-petstore-8080 --output yaml
    ---
    discoveryMetadata: {}
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"service":"petstore"},"name":"petstore","namespace":"default"},"spec":{"ports":[{"port":8080,"protocol":"TCP"}],"selector":{"app":"petstore"}}}
      labels:
        discovered_by: kubernetesplugin
        service: petstore
      name: default-petstore-8080
      namespace: gloo-system
      resourceVersion: "268143"
    status:
      reportedBy: gloo
      state: Accepted
    upstreamSpec:
      kube:
        selector:
          app: petstore
        serviceName: petstore
        serviceNamespace: default
        servicePort: 8080
        serviceSpec:
          rest:
            swaggerInfo:
              url: http://petstore.default.svc.cluster.local:8080/swagger.json
            transformations:
              addPet:
                body:
                  text: '{"id": {{ default(id, "") }},"name": "{{ default(name, "")}}","tag":
                    "{{ default(tag, "")}}"}'
                headers:
                  :method:
                    text: POST
                  :path:
                    text: /api/pets
                  content-type:
                    text: application/json
              deletePet:
                headers:
                  :method:
                    text: DELETE
                  :path:
                    text: /api/pets/{{ default(id, "") }}
                  content-type:
                    text: application/json
              findPetById:
                body: {}
                headers:
                  :method:
                    text: GET
                  :path:
                    text: /api/pets/{{ default(id, "") }}
                  content-length:
                    text: "0"
                  content-type: {}
                  transfer-encoding: {}
              findPets:
                body: {}
                headers:
                  :method:
                    text: GET
                  :path:
                    text: /api/pets?tags={{default(tags, "")}}&limit={{default(limit,
                      "")}}
                  content-length:
                    text: "0"
                  content-type: {}
                  transfer-encoding: {}

    The details of this application were discovered by Gloo’s Function Discovery (fds) service. This was possible because the petstore application implements OpenAPI (specifically, discovering a Swagger JSON document at petstore-svc/swagger.json). Note that some functions were discovered. We will use these to demonstrate function routing in the next tutorial.

  5. Let’s now use glooctl to create a basic route for this upstream.

    glooctl add route \
        --path-exact /sample-route-1 \
        --dest-name default-petstore-8080 \
        --prefix-rewrite /api/pets

    We use the --prefix-rewrite to rewrite path on incoming requests to match the paths our petstore expects.

    Note that we have omitted the --name flag for selecting a virtual service. Routes are always associated with a Virtual Service in Gloo, which groups routes by their domain. Since we skipped creating a virtual service for this route, my-virtual-service will be created automatically for us.

    With glooctl, we can see that a virtual service was created with our route:

    glooctl get virtualservice --output yaml
    ---
    metadata:
      name: default
      namespace: gloo-system
      resourceVersion: "268264"
    status:
      reportedBy: gateway
      state: Accepted
      subresourceStatuses:
        '*v1.Proxy gloo-system gateway-proxy':
          reportedBy: gloo
          state: Accepted
    virtualHost:
      domains:
      - '*'
      name: gloo-system.default
      routes:
      - matcher:
          exact: /sample-route-1
        routeAction:
          single:
            upstream:
              name: default-petstore-8080
              namespace: gloo-system
        routePlugins:
          prefixRewrite:
            prefixRewrite: /api/pets
        

    Note that you can add routes interactively using glooctl add route -i. This is a great way to explore Gloo’s configuration options from the CLI.

  6. Let’s test the route /sample-route-1 using curl:

    export GATEWAY_URL=$(glooctl proxy url)
    curl ${GATEWAY_URL}/sample-route-1
    [{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

Great! our gateway is up and running. Let’s make things a bit more sophisticated in the next section with Function Routing.