Pages

Saturday, 14 November 2015

用来连接Docker容器的代理 -Wormhole

Wormhole 是一个能识别命名空间的由 Socket 激活的隧道代理。可以让你安全的连接在不同物理机器上的 Docker 容器。可以用来完成一些有趣的功能,例如连接运行在容器本机的服务或者在连接后创建按需的服务。

例如要连到容器中的 MySQL 服务:

连接方法:
mysql=`docker run -d wormhole/mysql`
./wormhole create url :3306 docker-ns tail docker-ns $mysql
mysql -u root -h 127.0.0.1

创建一个本地的 WordPress 容器到 MySQL 容器:
app=`docker run -d wormhole/wordpress`
mysql=`docker run -d wormhole/mysql`
./wormhole create url :3306 docker-ns $app tail docker-ns $mysql

创建一个本地端口来连接:
./wormhole create url :80 trigger docker-run wormhole/wordpress \
           child url :3306 trigger docker-run wormhole/mysql

创建一个本地端口到远程 MySQL 服务:
mysql=`docker -H myserver run -d wormhole/mysql`
./wormhole create url :3306 remote myserver tail docker-ns $mysql
--------

A smart proxy that connects docker containers

Wormhole is a namespace-aware socket-activated tunneling proxy. It allows you to securely connect ports together on different physical machines inside docker containers. This allows for interesting things like connecting services running on localhost inside the container namespace or creating on-demand services that start when you connect to them.

But Why?

Containers give us the opportunity to move a whole bunch of complicated distributed systems problems (orchestration, service discovery, configuration management, and security) into the communication layer. They have the potential to finally give us truly standard components
This isn't intended to be a production solution for container relationships. Consider it an exploration of the above value. If you can create an application container that talks to a single port to get a secure connection to the database, many things get simpler. You don't have to configure the application with the proper address. You don't have to set a secure password for the database server. You can move the database without breaking the application. You can add a second database and start load balancing.
Most importantly, standardizing the communication layer means that containers are trivially sharable. Everyone who needs a mysql database container can use the same one. No configuration of the container is necessary, you can just drop it in and start using it.
Yes it is computationally more expensive to proxy connections, but consider:
  1. It is possible to accomplish many of the same things with sdn instead of proxying
  2. This proxy could replace the proxies that many services already use for load balancing or ssl termination.
Some people may feel that is inappropriate to proxy localhost connections this way, that localhost traffic should always be local. The above principles can be accomplished by using another well-known ip address. The one advantage of the localhost approach is almost every application is configured to listen on localhost out of the box so it makes container builds very easy.

Examples

Wormhole connects services together. The examples use the a wordpress container and a mysql container as the canonical example of two things that need to be connected.

Legend for diagrams

ex-legend

Proxy to the mysql in a local container

ex-01
mysql=`docker run -d wormhole/mysql`
./wormhole create url :3306 docker-ns tail docker-ns $mysql
mysql -u root -h 127.0.0.1
This requires a local install of mysql-client (ubuntu: apt-get install mysql-client).

Connect a local wp container to a local mysql container

ex-02
app=`docker run -d wormhole/wordpress`
mysql=`docker run -d wormhole/mysql`
./wormhole create url :3306 docker-ns $app tail docker-ns $mysql

Create a local port that does the above on connection

ex-03
./wormhole create url :80 trigger docker-run wormhole/wordpress \
           child url :3306 trigger docker-run wormhole/mysql

Create a local port to talk to a remote mysql

ex-04
mysql=`docker -H myserver run -d wormhole/mysql`
./wormhole create url :3306 remote myserver tail url :3306 docker-ns $mysql
The remote server must be running wormhole with the same key.secret

Do the above over an ipsec tunnel

ex-05
mysql=`docker -H myserver run -d wormhole/mysql`
./wormhole create url :3306 tunnel myserver trigger url :3306 docker-ns $mysql

Create a local port that runs a remote mysql on connection

ex-06
./wormhole create url :3306 trigger tunnel myserver trigger url :3306 docker-run wormhole/mysql
If the image has not been downloaded on 'myserver' then the initial connection will timeout.

Create a local port that runs wp followed by the above

ex-07
./wormhole create url :80 trigger docker-run wormhole/wordpress \
           child url :3306 tunnel myserver trigger url :3306 docker-run wormhole/mysql

Forget all this proxy stuff and make an ipsec tunnel

ex-08
./wormhole tunnel-create myserver
This command outputs a local and remote ip for the tunnel. Tunnels are not deleted when wormholed is closed. To delete the tunnel:
./wormhole tunnel-delete myserver

Getting Started

To get started you will need to:
a) Create a secret key
sudo mkdir -p /etc/wormhole
cat /dev/urandom | tr -dc '0-9a-zA-Z' | head -c 32 | sudo tee /etc/wormhole/key.secret
sudo chmod 600 /etc/wormhole/key.secret
b) Run the daemon as root
sudo ./wormholed
The wormhole cli communicates with the daemon over port 9999. To verify it is working:
./wormhole ping

Local Build and Test

Getting the source code:
go get github.com/vishvananda/wormhole
Building the binaries (will install go dependencies via go get):
make
Testing dependencies:
docker is required for functional tests
Unit Tests (functional tests use sudo):
make test-unit
Functional tests (requires root):
make test-functional # or sudo -E go test -v functional_test.go

Alternative Tools

Most of what wormhole does can be accomplished by hacking together various tools like socat and iproute2.

Future Work

Wormhole could be extended to support unix socket proxying. It would also be interesting to allow proxies from one type of socket to another a la socat.
Wormhole discovers existing tunnels when it starts, but it doesn't attempt to cleanup if it finds a partial tunnel. This option could be added.
Namespace support should be upstreamed to kubernetes/proxy so we don't have to maintain a fork.
Commands for list and tunnel-list should be added.
Wormhole could grow support for load balancing.
Traffic analysis and reporting could be added to the proxy layer.
from https://github.com/vishvananda/wormhole