Un’app in Docker su OpenStack

25 febbraio 2016

Fabrizio Soppelsa

- RHCE, Autore di Linux&C, Autore di Linux Journal

machine

Lo standard industriale del momento per creare hypervisor di container, è di creare prima una VM, installarci Docker, e poi invocare il daemon via API da remoto. A fronte di una certa latenza in fase di creazione dell’host, il vantaggio è l’isolamento al 100% e quindi la sicurezza.

Resta la domanda, dove creare questi Docker hypervisor? Ma su OpenStack, ovviamente!

Preparare l’ambiente

Si può installare un Docker hypervisor con strumenti quali Puppet o Ansible, ma perché reinventare la ruota o riciclare e adattare codice, quando nell’ecosistema di Docker un tool del genere esiste già? Questo tool si chiama Machine.

Machine è un binario capace di creare host Docker su vari provider – OpenStack incluso -, ed eventualmente collegarli per dare forma a un’infrastruttura distribuita con Swarm. Usare Machine è talmente semplice che io lo uso per installare Docker perfino sui miei desktop in locale.

docker-machine_w_450

Ma vediamo un’installazione seria: Machine su OpenStack. Servono:

  1. Un client Docker
  2. Un tenant OpenStack (suggerisco quote per lanciare almeno flavor medium)
  3. Una configurazione dei security groups che vedremo tra qualche momento

Come immagine della VM, potete usare qualsiasi distribuzione con un kernel preferibilmente 3.13+, per esempio Ubuntu Trusty. Se non l’avete già, caricate perciò un’immagine di Ubuntu in Glance. Poi fate download di Machine in locale:

$ sudo su
$ curl -L https://github.com/docker/machine/releases/download/v0.5.6/docker-machine_linux-amd64 > /usr/local/bin/docker-machine
$ chmod +x /usr/local/bin/docker-machine

Che versione abbiamo scaricato?

$ docker-machine --version
docker-machine version 0.5.6, build 61388e9

E quali machine attive abbiamo? Ovviamente ancora nessuna al momento:

$ docker-machine ls
NAME ACTIVE URL STATE URL SWARM DOCKER ERRORS

Security groups

Machine usa le porte ingress tcp/2376 per il Daemon, e tcp/22 per configurare remotamente l’host via SSH. Può funzionare su reti interni o su floating pool, preferendo floating se specificato.

Procediamo a creare il security group adatto, per esempio in Horizon, chiamandolo “machine”:

Screen Shot 2016-02-03 at 12.23.59 PM

Screen Shot 2016-02-03 at 12.24.07 PM

docker-machine create

Ora, dopo aver caricato in shell le credenziali OS_AUTH_URL, OS_TENANT_ID, OS_TENANT_NAME, OS_USERNAME e OS_PASSWORD di OpenStack del tenant da un file openrc (preferibilmente non di un utente amministratore), possiamo creare l’host con il seguente comando che spiegandosi da solo non ha bisogno di grandissimi commenti:

$ docker-machine create \
--driver openstack \
--openstack-image-id 98011e9a-fc46-45b6-ab2c-cf6c43263a22 \
--openstack-flavor-id 3 \
--openstack-floatingip-pool public \
--openstack-net-id 44ead515-da4b-443b-85cc-a5d13e06ddc85 \
--openstack-sec-groups machine \
--openstack-ssh-user ubuntu \
u1

In pratica, stiamo creando un Docker host chiamato u1 basato su Ubuntu 14.04 con un flavor medio, aggiungendogli un IP dal floating pool e specificando che deve usare machine come security group. Dopo qualche minuto…

$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
u1 - openstack Running tcp://172.18.186.56:2376

Mentre Machine crea l’host può essere istruttivo guardare il log dell’istanza (nova console-log IUID) e notare come il driver per OpenStack usi cloud-init per iniettare le configurazioni, aggiungere i certificati e le chiavi, installare i pacchetti e lanciare Docker.

Insomma, dopo l’installazione, caricando le variabili della machine in shell, è possibile governare l’hypervisor da remoto:

$ eval "$(docker-machine env u1)"

Per iniziare, ecco alcune informazioni sull’host:

$ docker info
...
Server Version: 1.9.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 89
 Dirperm1 Supported: false
...
Kernel Version: 3.13.0-55-generic
Operating System: Ubuntu 14.04.2 LTS
...
Labels:
 provider=openstack

Siamo ora pronti a lanciare un container su questo hypervisor!

$ docker run busybox echo “Hello from OpenStack”
Hello from OpenStack
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest 2c5ac3f849df 15 hours ago 1.113 MB

Compose up

Compose è un’altro dei pezzi pregiati dell’ecosistema Docker. È anche l’unico scritto in Python, sebbene libcompose, sua prossima libreria e ora experimental, è stata da poco rifatta in Go. Compose parte da una configurazione in un file YAML e crea uno o più container come lì descritto. Come dire, pensate di creare un’infrastruttura di 15 container per il solito WordPress, con 3 MySQL, 10 NginX e 2 balancer. Con un comando!

Installiamo Compose:

$ sudo su
$ curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > /usr/bin/docker-compose
$ chmod +x /usr/bin/docker-compose
$ docker-compose --version
docker-compose version: 1.4.2

Ora, ci sono migliaia di tutorial su Internet su come creare microservices in pochi secondi con Compose. Noi per pigrizia partiamo da una configurazione già pronta per OwnCloud:

$ git clone https://github.com/sameersbn/docker-owncloud.git
$ cd docker-owncloud

La struttura del servizio è la seguente: 3 container collegati, 1 con NginX, 1 con Postgres e 1 con OwnCloud. Vengono creati e messi in relazione automaticamente con:

$ docker-compose up -d

Con -d stiamo dicendo di eseguire i container in modalità daemon. Compose ora scarica le immagini sul nostro Docker host su OpenStack, lancia i container, li collega, e fa qualche altra operazione. Quando il comando ritorna, controlliamo cosa c’è in funzione:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e29ac6f6a394 sameersbn/nginx "/sbin/entrypoint.sh " 7 minutes ago Up 7 minutes 443/tcp, 0.0.0.0:80->80/tcp, 1935/tcp dockerowncloud_nginx_1
91ffba8739fd sameersbn/owncloud:latest "/sbin/entrypoint.sh " 7 minutes ago Up 7 minutes 9000/tcp dockerowncloud_owncloud_1
2d08e6679161 sameersbn/postgresql:latest "/sbin/entrypoint.sh" 8 minutes ago Up 8 minutes 5432/tcp dockerowncloud_postgresql_1

Siccome la porta 80 è rediretta internamente dall’host al container, se vogliamo accedere da remoto a questo servizio dovremo aprire similmente a quanto fatto sopra le porte tcp/80 e tcp/443 nel security group “machine”. Dopodiché:

$ docker-machine ip u1
172.18.186.56

Funziona!

Screen Shot 2016-02-03 at 12.24.31 PM

Se volete saperne di più su Machine o Swarm, dato che un po’ del codice in quei guazzabugli l’ho scritto anche io, non esitate a contattarmi. Se invece provate (soprattutto Machine) su OpenStack e trovate qualche difetto, potete aprirci una issue 🙂