Provisioning OpenStack instances with docker-machine

2 minute read

I had previously published a post about adding existing instances to Docker Machine using the generic driver.

In this post, I wanted to write about how I go about provisioning OpenStack instances with docker-machine using the openstack driver.

Assumption

You have provisioned some OpenStack resources (networks, routers, etc.) and want to use Docker Machine to provision instances for a more docker driven development workflow.

Download and source OpenStack RC file

Log in to the OpenStack Dashboard (Horizon), select the project for which you want to download the OpenStack RC file, and run the following commands:

$ source ~/Downloads/PROJECT-openrc.sh
Please enter your OpenStack Password for project PROJECT as user username:

Check your OpenStack environment variables:

$ env | grep OS_
OS_PROJECT_DOMAIN_ID=default
OS_PROJECT_ID=454f9cfc5f29d5108fe0cca0c74ad352
OS_REGION_NAME=RegionOne
OS_USER_DOMAIN_NAME=Default
OS_PROJECT_NAME=ProjectName
OS_IDENTITY_API_VERSION=3
OS_PASSWORD=fIUj!KqwertyC5Jrwqwy@
OS_AUTH_URL=https://openstackurl:5000/v3
OS_USERNAME=username
OS_INTERFACE=public

Install the OpenStack CLI client

Install the OpenStack CLI client and run the following commands, taking note of the output as some of these are mandatory for docker-machine CLI options:

$ openstack flavor list
+---

to get a list of available flavors,

$ openstack image list
+---

to get a list of available images,

$ openstack network list --external
+---

to get the floating ip pool,

$ openstack network list --internal
+---

to get a list of available internal networks, and

$ openstack security group list
+---

to get a list of available security groups

Note: I got into some authentication issues with OpenStack identity v3 and set the following environment variables as a workaround.

$ export OS_TENANT_ID=$OS_PROJECT_ID
$ export OS_DOMAIN_ID=$OS_PROJECT_DOMAIN_ID

Create a machine on OpenStack

To create a machine on OpenStack, specify -d openstack.

$ docker-machine create -d openstack \
--openstack-flavor-id 3 \
--openstack-image-name "ubuntu-18.04-server" \
--openstack-net-name INTERNAL-NET \
--openstack-floatingip-pool PUBLIC \
--openstack-ssh-user ubuntu \
--openstack-sec-groups default,OTHER-SEC-GROUP \
os-dm-instance

To connect your Docker client to the Docker Engine running on this instance, run:

eval $(docker-machine env os-dm-instance)

E.g, docker-machine inspect os-dm-instance lists the machine details.

To disconnect, run:

eval $(docker-machine env -u)

Docker MTU issues on OpenStack

Docker creates and configures the host system’s docker0 with an IP address, netmask, IP allocation range, and a default MTU of 1500 bytes.

The default MTU will causes network issues if it’s greater than the MTU of the outgoing interface (ens3), leading to containers not being able to access the Internet. You can check the MTU size with the following command:

$ docker-machine ssh os-dm-instance
ubuntu@os-dm-instance:~$  ip link | grep mtu
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
ubuntu@os-dm-instance:~$

To fix this, create or edit /etc/docker/daemon.json, with:

ubuntu@os-dm-instance:~$  sudo vi /etc/docker/daemon.json
//daemon.json
{
  "mtu": 1450
}

Restart Docker and ensure that the MTU is set.

ubuntu@os-dm-instance:~$ sudo systemctl daemon-reload
ubuntu@os-dm-instance:~$ sudo systemctl restart docker
ubuntu@os-dm-instance:~$ sudo docker run -it alpine /bin/sh
/ # ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
/ # ping alpinelinux.org
PING alpinelinux.org (147.75.101.119): 56 data bytes
64 bytes from 147.75.101.119: seq=0 ttl=47 time=147.360 ms

If you’re using docker-compose to deploy your containers, beware that compose creates a new network (mtu 1500) by default. Add the following in the network section of your compose file to change the MTU size:

#docker-compose.yml
networks:
  default:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: 1450

Hope someone finds this helpful.

Leave a comment