Upstreams and rack awareness

I’m pretty much sure that is not supported, but maybe.

Suppose I have following setup:
Kong1 - rack1
Kong2 - rack2
Kong3 - rack3

we have Service and Upstream configured, with 3 targets:
T1 - rack1
T2 - rack2
T3 - rack3

obvious desire that requests that land to Kong1 will try T1 first, this can be done with weight configuration, but configuration is shared, so it will be the same for all Kong instances.

Workaround of this, we can encode rack in upstream name and use plugin to supply the correct servers, but I’m looking if something like that is available or planed to be available in Kong.

*rack in this case could be availability group, subnet, etc ( close server(s) )

Reminds me of a similar goal we had with upstreams being DC aware maybe driven by ping/latency results but this takes that granularity to a whole new level. I had not heard this being on their(kongs) roadmap as it is very particular but an interesting idea to try and get that specific.

It is really important for fast services and cloud provides where access from one availability zone to another really impose a penalty. My lame approach to this ( in AWS context ), create 3 upstreams prefixed with availability zone, like so:

eu_east_1a_upstream

  • target1, 100
  • target2, 80
  • target3, 80

eu_east_1b_upstream

  • target2, 100
  • target1, 80
  • target3, 80

eu_east_1c_upstream

  • target3, 100
  • target2, 80
  • target1, 80

and use Kong plugin to assign upstream based on current kong instance placement, but this really makes is very verbose.

ideal would be something like that:

upstream

  • target1, eu_east_1a: 100, eu_east_1b: 80, eu_east_1c: 80
  • target2, eu_east_1a: 80, eu_east_1b: 100, eu_east_1c: 80
  • target3, eu_east_1a: 80, eu_east_1b: 80, eu_east_1c: 100
1 Like

You opensource that plugin :slight_smile: ? I could use something like that to quickly build upon it for my implementation that would leverage the right upstream for routing depending on which DC my kong node is sitting in. It’s trivial enough I could do it myself but would rather see how others did it. But yeah I do get what you are saying and it would make things a bit cleaner.

-Jeremy

it is pretty trivial, as far as plugin goes, supporting infrastructure is somewhat involved.
I can explain how that would be done in general, btw I’ll reference AWS something that I know how to deal with, I’ll assume us-west-2 as a reference.

lets define env. variable: EC2_ZONE

you will have to create custom nginx.lua and define:
env EC2_ZONE;

so in lua you can do:

local zone = os.getenv(“EC2_ZONE”)

  1. You have to deploy at least 1 instance of kong in each availability zone, in startup script you can do following:
    export EC2_ZONE=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)

  2. for the plugin, this is dumbed down:
    2.1 in config you define upstream name
    2.2 in body you do:
    local zone = os.getenv(“EC2_ZONE”)
    local name = conf.upstream_name

    – you will have to deal with “-” in zone name, like string.gsub(zone, “%-”, “x”)

    kong.service.set_upstream(zone .. "_" .. name)

  3. you will have to define upstreams and targets with different names and weights
    (this is really where your requirements lies, we use Eureka for this, so service scans Eureka and updates/syncs Kong)

We can definitely look at open sourcing this, but I’m not sure if our specific usecase is really interesting for other users.

More advanced use, you can have multi-region installation and use region(s) to have cross-region traffic, like proxy to other region if service is not available or down, it needs some infrastructure in place, but it is possible.

1 Like

Ah they made it pretty easy with the kong.service.set_upstream(zone … “_” … name) call. I wonder if we can do something similar with the individual targets too. like if (name in some env variable contains name in target hostname route to this target IF its healthy always, else route to the other one if we must because the one we want is unhealthy).

technically if we can dynamically assign weight to a target, it can be done, you would prefer closest one by differentiating the weight of the target. You will still need all targets in case some of the fail.

1 Like