do-shark2

In APSL we use the cloud provider digitalocean (DO onwards) for some support services and we are really happy with it. It’s not at the same level in services of AWS but allows us reduce costs in small self-managed services at the cloud.

One limitation with a "droplet" (this is how call to an instance in DO) is the few options for the configuration. DO assigns you a fixed IPv4 in the host and it’s now allowed add extra network interfaces. This is a limitation when you want to do something that is out of the common case: a problem that we found this week is that the Gitlab Pages service needs a second public interface to configure a secondary webserver. Other problem is when we want to serve two https sites without SNI,.

When faced with the problem we had three options:

  1. Do not have the functionality: not an option, we need to eat.

  2. Change the provider: extremely boring and expensive service migration.

  3. Hack the system: more fun and cheap (if you succeed).

Since the third option is the only viable path, we had to investigate what options we have in DO to solve the problem.

DO is not offering you a standard second interface but it offers the possibility of a Floating IP, which you can associate with a Droplet and change the association to another Droplet if you are interested. This service is useful for high availability architectures or maintenance tasks.

This Floating IP won’t create a new interface on the host network, but it goes to an aliased and private IP in the same eth0 interface, it’s documented like a "Anchor IP" .

We can know the Anchor IP via DO API or in the server shell with:

ip addr show eth0

Then you get printed the droplet's public IP (first inet) and Anchor IP (second inet) address information:

[secondary_output Example output:]
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdiscs pfifo_fast UP state group default qlen 1000
    link/ether 04:01:7d:c2:2:01 brd ffffffffffff
    inet 159.203.90.122/20 brd 159,203.95,255 scope Global eth0
       valid_lft forever forever preferred_lft
    inet 10.17.0.47/20 scope Global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::1 dff:fec2:a201/64 link scope
       valid_lftpreferred_lft forever forever

This two aliases of the eth0 network interface could be usable in the service configuration. For example, in our Gitlab Pages case:

# Gitlab frontend configuration
nginx['listen_addresses'] = ['159.203.90.122']

# Gitlab Pages web service configuration
gitlab_pages['external_http'] = [10.17.0.47:80']

Then we get two working services with the same port in digitalocean:

# netstat -tnlp | grep ": 80"
tcp        0      0 10.17.0.47:80            0.0.0.0:*               LISTEN      31449/gitlab-pages
tcp        0      0 159.203.90.122:80       0.0.0.0:*               LISTEN      31436/nginx

We will use the original droplet public IP for one service and the associated Floating IP for the other.

Concluding this is a nice hack to solve this particular problem but we still limited by the number of public IPs because we can only associate one Floating IP for each droplet.

Hope this post helps to someone to avoid another service migration, as you know, it was fun only the first time.