deis/router

Support non-HTTP, streaming apps

mh0pe opened this issue · 2 comments

mh0pe commented

It would be really beneficial to opt into stream mode like the Deis Builder does for an app, allowing protocols like FTP and SFTP to function within Deis.

I hate saying that something isn't possible, but this probably isn't.

Nevermind that the router's implementation utilizes Nginx (that's just a detail), the router, just like a proper ingress controller routes traffic based on hostnames that are determined by looking at the HTTP Host header. This is, obviously, a specific feature of the HTTP protocol.

Other protocols, e.g. FTP, SFTP, SMTP, etc., etc. (none of which I am as familiar with as I am with HTTP, if I am being honest) might have analogous mechanisms for performing hostname-based routing, but I believe, if I'm interpreting your request correctly, you don't want support for specific protocols-- you want support for any/all protocols.

To deliver on that would require routing traffic at L4 (i.e. routing TCP packets). TCP has no header for conveying hostname.

There is a really crappy workaround for getting around the above, and in fact, it is what the router does with builder traffic. The router listens on port 2222 and streams all packets received on that port to the builder. But this workaround doesn't scale...

If we wanted to apply a workaround like that, we'd be faced with two problems:

  1. The router would have to listen on a new port for every non-HTTP app, and there's no (easy?) way to dynamically expose new ports on a running pod (e.g. the router's pod(s)) or the Kubernetes services for which those pods are endpoints (i.e. the router's service).

  2. Even if we jumped through hoops to solve for the first issue, the fact remains that for every non-HTTP app, the router would be listening on a new/dedicated port. That would mean all clients connecting to those apps via the router would have to somehow be aware of the port number on which the router listens for traffic for their application. (Again, recall that the router works with the builder in this way. Note that the git remote for any workflow application is explicitly configured to talk to port 2222.) At this point, because clients would need special knowledge of what port to talk to, the router would cease to be transparent to application clients.

fwiw, the problems I have articulated are, afaik, the very reason that Kubernetes ingress controllers function only at L7 (application layer) and not L4 (transport layer). How to solve this elegantly is an unsolved problem for the entire k8s community...

And having said that, it would be better to solve this in k8s than in the router, as we're currently divesting from feature development in the router and beginning to encourage use of ingress controllers instead. (Recent releases of Workflow include an experimental "bring your own ingress controller" mode.)

Lastly, since I don't want to leave you hanging, I'll tell you how I'd personally handle cases such as yours. I'd mark the application as unroutable and I'd create a new, dedicated service for the application of type: LoadBalancer.

$ deis routing:disable

https://deis.com/docs/workflow/applications/domains-and-routing/

I hope this help a bit. And of course, if you have some insight into how this could be accomplished more elegantly, I am totally happy to hear it.

@MadisonHope, I'm going to close this issue, but if you think I've been hasty in doing so, please feel free to re-open and add some comments.