Light Dark Auto

Add an Upstream to a Service

Introduction

Upstreams exist at the very bottom of the application networking object hierarchy. They represent a networked set of hosts that requests get proxied to.

This guide will walk you through adding an upstream to both a TCP and an HTTP listener. This guide will also showcase the two types of upstream host resolution: static and discovered. By the end, you will have a service with a new upstream, either by itself, or in a collection of upstreams in the case of traffic shaping.

Prerequisites

  • A GSL service file

Add an Upstream

Upstreams have two possible attachment points: HTTP and TCP Listeners. For HTTP listeners, they attach to routes and for TCP listeners they attach directly to the listener object.

HTTP Listener

Inside the routes template for the listener, locate the route path that needs an upstream and add the upstream field if it does not already exist:

...
routes: {
    "<route path>": {
        ...
        upstreams: {

        }
    }
}

Just like the ingress/egress and routes field, and upstream is a template struct. Each key-value pair defines a new upstream on that route. Routes with multiple upstreams allow for advanced traffic shaping patterns like Blue-Green deployments.

Define a new upstream by adding its name as a key to the template( leave the name empty for now):

upstreams: {
    "": {
        gsl.Upstream

    }
    ...
}

TCP Listener

Since TCP listeners can only reference one upstream, make sure to create a new one. Inside the listener object, add the upstream field (leave the name empty for now):

"<tcp listener name>": {
    ...
    upstream: {
        name: ""
    }
}

Configure the Upstream Host

Greymatter exposes two different types of host resolution: Service Discovery and Static. Static resolution refers to using a known and unchanging IP address (or DNS record). Discovered resolution uses service discovery to find new instances of a particular service. Upstreams can enable one or the other.

Service Discovery

To discover the host, you need to set two values:

  • the upstream name to the name of the application found in the Kubernetes manifest.
  • the upstream namespace field to the namespace of the application.

For an HTTP listener:

upstreams: {
    "<Name of the application>": {
        gsl.#Upstream
        namespace: "<namespace of the application>"
        ...
    }
}

For a TCP listener:

upstream: {
  gsl.#Upstream
  name: '<name of the application>'
  namespace: '<namespace of the application>'
  ...
}

Static

Static host addresses get placed in the instances list.

For HTTP:

upstreams: {
    "<any name>": {
        gsl.#Upstream
        instances: [{ host: "<host address>", port: "<host port>" }]
    }
}

And for TCP:

upstream: {
  gsl.#Upstream
  name: '<any name>'
  instances: [{host: '<host address>', port: '<host port>'}]
}

When defining static host addresses, the name of the upstream does not matter. It only matters in the case of service discovery.

Conclusion

You now have a basic configured upstream on either an HTTP or TCP listener pointing to some hosts through service discovery or static addresses. At this point, you can continue configuring the upstream with security policies, changing load balancing policies, or use traffic shaping with multiple upstreams.

Next Steps

Reference