Migrating DNS TCP Services to Connect (Service-Router)

Hi All,

So we are going through our “Mesh” journey and all our POC work looks great for regular HTTP style services (so far), but we’ve hit a migration problem on our TCP services we were hoping someone had some insight in to.

So here’s the scenario - we have Postgres (scheduled in Nomad) using Patroni to handle Leader and Read Replica scenarios. Our consuming applications would have something like this in their environment variables:

LEADER_CONN_STRING=master.postgres.service.consul
LEADER_PORT=5432
REPLICA_CONN_STRONG=replica.postgres.service.consul
REPLICA_PORT=5432

The above tags are handled by Patroni and as services change roles, then Patroni updates the service tag all under the “service name” of Postgres (in our case).

Now, as we migrate to mesh we need to route traffic coming from clients to either the leader or the replica - but since we can’t do MATCH on TCP we seem to be stuck with having to modify Patroni scripts to now register 2 service names in consul (so instead of “postgres” now we register “leader-postgres” and “replica-postgres”) which just feels wrong. Is there some routing option that will allow resolution by tag and service name that we are missing, or not understanding that would allow consul connect name resolution in the upstream to be able to send to the correct services based on the naming we have already, or is separate service names the only way?

I realize it’s a lot to type out and discuss so if I’ve glossed over anything that would be meaningful, I’d be happy to explain further.

Thanks
Ian

Hi @idrennanvmware,

You should be able to accomplish this with a service-resolver.

First create a service-resolver for the postgres service.

# postgres-service-resolver.hcl
Kind = "service-resolver"
Name = "postgres"
DefaultSubset = "primary"
Subsets = {
  "primary" = {
    filter = "\"primary\" in Service.Tags"
  }
  "replica" = {
    filter = "\"replica\" in Service.Tags"
  }
}

Then create two service-resolvers to represent the virtual services postgres-primary and postgres-replica which redirect to the appropriate service subset.

# postgres-primary-service-resolver.hcl
Kind = "service-resolver"
Name = "postgres-primary"
Redirect {
  Service = "postgres"
  ServiceSubset = "primary"
}
# postgres-replica-service-resolver.hcl
Kind = "service-resolver"
Name = "postgres-replica"
Redirect {
  Service = "postgres"
  ServiceSubset = "replica"
}

Declare postgres-primary and/or postgres-replica as upstreams for your downstream services.

I haven’t tested this exact config, but it should be close enough to what you’re looking for.

@blake thank you! Its so obvious, in hindsight, where we missed things. The virtual service is the piece of the puzzle that makes it all click.

Thanks for the fast response and good like this week at the Conf!