Consul Services

Gloo’s service discovery leverages existing registry or catalog implementations. A widely deployed service for registering and discovery services is HashiCorp Consul. If your services already register into Consul, we can use Gloo to read the service catalog from Consul and discover these services automatically.

When services registered into Consul require a bit more fine-grained grouping and routing, Gloo can do that too.

Configuring Gloo to Discover from Consul

Gloo can automatically discover Upstreams from Consul. You can also explicitly create upstreams from Consul.

To enable automatic discovery of Consul services, update your gloo.solo.io.Settings resource and add the consul section:

kubectl patch settings -n gloo-system default \
    --patch '{"spec": {"consul": {"address": "gloo-consul-server.default:8500", "serviceDiscovery": {}}}}' --type=merge
apiVersion: gloo.solo.io/v1
kind: Settings
metadata:
  labels:
    app: gloo
  name: default
  namespace: gloo-system
spec:
  consul:
    address: gloo-consul-server.default:8500
    serviceDiscovery: {}
  discovery:
    fdsMode: WHITELIST

    ...
    ...

If you have Discovery enabled, Gloo will automatically discover upstreams from the Consul cluster. After enabling this setting, go check your upstreams:


kubectl get upstream -n gloo-system

glooctl get upstreams

Explicitly creating consul upstreams

Even if you opt not to automatically discovery upstreams from Consul (ie, you disable Discovery), you can create them explicitly. You still need the Consul server settings in the settings configuration for Gloo.


apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
  name: jsonplaceholder
  namespace: gloo-system
spec:
  consul:
    serviceName: jsonplaceholder
    serviceTags:
    - gloo
    - jsonplaceholder

glooctl create upstream consul --name jsonplaceholder \
--consul-service jsonplaceholder --consul-service-tags gloo,jsonplaceholder

Routing to Consul upstreams

A single Consul service usually maps to several service instances, which can have distinct sets of tags, listen on different ports, and live in multiple data centers. To give a concrete example, here is a simplified response you might get when querying Consul for a service with a given name:

[
  {
    "ServiceID": "32a2a47f7992:nodea:5000",
    "ServiceName": "my-db",
    "Address": "192.168.1.1",
    "Datacenter": "dc1",
    "ServicePort": 5000,
    "ServiceTags": [
      "primary"
    ]
  },
  {
    "ServiceID": "42a2a47f7992:nodeb:5001",
    "ServiceName": "my-db",
    "Address": "192.168.1.2",
    "Datacenter": "dc1",
    "ServicePort": 5001,
    "ServiceTags": [
      "secondary"
    ]
  },
  {
    "ServiceID": "52a2a47f7992:nodec:6000",
    "ServiceName": "my-db",
    "Address": "192.168.2.1",
    "Datacenter": "dc2",
    "ServicePort": 6000,
    "ServiceTags": [
      "secondary"
    ]
  }
]

If the ports and data centers for all of the endpoints for a Consul service are the same, and you don’t need to slice and dice them up into finer-grained subsets, you can just use Upstreams like you do with any other service to which to route.

Example:

apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: default
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    routes:
    - matchers:
      - prefix: /todos      
      routeAction:        
        single:
          upstream:
            name: jsonplaceholder
            namespace: gloo-system

Also, with using Upstreams instead of the consul-specific config, you can also leverage the fact that Gloo does function discovery (ie, REST or gRPC based on swagger or reflection respectively).

Subset based routing

If you have subsets within the Consul registry for a particular service, you can target them very specifically with the consul destination type settings. This allows you to target a subset of these service instances via the optional tags and dataCenters fields. Gloo will detect the correspondent IP addresses and ports and load balance traffic between them.

If the ports and data centers for all of the endpoints for a Consul service are the same, and you don’t need to slice and dice them up into finer-grained subsets, you can just use Upstreams like you do with any other service to which to route. Also, with using Upstreams instead of the consul-specific config, you can also leverage the fact that Gloo does function discovery (ie, REST or gRPC based on swagger or reflection respectively).

When providing the tags option, Gloo will only match service instances that exactly match the given tag set.

For example, the following configuration will forward all matching requests to the second and third service instances,

routes:
- matchers:
   - prefix: /db
  routeAction:
    single:
      consul:
        serviceName: my-db
        tags:
        - secondary

while this next example will forward the same requests only to the first two instances (the ones in data center dc1)

routes:
- matchers:
   - prefix: /db
  routeAction:
    single:
      consul:
        serviceName: my-db
        dataCenters:
        - dc1

Finally, not specifying any optional filter fields will cause requests to be forwarded to all three service instances:

routes:
- matchers:
   - prefix: /db
  routeAction:
    single:
      consul:
        serviceName: my-db

As is the case with Subsets, Gloo will fall back to forwarding the request to all available service instances if the given criteria do not match any subset of instances.