Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Libprocess woes from behind NAT (docker BRIDGE networking) #25

Open
anthonyrisinger opened this issue Jun 5, 2015 · 1 comment
Open

Comments

@anthonyrisinger
Copy link

I'm not sure if this is a bug/feature-request in pesos/compactor, but since it affects how pesos can be deployed, and since docker is a standard Mesos executor, I'm documenting here.

Our infrastructure is primarily composed of running docker images in BRIDGE mode across our Mesos cluster. BRIDGE is preferred to HOST networking for a number of reasons, including security and flexibility (otherwise many services would be limited to one instance per slave). Our custom framework is no different; it's ran as a normal Marathon+docker task, which in turn starts it's own tasks against the same Mesos cluster.

The problem is how libprocess/compactor works: it requires BOTH nodes to host an HTTP server, and advertises it's own return address as a Libprocess-From: name@ip:port header. However, since the framework is running within a BRIDGE container, the ip:port address advertised is INTERNAL and NON-ROUTABLE from the outside.

The solution is to allow compactor.context.Context to initially bind to the internal ip:port, then change it's properties to advertise the public side of the port forwarding setup by docker, thus making it self-referential. Mesos (or Marathon or docker executor?) exports the forwards as PORT* environment variables, and one can use this to learn the public facing ip:port:

        context = None
        if 'PORT_8055' in os.environ:
            # Construct/hack our own context to account for docker BRIDGE
            # networking (NAT). The socket is bound to 0.0.0.0:8055 but we
            # advertise something externally routable.
            context = compactor.context.Context(port=8055)
            context.start()
            context.port = int(os.environ['PORT_8055'])
            if 'HOST' in os.environ:
                # context.ip = socket.gethostbyname(os.environ['HOST'])
                context.ip = socket.getaddrinfo(
                        os.environ['HOST'], 8055, socket.AF_INET,
                        socket.SOCK_STREAM, socket.IPPROTO_TCP
                        )[0][4][0]

        # pesos will use our context instead of Context.singleton()
        # driver = pesos.scheduler.SchedulerDriver(..., context=context)

Maybe this is a use case pesos/compactor would like to support directly? Or maybe Libprocess already has a solution, and compactor needs an update? The above "works" but feels like a hack.

I'd like a clean way to say "bind to this ip:port, but advertise this other ip:port".

@tarnfeld
Copy link
Contributor

tarnfeld commented Jun 8, 2015

If I understand what you're saying correctly... TL;DR this is how LibProcess works.

You can configure the IP address that's bound to by using the LIBPROCESS_IP environment variable, however with bridge networking if you specify that as the host interface you're not going to be able to bind to that, as you mentioned.

There's a couple of tickets you might want to keep an eye on;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants