Exposing multiple ports from within a ManagedVM

2019-04-10 05:34发布

问题:

I'm using the Managed VM functionality to run a WebSocket server that I'd like to expose to the Internet on any port (preferably port 80) through a URL like: mvm.mydomain.com

I'm not having much success yet. Here are the relevant parts of various files I'm using to accomplish this:

Dockerfile:

EXPOSE 8080 8081

At the end of the Dockerfile, a Python app is started: it responds to health checks on port 8080 (I can verify this works) and responds to WebSocket requests on port 8081.

app.yaml:

module: mvm
version: 1
runtime: custom
vm: true
api_version: 1

network:
  forwarded_ports: ["8081"]

I deploy this app to the cloud using:

$ gcloud preview app deploy .

In the cloud console, I make sure TCP ports 8080 and 8081 are accepted for incoming traffic. I also observe the IP address assigned to the GCE instance (mvm:1) is: x.y.z.z.

$ curl http://x.y.z.z:8080/_ah/health
$ curl http://mvm.my-app-id.appspot.com/_ah/health

Repond both with 200 OK.

Connecting the WebSocket server using some JavaScript works as well:

new WebSocket('ws://x.y.z.z:8081');

So far so good. Except this didn't work (timeout):

new WebSocket('ws://mvm.my-app-id.appspot.com:8081');

I'd like to know why the above WebSocket command doesn't work. Perhaps something I don't understand in the GAE/GCE port forwarding interaction?

If this could be made to work somehow, I envision the following would be the last steps to finish it.

dispatch.yaml:

dispatch:
  # Send all websocket traffic to the ManagedVM module.
  - url: "mvm.mydomain.com/*"
    module: mvm

I also setup the GAE custom domain CNAME at mvm.mydomain.com.

Connecting the WebSocket server using JavaScript should then work like:

new WebSocket('ws://mvm.mydomain.com:8081');

回答1:

It may very well be that port forwarding from appspot.com isn't performed, given that prior to the (relatively recent) release of managed VMs, the only traffic that went to appspot.com was on port 80 or 443. I'd suggest using the IP-of-instance method you found to work.

If you don't find that fully satisfying, you should go to the public issue tracker for app engine and post a feature request to have the appspot.com router detect whether a request is heading for a module that corresponds to a managed VM and attempt the port forwarding in that case.

The thing is, putting the raw port on the end of the domain like that means that your browser will use the port you specified as a connection parameter to appspot.com, not as a query param, so appspot.com will have to listen on all ports and redirect if valid. This could be insecure/inefficient, so maybe the port number could be a query param or part of the domain string, similar to how version and module can be specified...

At any rate, given the way in which ports work, I would highly doubt, if your very simple example caused a fail, that app engine's appspot.com domain was even set up to handle port forwarding to managed VM containers at all at present.