Desplegando imágenes Docker en Openstack

Desplegando imágenes Docker en Openstack

Vamos a ver un procedimiento básico sobre uso de Docker y su interacción con una nube privada Openstack; varios conceptos de esta entrada le serán útiles para desplegar soluciones de este tipo ya que veremos como conectarnos a una nube AWS Amazon usando claves; alterar imágenes Docker, uso del Hub de Docker, conexión a un Droplet de Digital Ocean, creación de una nube Openstack usando DevStack.

Configuración de instancia

Para comenzar configuremos nuestra conexión a AWS para crear una instancia Ubuntu 14.04 con la finalidad de instalar Docker y modificar una imagen básica. Una vez provisionada la imagen hacemos sudo apt-get update && sudo apt-get –y upgrade para actualizar el sistema operativo. Aquí nuestra instancia.

La conexión PuTTY la configuramos de la siguiente forma, el archivo AWS-Uniqs-Ubuntu.ppk fue generado con PuTTYGen a partir de la clave que nos provee AWS; para el caso de servidores Ubuntu el Host Name debe especificarse en el formato “ubuntu@<Public DNS>”. Esta referencia nos ayudará a generar el archivo .ppk (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html?icmpid=docs_ec2_console)

Instalación de docker

Una vez disponible la instancia procedemos a instalar Docker. Primero aseguramos que aufs se encuentre disponible:

sudo apt-get install linux-image-extra-`uname -r` 

Agregamos el repositorio de docker

sudo apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update

Bajamos e instalamos docker

sudo apt-get install docker-engine

Aplicación Docker

Vamos a usar Webapp que es una imagen pre-construída que contiene una sencilla aplicación web de Python y cuya finalidad de poder instanciar un pequeño código Python, nuestro objetivo es mostrar como manipularla en un servidor standalone y luego “enchufar” dicha imagen en una nube privada Openstack (aun usando otro proveedor de nube pública).

Ejecutamos docker run para levantar un container con los siguientes parámetros.

$ sudo docker run -P -t -i training/webapp /bin/bash 
  • -P: Instruye a docker para que mapee los puertos necesarios dentro del rango de los expuestos.
  • -t: Aloca una pseudo-TTY
  • -i: Interactivo
  • training/webapp. Usaremos la imagen webapp.
  • /bin/bash. Nos permitirá ejecutar un Shell interactivo dentro del contenedor.

Este contenedor nos brinda una aplicación simple cuya salida es la siguiente.

En otra sesión ssh ejecutamos el comando “docker ps –a” que nos permite conocer el estado del contenedor (Up, Down, etc.), su nombre, puertos involucrados

$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
84c66094c852 training/webapp "/bin/bash" 11 seconds ago Up 10 seconds 0.0.0.0:32768->5000/tcp angry_mclean
 

En nuestro caso a aplicación web ofrecida por el código python se ejecuta en el puerto 32768. Hagamos una revisión de conectividad básica con telnet para ver si efectivamente mi aplicación escucha en el puerto informado.

$ telnet 127.0.0.1 32768
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'. 

Vamos a volver nuevamente al shell interactivo del contenedor para editar el archivo app.py para alterar su contenido

$ sudo docker run -P -t -i training/webapp /bin/bash
root@7d8a7cbebee5:/opt/webapp# vi app.py

Archivo app.py

import os
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
 provider = str(os.environ.get('PROVIDER', 'world'))
 return 'Hello '+provider+'!'
if __name__ == '__main__':
 # Bind to PORT if defined, otherwise default to 5000.
 port = int(os.environ.get('PORT', 5000)) app.run(host='0.0.0.0', port=port) 

Cambiaremos “provider = str(os.environ.get(‘PROVIDER’, ‘world’))” por “provider = str(os.environ.get(‘PROVIDER’, ‘guys’))”

Guardaremos una nueva imagen en el mismo servidor pero en este caso con el nuevo código python, levantamos un nuevo contenedor para verificar que todo funcione de manera satisfactoria y luego la subiremos al Hub de Docker

$ sudo docker commit -a "Pablo" -m "GuysxWorld" 84c66094c852 pablocalvo/webapp:1.0
sha256:77fc232059bc15b142cd5725e9e2badfac3949a3cb644885fedf51a6f5dd3835
 
  • -m: Útil para control de versiones.
  • -a: Nos permite especificar un autor para nuestra actualización.
$ sudo docker run -P pablocalvo/webapp:1.0 python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 


Ingresamos a nuestro Hub y ejecutamos el Push para subir la imagen.

$ sudo docker login -u pablocalvo
Password:
Login Succeeded
$ sudo docker push pablocalvo/webapp:1.0
The push refers to a repository [docker.io/pablocalvo/webapp] 
be5d1b73e5eb: Pushed
...
1154ba695078: Pushed
1.0: digest: sha256:986e81d8f82405fe88d20e138ce696c1fecbba156ddc33fdb0c08654faad0507 size: 8819 

Hemos subido en forma satisfactoria nuestra imagen al Hub.

Configuración de Openstack

Ahora vamos a contratar un Droplet en Digital Ocean para instalar y configurar Openstack en un solo servidor, en nuestro caso Ubuntu; el servidor debe tener al menos 4 Gb de memoria RAM.

La guía de instalación se encuentra disponible aquí: http://docs.openstack.org/developer/devstack/guides/single-machine.html, básicamente ejecutaremos el script devstack que es muy útil para lograr una configuración base de openstack basada en screens.

Creamos el usuario “stack”

adduser stack 

Instalamos sudo, configuramos al usuario “stack” para que no requiera clave al ejecutar sudo.

apt-get install sudo -y || yum install -y sudo
echo "stack ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

Instalamos git y bajos el repositorio de devstack.

sudo apt-get install git -y || sudo yum install -y git
git clone https://git.openstack.org/openstack-dev/devstack
cd devstack 

Antes de lanzar DevStack hemos configurado el archivo /home/stack/devstack/local.conf de la siguiente forma.

[[local|localrc]]
FLOATING_RANGE=107.170.92.76/27
FIXED_RANGE=10.11.12.0/24
FIXED_NETWORK_SIZE=256
FLAT_INTERFACE=eth0
ADMIN_PASSWORD=<some password>
DATABASE_PASSWORD=<some password>
RABBIT_PASSWORD=<some password>
SERVICE_PASSWORD=<some password>

A continuación la ejecución del comando y su finalización

$ ./stack.sh
This is your host IP address: 107.170.92.76
This is your host IPv6 address: ::1
Horizon is now available at http://107.170.92.76/dashboard
Keystone is serving at http://107.170.92.76/identity/
The default users are: admin and demo
The password: <same password>

Una vez configurada nuestra nube Openstack debemos adecuarla para que acepte imágenes docker (https://wiki.openstack.org/wiki/Docker) y debemos instalar docker en el servidor (Ver “Instalación de Docker” en este mismo blog)

Configuración de nova

Nova debe ser configurado para poder usar el driver de docker; para ello debe configurar el archivo /etc/nova/nova.conf de la siguiente manera:

[DEFAULT]
compute_driver = novadocker.virt.docker.DockerDriver

Debemos crear el directorio /etc/nova/rootwrap.d si no existe y allí escribir el archivo “docker.filters” de la siguiente forma:

[Filters]
ln: CommandFilter, /bin/ln, root

Configuración de glance

[DEFAULT]
container_formats = ami,ari,aki,bare,ovf,docker

Ya realizadas las configuraciones del caso procedemos a crear una copia local de la imagen alojada en el Hub.

$ docker pull pablocalvo/webapp:1.0
1.0: Pulling from pablocalvo/webapp
e190868d63f8: Pull complete
...
349abde8a623: Pull complete
Digest: sha256:986e81d8f82405fe88d20e138ce696c1fecbba156ddc33fdb0c08654faad0507
Status: Downloaded newer image for pablocalvo/webapp:1.0 

Ahora incorporemos la imagen a la nube openstack

$ docker save pablocalvo/webapp:1.0 | glance image-create --container-format=docker --disk-format=raw --name=pablocalvo-webapp
  • image-greate: Instruye a glance a crear una imagen
  • container-format: Determina que el contenedor que se creará a partir de la imagen será del tipo docker.
  • disk-format: El formato de la imagen; puede ser ami, ari, aki, vhd, vmdk, raw, qcow2, vdi e iso.
  • name: Es el nombre de la imagen

Revisemos que la misma efectivamente se encuentre bajo el control de Glance

$ glance image-list
+--------------------------------------+---------------------------------+
| ID | Name |
+--------------------------------------+---------------------------------+
| 9ba9989b-1c38-4875-ba33-fdd593edc818 | cirros-0.3.4-x86_64-uec |
| ddfca0dc-0236-4a62-bdaf-3061bf96cd27 | cirros-0.3.4-x86_64-uec-kernel |
| ef5a5fcb-4eb6-490c-912c-ede1f07bfbbd | cirros-0.3.4-x86_64-uec-ramdisk |
| b7d3c11a-c675-46d3-bef4-f70b0edb3492 | pablocalvo-webapp |
+--------------------------------------+---------------------------------+
 

Y que sea una imagen tipo docker


Sólo nos resta crear una instancia usando la imagen previamente cargada

En este blog hemos desarrollado un procedimiento secuencial de despliegue de una imagen docker sobre una nube Openstack con el objetivo de entender la potencialidad de utilizar la tecnología de contenedores en forma conjunta con los servicios de computación en la nube. Esta guía le permitirá aplicar a casos prácticos a partir de aplicativos “dockerizados” que pueden “enchufarse” a instalaciones Openstack productivas.

Por Pablo Calvo

Dejá un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *