Experimentando con Ubuntu juju y Cloud Foundry

Después de las vacaciones de verano, volvemos con la energia renovada y con ganas de hacer más experimentos 🙂

En una entrada anterior donde os hablabla de Cloud Foundry, un lector me pedia un post sobre como montar un servidor propio. La verdad es que comencé a escribirlo, aunque por motivos que no vienen a cuento tardé más de la cuenta. Y casi justo cuando lo tenia terminado, VMWare lanzó un script que simplifica mucho el proceso de instalación, por lo que borré el post por careced de sentido. Así pués, si todavia estais interesados, solamente tenéis que seguir las instrucciones que aparecen en la página del proyecto en github. El proceso, aunque largo, es muy sencillo.

En esta entrada, en cambio, nos vamos a centrar en ver como os podeis montar vuestro propio servidor de Cloud Foundry, pero en vez de en local, lo vamos a albergar en Amazon EC2. Además, en vez de hacerlo de la forma tradicional (o sea, creando una instancia de EC2 y ejecutando el script de instalación tal como se describe en esta página), vamos a utilizar una nueva herramienta muy interesante que ha aparecido recientemente, y que nos permitirá además escalar los servicios ofrecidos por Cloud Foundry de una manera muy sencilla y rápida.

La herramienta en cuestión se llama Ubuntu Ensemble. Bien, de hecho ya no se llama así 🙁 . Justo cuando estoy escribiendo esta entrada, lo magnificos chicos de Canonical han decidido cambiarle el nombre por Ubuntu juju (esta entrada debe estar “gafada” 🙂 ) en referencia a la magia/brujería practicada en algunas regiones de Africa.

juju es un framework de orquestación para el despliegue de servicios de infraestructura en la “nube” (similar en cuanto a concepto a Chef o Puppet o, en otro nivel, a los ServerTemplates de RightScale), o dicho de otra manera, una especie de APT pero dirigido a entornos que se ejecutan en la “nube” y, a diferencia del primero, en vez de focalizarse en el despliegue de un producto en una máquina, persigue la instalación orquestada en entornos distribuidos de servicios interrelacionados. La idea detrás de juju es que haya una comunidad de desarrolladores que paquetizen el despliegue de sus servicios (similar a lo que hace APT con los paquetes o a las recipes de Chef) mediante lo que llaman charms (hechizos) y que estas charms, además de ser reutilizables por otros usuarios, incluyan los metadatos del servicio, las dependencias a otros servicios, los paquetes necesarios para su despliegue, así como la lógica para gestionar el servicio. Actualmente esta en fase de desarrollo, y solo admite entornos Amazon EC2 (o clones en cuanto a la API, como OpenStack), aunque está previsto soporte a otros entornos en un futuro. Se incluirá por defecto en la release 11.10 de Ubuntu, aunque a dia de hoy, ya se puede probar tanto en la Beta 1 de la release 11.10 como en versiones anteriores (11.04 y 10.04).

Bien, una vez hechas las presentaciones, vamos a experimentar con esta herramienta. En primer lugar vamos a instalar juju. Si estamos utilizando Ubuntu 11.10 es tan sencillo como:

~$ sudo apt-get install juju

Pero si utilizamos Ubuntu 10.04 o 11.04, entonces tendremos que añadir primero el repositorio PPA correspondiente:

~$ sudo apt-get install python-software-properties
~$ sudo add-apt-repository ppa:juju/pkgs
~$ sudo apt-get update
~$ sudo apt-get install juju

Ahora vamos a inicializar el entorno de juju. Primero invocaremos al comando que nos creará un archivo de entorno por defecto:

~$ juju
error: No environments configured. Please edit: /home/frodenas/.juju/environments.yaml

Y editaremos el archivo añadiendo algunas líneas:

~$ vi /home/frodenas/.juju/environments.yaml
environments:
  sample:
    type: ec2
    ec2-uri: https://ec2.eu-west-1.amazonaws.com
    access-key: --- INSERTAR AQUI VUESTRA ACCESS-KEY DE AMAZON EC2 ---
    secret-key: --- INSERTAR AQUI VUESTRA SECRET-KEY DE AMAZON EC2 ---
    control-bucket: --- ELIMINADO POR SEGURIDAD - DEJAR EL VALOR POR DEFECTO ---
    admin-secret: --- ELIMINADO POR SEGURIDAD - DEJAR EL VALOR POR DEFECTO ---
    default-image-id: ami-66f6c512
    default-instance-type: m1.large

Lo que hemos añadido ha sido:

  • ec2-uri: aquí hemos puesto el endpoint de la región de Amazon EC2 que nos interesa, en este caso, la región EU West (Irlanda).
  • access-key y secret-key: vuestras credenciales de Amazon EC2.
  • default-image-id: aquí ponemos el nombre de la AMI de Amazon EC2 que se utilizará por defecto, en este caso, utilizaremos una imagen de Ubuntu Cloud 11.10 de 64 bits disponible en la región de EU West. El nombre de la AMI varia cada dia, por lo que os recomiendo que comproveis la lista actual de imagenes antes de utilizar la que yo he puesto.
  • default-instance-type: aquí ponemos el tipo de instancia de Amazon EC2 que se utilizará por defecto, en este caso, como la instancia contendrá Cloud Foundry y diversos servicios (MySQL, MongoDB y Redis), escogemos la instancia grande (m1.large).

Bien, ahora hemos de arrancar el entorno. Pero antes, y debido a que las charms de juju que nos permiten instalar el servidor de Cloud Foundry y sus servicios todavia no están publicadas en los repositorios oficiales, nos tocará instalarlas manualmente en local:

~$ sudo apt-get install bzr
~$ mkdir charms && cd charms
~/charms$ bzr branch lp:~canonical-sig/+junk/cloudfoundry-server

Ahora si podemos arrancar el entorno de juju (generar antes un par de claves en vuestro sistema sino lo habéis hecho, de lo contrario el entorno no arrancará):

~/charms$ ssh-keygen -t rsa -b 2048
~/charms$ juju bootstrap
2011-09-22 00:46:54,161 INFO Bootstrapping environment 'sample' (type: ec2)...
2011-09-22 00:47:01,753 INFO 'bootstrap' command finished successfully

Esto proceso lo que hará es crear una instancia en Amazon EC2 e instalarle el servidor de juju mediante cloud-init. Con el comando status podremos ver si el entorno está ya arrancado:

~/charms$ juju status
No machines have addresses assigned yet
2011-09-22 00:47:11,893 ERROR No machines have addresses assigned yet

Vemos que la instancia todavía no está levantada. Nos vamos a la consola web de Amazon EC2 y esperamos a que arranque:

Una vez esté en marcha, volvemos a ejecutar el comando status:

~/charms$ juju status
2011-09-22 00:49:00,215 INFO Connecting to environment.
machines:
  0: {dns-name: ec2-46-51-151-139.eu-west-1.compute.amazonaws.com, instance-id: i-af00e1e6}
services: {}
2011-09-22 00:49:01,834 INFO 'status' command finished successfully

Como veis, ahora si nos indica que hay una máquina en marcha. Ahora vamos a desplegar el servidor de Cloud Foundry. Para ello utilizaremos el comando deploy y la charm que nos hemos descargado anteriormente:

~/charms$ juju deploy --repository . cloudfoundry-server
2011-09-22 00:49:25,033 INFO Connecting to environment.
2011-09-22 00:49:27,823 INFO Charm deployed as service: 'cloudfoundry-server'
2011-09-22 00:49:27,825 INFO 'deploy' command finished successfully

Igual que en el caso anterior, esperamos a que arranqué la instancia, se despliegue el servidor y servicios de Cloud Foundry, y estos se pongan en marcha (tened paciencia, es un proceso un poco lento). Podemos ir consultando periodicamente el estado hasta que el servicio está en marcha (el campo “state” pasará de “null” a “installed” y finalmente “started“):

~/charms$ juju status
2011-09-22 00:55:17,906 INFO Connecting to environment.
machines:
  0: {dns-name: ec2-46-51-151-139.eu-west-1.compute.amazonaws.com, instance-id: i-af00e1e6}
  1: {dns-name: ec2-46-137-3-58.eu-west-1.compute.amazonaws.com, instance-id: i-0503e24c}
services:
  cloudfoundry-server:
    charm: local:cloudfoundry-server-26
    relations: {}
    units:
      cloudfoundry-server/0:
        machine: 1
        relations: {}
        state: started
2011-09-22 00:55:20,236 INFO 'status' command finished successfully

El siguiente paso será abrir los puertos necesarios para que nos podamos conectar con el servidor de Cloud Foundry. Para ello utilizaremos el comando expose (y no es necesario indicar los puertos a abrir, ya que estos están indicados en la charm):

~/charms$ juju expose cloudfoundry-server
2011-09-22 00:55:41,155 INFO Connecting to environment.
2011-09-22 00:55:42,485 INFO Service 'cloudfoundry-server' was exposed.
2011-09-22 00:55:42,486 INFO 'expose' command finished successfully

Consultamos el estado del servicio y veremos como ahora nos indica los puertos que están abiertos:

~/charms$ juju status
2011-09-22 00:55:45,701 INFO Connecting to environment.
machines:
  0: {dns-name: ec2-46-51-151-139.eu-west-1.compute.amazonaws.com, instance-id: i-af00e1e6}
  1: {dns-name: ec2-46-137-3-58.eu-west-1.compute.amazonaws.com, instance-id: i-0503e24c}
services:
  cloudfoundry-server:
    charm: local:cloudfoundry-server-26
    exposed: true
    relations: {}
    units:
      cloudfoundry-server/0:
        machine: 1
        open-ports: [80/tcp, 443/tcp, 4222/tcp]
        relations: {}
        state: started
2011-09-22 00:55:48,101 INFO 'status' command finished successfully

En teoria ahora está todo levantado, pero por si acaso, vamos a comprobarlo conectandonos a la máquina que contiene el servidor de Cloud Foundry. Para ello utilizaremos el comando ssh del propio juju y el número de máquina que nos ha indicado el comando status:

~/charms$ juju ssh 1
2011-09-22 00:56:14,640 INFO Connecting to environment.
2011-09-22 00:56:16,265 INFO Connecting to machine 1 at ec2-46-137-3-58.eu-west-1.compute.amazonaws.com

Una vez hayamos entrado, miraremos si los servicios de Cloud Foundry están levantados:

ubuntu@ip-10-228-250-63:~$ cd /opt/cloudfoundry-server/vcap/bin
ubuntu@ip-10-228-250-63:/opt/cloudfoundry-server/vcap/bin$ sudo ./vcap status
router              :    RUNNING
cloud_controller    :    RUNNING
dea                 :    RUNNING
health_manager      :    RUNNING
redis_gateway       :    RUNNING
redis_node          :    RUNNING
mysql_gateway       :    RUNNING
mysql_node          :    RUNNING
mongodb_gateway     :    RUNNING
mongodb_node        :    RUNNING

Como vemos, todos los servicios de Cloud Foundry están en marcha. Ya nos podemos desconectar de la instancia de Amazon EC2:

ubuntu@ip-10-228-250-63:/opt/cloudfoundry-server/vcap/bin$ exit
Connection to ec2-46-137-3-58.eu-west-1.compute.amazonaws.com closed.

Ahora vamos a proceder a conectarnos a Cloud Foundry para ver si responde. Lo primero que deberemos hacer es bajarnos el cliente vmc:

~/charms$ sudo apt-get install ruby-vmc

Pero para poder conectarnos remotamente necesitamos disponer de un registro wildcard DNS que redirija nuestras peticiones hacia el servidor de Cloud Foundry. En nuestro caso, como es solo un experimento low cost, vamos a utilizar un truco. Lo que vamos a hacer en crear un tunel ssh de manera que las peticiones al puerto 80 de nuestra máquina se redirijan al puerto 80 de la instancia de Amazon EC2 que contiene el servidor de Cloud Foundry (si en vuestra máquina ya estais utilizando el puerto 80, lo podeis cambiar a otro, por ejemplo, el 8080). Pero para poder montar el túnel contra la instancia de Amazon EC2, necesitamos tener la clave privada y que esta coincida con la clave pública almacenada en la instancia de Amazon EC2. Como en el archivo de entorno de juju no hemos especificado ningún par de claves, este ha utilizado el par de claves de nuestro usuario (de ahí que os recordava anteriormente el generar un par de claves). Así pués, lo que haremos es indicar al ssh que utilize la clave privada de nuestro usuario:

~/charms$ cd ~/.ssh
~/.ssh$ sudo ssh -i id_rsa -L 80:46.137.3.58:80 ubuntu@46.137.3.58 -N

El problema de este metodo es que nos bloquea la sesión de terminal, por lo que nos tocará abrir una nueva sesión. Una vez la tengamos, procederemos a provar la conexión contra Cloud Foundry:

~$ vmc target api.vcap.me
Succesfully targeted to [http://api.vcap.me]</p>
<p>~$ vmc info</p>
<p>VMware's Cloud Application Platform
For support visit http://support.cloudfoundry.com</p>
<p>Target:   http://api.vcap.me (v0.999)
Client:   v0.3.10

Bien, parece que el servidor responde. Ahora vamos a crear un usuario:

~$ vmc register
Email: frodenas@gmail.com
Password: ********
Verify Password: ********
Creating New User: OK
Successfully logged into [http://api.vcap.me]</p>
<p>~$ vmc info</p>
<p>VMware's Cloud Application Platform
For support visit http://support.cloudfoundry.com</p>
<p>Target:   http://api.vcap.me (v0.999)
Client:   v0.3.10</p>
<p>User:     frodenas@gmail.com
Usage:    Memory   (0B of 2.0G total)
          Services (0 of 16 total)
          Apps     (0 of 20 total)

Perfecto! El servidor de Cloud Foundry ya está listo para ser usado!

Podríamos finalizar el experimento aquí, pero vamos a ir un poco más allá. En un teórico entorno de producción, seguramente nos quedaremos cortos con solo 1 instancia de Cloud Foundry y que esta incluya todos los servicios. Lo que haríamos es crear más instancias y albergar en cada una de ellas alguno de los servicios disponibles. Vamos a ver como lo podemos hacer con juju.

En primer lugar, nos descargamos los charms que nos interesen. Aquí os pongo los charms de los servicios de DEA (el agente de Cloud Foundry que ejecutará nuestras aplicaciones), MySQL, MongoDB y Redis:

~$ cd charms
~/charms$ bzr branch lp:~canonical-sig/+junk/cloudfoundry-server-dea
~/charms$ bzr branch lp:~canonical-sig/+junk/cf-mysql
~/charms$ bzr branch lp:~canonical-sig/+junk/cf-mongodb
~/charms$ bzr branch lp:~canonical-sig/+junk/cf-redis

Vamos a utilizar como ejemplo la instalación de un nuevo servidor de MongoDB. Utilizaremos igual que antes el comando deploy:

~/charms$ juju deploy --repository . cf-mongodb
2011-09-22 01:04:42,031 INFO Connecting to environment.
2011-09-22 01:04:45,147 INFO Charm deployed as service: 'cf-mongodb'
2011-09-22 01:04:45,149 INFO 'deploy' command finished successfully

Y esperaremos a que el servicio de MongoDB esté levantado (cuando aparezca “state: started“):

~/charms$ juju status
2011-09-22 01:11:07,813 INFO Connecting to environment.
machines:
  0: {dns-name: ec2-46-51-151-139.eu-west-1.compute.amazonaws.com, instance-id: i-af00e1e6}
  1: {dns-name: ec2-46-137-3-58.eu-west-1.compute.amazonaws.com, instance-id: i-0503e24c}
  2: {dns-name: ec2-79-125-44-111.eu-west-1.compute.amazonaws.com, instance-id: i-7b04e532}
services:
  cf-mongodb:
    charm: local:cf-mongodb-1
    relations: {mongodb-cluster: cf-mongodb}
    units:
      cf-mongodb/0:
        machine: 2
        relations:
          mongodb-cluster: {state: up}
        state: started
  cloudfoundry-server:
    charm: local:cloudfoundry-server-26
    exposed: true
    relations: {}
    units:
      cloudfoundry-server/0:
        machine: 1
        open-ports: [80/tcp, 443/tcp, 4222/tcp]
        relations: {}
        state: started
2011-09-22 01:11:11,105 INFO 'status' command finished successfully

Ahora lo que debemos hacer es informar al servidor de Cloud Foundry de que tiene una nueva instancia de MongoDB disponible para ser usada. Para realizar esta acción, simplemente debemos establecer una relación entre las 2 instancias mediante juju, y este, mediante las instrucciones contenidas en la charm, hará las modificaciones pertinentes en el archivo de configuración de Cloud Foundry. Así pués, vamos a ello:

~/charms$ ~/charms$ juju add-relation cloudfoundry-server cf-mongodb
2011-09-22 01:11:36,088 INFO Connecting to environment.
2011-09-22 01:11:37,997 INFO Added cf-server relation to all service units.
2011-09-22 01:11:37,997 INFO 'add_relation' command finished successfully

Consultamos ahora el estado y vemos que nos aparece la relación:

~/charms$ juju status
2011-09-22 01:11:51,639 INFO Connecting to environment.
machines:
  0: {dns-name: ec2-46-51-151-139.eu-west-1.compute.amazonaws.com, instance-id: i-af00e1e6}
  1: {dns-name: ec2-46-137-3-58.eu-west-1.compute.amazonaws.com, instance-id: i-0503e24c}
  2: {dns-name: ec2-79-125-44-111.eu-west-1.compute.amazonaws.com, instance-id: i-7b04e532}
services:
  cf-mongodb:
    charm: local:cf-mongodb-1
    relations: {cf-server: cloudfoundry-server, mongodb-cluster: cf-mongodb}
    units:
      cf-mongodb/0:
        machine: 2
        relations:
          cf-server: {state: up}
          mongodb-cluster: {state: up}
        state: started
  cloudfoundry-server:
    charm: local:cloudfoundry-server-26
    exposed: true
    relations: {cf-server: cf-mongodb}
    units:
      cloudfoundry-server/0:
        machine: 1
        open-ports: [80/tcp, 443/tcp, 4222/tcp]
        relations:
          cf-server: {state: up}
        state: started
2011-09-22 01:11:55,279 INFO 'status' command finished successfully

Vamos a comprobar si el servicio está levantado en Cloud Foundry mediante una conexión ssh de juju:

~/charms$ juju ssh 2
2011-09-22 01:12:17,200 INFO Connecting to environment.
2011-09-22 01:12:18,813 INFO Connecting to machine 2 at ec2-79-125-44-111.eu-west-1.compute.amazonaws.com
ubuntu@ip-10-58-121-108:~$ cd /opt/cloudfoundry-server/vcap/bin
ubuntu@ip-10-58-121-108:/opt/cloudfoundry-server/vcap/bin$ sudo ./vcap status
router              :    STOPPED
cloud_controller    :    STOPPED
dea                 :    STOPPED
health_manager      :    STOPPED
redis_gateway       :    STOPPED
redis_node          :    STOPPED
mysql_gateway       :    STOPPED
mysql_node          :    STOPPED
mongodb_gateway     :    RUNNING
mongodb_node        :    RUNNING
ubuntu@ip-10-58-121-108:/opt/cloudfoundry-server/vcap/bin$ exit
Connection to ec2-79-125-44-111.eu-west-1.compute.amazonaws.com closed.

Vemos como en esta instancia solamente se está ejecutando el servicio de MongoDB. Si viésemos que necesitamos otra instancia adicional de MongoDB, en este caso no haría falta ejecutar los comandos anteriores. Simplemente utilizando el comando add-unit nos crearía una nueva instancia que formaria parte de un cluster de MongoDb y con la relación con el servidor de Cloud Foundry creada por defecto:

~/charms$ juju add-unit cf-mongodb

Y hasta aquí llega el experimento. Un consejo antes de finalizar: si tenéis cualquier problema ejecutando alguno de los pasos anteriores y no sabeis que está pasando, podeis utilizar el comando debug-log para ver el log del servidor de juju e intentar determinar la causa del problema:

~/charms$ juju debug-log
2011-09-22 01:13:31,421 INFO Connecting to environment.
2011-09-22 01:13:32,588 INFO Enabling distributed debug log.
2011-09-22 01:13:32,696 INFO Tailing logs - Ctrl-C to stop.

Como último paso, como siempre, recordar que hay que finalizar el entorno. Utilizaremos para ello el comando destroy-environment:

~/charms$ juju destroy-environment
WARNING: this command will destroy the 'sample' environment (type: ec2).
This includes all machines, services, data, and other resources. Continue [y/N]yes
2011-09-22 01:14:02,900 INFO Destroying environment 'sample' (type: ec2)...
2011-09-22 01:14:04,644 INFO Waiting on 3 EC2 instances to transition to terminated state, this may take a while
2011-09-22 01:14:27,728 INFO 'destroy_environment' command finished successfully

Este comando debería eliminar también las instancias de Amazon EC2, pero por si acaso, no está de más que lo comproveis vosotros mismos en la consola web de Amazon EC2.

Bien, como hemos visto, esta herramienta promete bastante. Si bien está previsto que entre por defecto en la release 11.10 de Ubuntu del mes de Octubre de 2011, la versión liberada estará todavia un poco verde, por lo que no os la recomiendo para un entorno de producción. Mientras tanto, espero que disfrutéis experimentado con ella (probad alguna de las charms oficiales o crearos vosotros mismos alguna de prueba). Si alguien se anima, que deje sus impresiones en los comentarios de esta entrada.

Comments

Comment by Rogelio on 2012-03-06 19:59:48 +0000

Ferdy,

Google me trajo aqui cuando busque: “cloudfoundry ec2 ami”. Encuentro muy interesante tu blog, tenemos algunos intereses comunes.

Al igual que tú, en este momento estoy interesado en open source PaaS como CloudFoundry. Los conoci en la conferencia CloudExpo 2011 en Santa Clara, CA. Todavia no he tenido una oportunidad de conocer OpenStack.

Mi objetivo es utilizar la plataforma tanto para aplicaciones front-end web y batch jobs: spring batch y Hadoop. Me gusta CloudFoundry para usarlo en Amazon EC2 o en nuestras propias instalaciones.

Soy originario de Mexico, vivo en el sur de California, arriba el español!

Gracias por la informacion en tu blog, lo visitare nuevamente en un futuro.

Rogelio

Comment by ferdy on 2012-03-06 23:13:57 +0000

Bienvenido al blog Rogelio.

Comment by fernando Gutierrez on 2012-07-29 15:23:32 +0000

ferdy, no me ha quedado muy claro la verdadera funcionalidad del servicio de juju, pues tengo una instancia en amazon AWS gratis por un año y directamente y sin unstakar nada en una instancia, monte el servidor de ubuntu y configure un servidior web, corro una aplicación, pero esto no es del todo gratis, porque si me paso de uso y otras servicios me cobran, entonces cual es el papel con juju, si segun entiendo se conectara a Amazon y hay crear un usuario y pues siempre te cobraran ,si te pasas de que ofrecen. Me imagene que juju, servia para montar o conectarse a una cloud gratuita de ubuntu??.

saludos,

Comment by ferdy on 2012-08-05 22:19:21 +0000

Fernando, juju no proporciona ningún servicio de cloud (ni gratis ni de pago), es un servicio para poder orquestar la instalación de productos de una forma sencilla en entornos cloud. Por decirlo de otra manera, en vez de instalarte tu mismo el servidor web con la BBDD (etc), juju te proporciona una especia de recetas para simplificarte la instalación y posterior mantenimiento (escalado, actualización, …).

Comment by Pablo on 2012-11-03 07:36:10 +0000

Estoy intentando configurar un nube privada con Ubuntu Cloud y he tenido algunos problemas con la configuración del environment de juju, ¿hay alguna manera similar de configurar juju para una nube privada con Ubuntu Cloud Infraestructure utilizando MAAS?, es decir, ¿es similar el procedimiento de configuración de una nube privada como de una publica?.

Comment by Jamelgo on 2013-06-10 11:27:50 +0000

Esto está bastante desfasado.

Comment by Eduardo Peredo on 2013-12-03 20:29:36 +0000

Por lo que entiendo es una especie de consola para la administración de los “charms”, pero lo que me queda duda es si la administración es local o remota. Jugare con juju un rato para averiguarlo.

Publicado en General | Etiquetado

Instalando Openstack Glance

Hoy toca jugar con un nuevo servicio de Openstack, liberado hace muy poco tiempo, y que todavia se encuentra en fase “experimental”: Openstack Glance.

Podríamos definir a este proyecto como un servicio de gestión de imagenes de máquinas virtuales, con el objetivo de independizar el sistema de computación o almacenamiento de la gestión de las imagenes. De esta forma, podríamos llegar a instanciar imagenes que se encontrasen almacenadas en localizaciones diferentes (incluso en sistemas gestionados por terceros: ¿un proveedor especializado en imagenes?), o podríamos guardar copias de seguridad de instantáneas en otro centro de datos (por temas de DR), o podríamos almacenar nuestras imagenes en nuestro repositorio, y cambiar de proveedor de IaaS tantas veces como quisiésemos sin tener que estar ligado a ellos (vendor lockin), o podríamos … siempre y cuando los proveedores adopten Glance, claro está (que fácil es soñar 🙂 ). En definitiva, un proyecto con mucho potencial, aunque a expensas de que se convierta en un estándard y los proveedores lo quieran adoptar.

El proyecto se divide en 2 servicios:

  • glance-registry“, un servicio que nos permite registrar y descubrir imagenes de máquinas virtuales;
  • glance-api“, un servicio que nos permite almacenar y recuperar imagenes de máquinas virtuales en repositorios diversos. A dia de hoy los repositorios pueden ser: un almacen en Amazon S3, un almacen en Openstack Swift, un sistema de ficheros, o un almacen HTTP.

Pues bien, una vez definido el proyecto, detallemos las instrucciones de instalación. Como he dicho anteriormente, el proyecto todavia es experimental, con lo que nos encontraremos muchas cosas por pulir.

En primer lugar añadiremos el repositorio PPA de Launchpad donde se encuentra el proyecto y lo instalaremos con el metodo habitual:

~$ sudo add-apt-repository ppa:glance-core/trunk
~$ sudo apt-get update
~$ sudo apt-get install glance

Ahora debemos configurar los servicios. Desgraciadamente el paquete no lleva ningún ejemplo de archivo de configuración, por lo que lo tendremos que crearlo a mano:

~$ cd
~$ mkdir glance
~$ cd glance

A continuación copiad el siguiente texto en vuestro editor preferido y guardarlo como glance.conf. Para vuestra comodidad, lo podeis descargar de aquí (acordaos de renombrarlo como glance.conf):

[DEFAULT]
# Show more verbose log output (sets INFO log level output)
verbose = True
# Show debugging output in logs (sets DEBUG log level output)
debug = False
[app:glance-api]
paste.app_factory = glance.server:app_factory
# Directory that the Filesystem backend store
# writes image data to
filesystem_store_datadir=/var/lib/glance/images/
# Which backend store should Glance use by default is not specified
# in a request to add a new image to Glance? Default: 'file'
# Available choices are 'file', 'swift', and 's3'
default_store = file
# Address to bind the API server
bind_host = 0.0.0.0
# Port the bind the API server to
bind_port = 9292
# Address to find the registry server
registry_host = 0.0.0.0
# Port the registry server is listening on
registry_port = 9191
[app:glance-registry]
paste.app_factory = glance.registry.server:app_factory
# Address to bind the registry server
bind_host = 0.0.0.0
# Port the bind the registry server to
bind_port = 9191
# SQLAlchemy connection string for the reference implementation
# registry server. Any valid SQLAlchemy connection string is fine.
# See: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/connections.html#sqlalchemy.create_engine
sql_connection = sqlite:///glance.sqlite
# Period in seconds after which SQLAlchemy should reestablish its connection
# to the database.
#
# MySQL uses a default `wait_timeout` of 8 hours, after which it will drop
# idle connections. This can result in 'MySQL Gone Away' exceptions. If you
# notice this, you can lower this value to ensure that SQLAlchemy reconnects
# before MySQL can drop the connection.
sql_idle_timeout = 3600

El siguiente paso es arrancar los servicios, tanto el registry como el servidor api. Podemos arrancarlos de forma independiente, pero en este caso vamos a hacerlo de forma conjunta:

~/glance$ sudo glance-control all start

Si todo ha ido bien, el sistema nos dirá que ha arrancado los 2 servicios y que ha utilizado el archivo de configuración glance.conf:

Starting glance-api with /home/ferdy/glance/glance.conf
Starting glance-registry with /home/ferdy/glance/glance.conf

Para comprobar que todo está correcto, vamos a lanzar una consulta al servidor api. Para ello utilizaremos curl, aunque podemos realizar la misma prueba desde nuestro navegador:

~/glance$ curl http://localhost:9292

Y el servidor nos devolverá las imagenes registradas (en este caso, ninguna):

{"images": []}

Ahora vamos a almacenar una imagen de una máquina virtual. En primer lugar nos descargamos una imagen de Ubuntu (si ya tenéis una imagen, podeis saltaos este paso), y luego la almacenaremos y registraremos en el sistema:

~/glance$ wget http://uec-images.ubuntu.com/maverick/current/maverick-server-uec-amd64.tar.gz
~/glance$ glance-upload --type raw maverick-server-uec-amd64.tar.gz "Ubuntu Maverick 10.10"

Como respuesta recibiremos los metadatos de la imagen:

Stored image. Got identifier: {u'created_at': u'2011-03-04T23:47:58.145889',
 u'deleted': False,
 u'deleted_at': None,
 u'id': 1,
 u'is_public': True,
 u'location': u'file:///var/lib/glance/images/1',
 u'name': u'Ubuntu Maverick 10.10',
 u'properties': {},
 u'size': 187634470,
 u'status': u'active',
 u'type': u'raw',
 u'updated_at': None}

Ahora volvemos a realizar la consulta sobre el servidor api, y veremos que ya tenemos registrada nuestra imagen:

~/glance$ curl http://localhost:9292
{"images": [
   {"type": "raw",
    "id": 1,
    "name": "Ubuntu Maverick 10.10",
    "size": 187634470}
  ]
}

Incluso podemos pedirle que nos devuelva los metadatos completos de las imagenes registradas:

~/glance$ curl http://localhost:9292/images/detail
{"images": [
   {"status": "active",
    "name": "Ubuntu Maverick 10.10",
    "deleted": false,
    "created_at": "2011-03-04T23:47:58.145889",
    "updated_at": "2011-03-04T23:48:02.011583",
    "id": 1,
    "location": "file:///var/lib/glance/images/1",
    "is_public": true,
    "deleted_at": null,
    "type": "raw",
    "properties": {},
    "size": 187634470}
   ]
}

Y en el caso de que tengamos varias imagenes y queramos obtener los metadatos de una imagen en concreto, podemos utilizar el siguiente comando (aunque en este caso nos los devuelve en forma de headers de HTTP):

~/glance$ curl -I http://localhost:9292/images/1
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 0
X-Image-Meta-Type: raw
X-Image-Meta-Id: 1
X-Image-Meta-Deleted: False
X-Image-Meta-Location: file:///var/lib/glance/images/1
X-Image-Meta-Properties: {}
X-Image-Meta-Deleted_at: None
X-Image-Meta-Created_at: 2011-03-04T23:47:58.145889
X-Image-Meta-Size: 187634470
X-Image-Meta-Status: active
X-Image-Meta-Is_public: True
X-Image-Meta-Updated_at: 2011-03-04T23:48:02.011583
X-Image-Meta-Name: Ubuntu Maverick 10.10
Date: Fri, 04 Mar 2011 23:57:05 GMT

Y nada más, ya que de momento las opciones por línia de comando son muy limitadas. De igual forma, a dia de hoy no hay integración con el sistema de computación nova, por lo que tendremos que esperar a que un futuro no muy lejano se vayan ampliando las funcionalidades de este proyecto.

Y como siempre, antes de acabar, acordaos de apagar los servicios:

~/glance$ sudo glance-control all stop
Stopping glance-api  pid: 3518  signal: 15
Stopping glance-registry  pid: 3519  signal: 15

Comments

Comment by Diego Parrilla on 2011-03-05 09:38:55 +0000

Gran post. Glance está verde todavía, pero la posibilidad de tener un registros distribuidos de imágenes por la red es algo muy potente.

En el Roadmap futuro el registro también realizará conversiones entre diferentes formatos de disco virtual y de contenedor (ovf, vmx, ami…). En ese punto lo incorporaremos a la distro de StackOps.

Diego Parrilla

StackOps CEO

Comment by ferdy on 2011-03-06 00:52:44 +0000

Gracias Diego. Coincido contigo que este proyecto promete bastante, y creo además, que favorecerá que aparezcan negocios relacionados con el almacenamiento y provisioning de imagenes.

Comment by Armando on 2011-03-21 10:46:16 +0000

pero donde esta el paquete de instalación!!

eske tengo al profe aquí al lado i no para!!

Comment by ferdy on 2011-03-21 23:47:24 +0000

Armando, ejecuta:

~$ sudo add-apt-repository ppa:glance-core/trunk
~$ sudo apt-get update
~$ sudo apt-get install glance

Y te instalará el paquete.

Comment by Francisco on 2011-04-05 02:17:15 +0000

Que tal, esta muy bueno el blog, me ha ayudado mucho.

Podrían por favor colocar mas referencias a servidores que podemos cargar usando glance?

Estamos experimentando con esta aplicación, pero me gustaria probarla lo mas que sea posible.

Muchas gracias.

Comment by daniel on 2014-03-04 18:32:39 +0000

alguien me puede ayudar a subir imagenes ISO a openstack lo tengo instalado pero no he podido subir nada aun, la maquina de cirros funciona super bien

Publicado en General | Etiquetado

Instalando el Dashboard de Openstack

Como lo prometido es deuda, aquí teneis las instrucciones para manejar openstack desde una consola web en vez de la línea de comandos.

Lo primero que debéis hacer es instalar el sistema de control de versiones bazaar, ya que el dashboard de Openstack todavia no está disponible en forma de paquete:

~$ sudo apt-get install bzr

A continuación vamos a instalar el módulo que contiene la interfaz para actuar con el controlador de openstack (django-nova):

~$ mkdir src
~$ cd src
~/src$ mkdir django-nova
~/src$ cd django-nova
~/src/django-nova$ bzr init-repo .
~/src/django-nova$ bzr branch lp:django-nova/trunk

Ahora instalaremos el módulo que contiene el dashboard (openstack-dashboard). Este módulo es una referencia que ha de servir de ejemplo para que otras empresas creen sus propios dashboards, y a dia de hoy no esta claro que en futuro se convierta en oficial, aunque a efectos de este tutorial ya nos vale:

~/src/django-nova$ cd ..
~/src$ mkdir openstack-dashboard
~/src$ cd openstack-dashboard
~/src/openstack-dashboard$ bzr init-repo .
~/src/openstack-dashboard$ bzr branch lp:openstack-dashboard trunk

Antes de arrancar la consola, debemos ajustar algunos parametros. En primer lugar creamos y editamos el archivo de configuración (_localsettings.py):

~/src/openstack-dashboard$ cd trunk/local
~/src/openstack-dashboard/trunk/local$ cp local_settings.py.example local_settings.py
~/src/openstack-dashboard/trunk/local$ vi local_settings.py

En este archivo debemos especificar los siguientes parámetros:

  • NOVA_ACCESS_KEY: debemos especificar el contenido de la variable EC2_ACCESS_KEY que encontrareis en el archivo novarc
  • NOVA_SECRET_KEY: debemos especificar el contenido de la variable EC2_SECRET_KEY que encontrareis en el archivo novarc
  • NOVA_ADMIN_USER: debemos especificar el contenido de la variable NOVA_USERNAME que encontrareis en el archivo novarc
  • NOVA_PROJECT: debemos especificar el nombre de un proyecto sobre el que el usuario indicado anteriormente tengo permisos

Ahora ya podemos seguir con el proceso de configuración:

~/src/openstack-dashboard/trunk/local$ apt-get install -y python-setuptools
~/src/openstack-dashboard/trunk/local$ cd ..
~/src/openstack-dashboard/trunk$ sudo easy_install virtualenv
~/src/openstack-dashboard/trunk$ python tools/install_venv.py ../../django-nova/trunk
~/src/openstack-dashboard/trunk$ tools/with_venv.sh dashboard/manage.py syncdb

En este punto, el proceso de instalación nos pedirá si queremos crear un usuario administrador de la consola. Indicamos que si queremos crearlo, y nos preguntará por un nombre de usuario, nuestro email y una contraseña para el usuario a crear:

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'ferdy'):
E-mail address: YOUR_EMAIL
Password: PASSWORD
Password (again): PASSWORD

Una vez instalados y configurados todos los módulos, vamos a arrancar el servidor web:

~/src/openstack-dashboard/trunk$ tools/with_venv.sh dashboard/manage.py runserver 0.0.0.0:8000

Y ahora nos conectaremos al dashboard utilizando la URL http://localhost:8000. Lo primero que nos aparecerá será la pantalla de login, donde introduciremos el usuario y contraseña que hemos creado anteriormente:

Una vez conectados nos aparece una pantalla con la relación de nuestros proyectos:

Si consultamos “Miproyecto” os aparece el dashboard con las acciones que podeis realizar sobre el:

En primer lugar vamos a consultar las imagenes publicadas. Pulsamos sobre el enlace de “Images” situado en el menu de la izquierda y nos aparece la relación de imagenes disponibles:

Si pulsamos en el identificador de la imagen emi (campo ID), nos aparecen los detalles de la imagen:

Ahora vamos a instanciarla. Pulsamos sobre “Launch“, y nos aparece una pantalla donde podremos indicar las características de la instancia que queremos arrancar. Escogemos que solo queremos arrancar 1 instancia, indicamos el tipo de instancia (m1.small – Memory: 2048MB, VCPUS: 1) y le asignamos la credencial miclave:

Ya tenemos la instancia lanzada. La aplicación nos dirigirá a la pantalla de instancias donde podreís ver todas las instancias junto con el estado de las mismas (campo State) y la dirección IP asignada:

Si pulsamos en el identificador de una instancia (camp ID), nos aparecen los detalles de la instancia:

Mientras esperamos a que la instancia esté disponible (estado running), nos vamos a ver las credenciales disponibles. Pulsamos sobre el enlace de Keys situado en el menu de la izquierda y nos aparece la relación de claves disponibles:

Si pulsamos sobre el enlace de Volumes en el menu de la izquierda, podremos ver la relación de volumenes de almacenamiento disponibles:

Ahora volvemos a las instancias para comprobar si ya esta disponible:

En caso de que así sea, podeis abrir una sesión de terminal y conectaros via SSH a vuestra instancia. Y como siempre, una vez os hayáis cansado de jugar, no os olvideis de apagar la instancia pulsando sobre “Terminate“:

Para próximos posts, intentaré explicar como configurar la gestión de almacenamiento.

Comments

Comment by rmacian on 2011-04-28 17:45:11 +0000

Hola,

Primero de todos felicitarte por la cantidad de contenido por la brevedad de proyecto.

He seguido la entrada de instalación y este y cuando ya estoy intentando arrancar la instancia se me queda en scheduling. Mirando los logs veo que aparece un error

Error: libvirt version is too old (does not support getVersion). Los paquetes instalados son los propios de launchpad excepto uno

# dpkg -l | grep libvirt

ii libvirt-bin 0.8.8-1ubuntu3~ppalucid1 the programs for the libvirt library

ii libvirt0 0.8.8-1ubuntu3~ppalucid1 library for interfacing with different virtu

ii python-libvirt 0.7.5-5ubuntu27.9 libvirt Python bindings

Alguna idea ?

Comment by ferdy on 2011-04-29 03:44:27 +0000

Hola, el problema lo tienes precisamente en el paquete del binding de Python para libvirt (python-libvirt), ya que, tal como dice el error, la version que tienes es obsoleta. Esta comprobación se introdujo en nova hace 1 mes aprox .

Has probado a actualizar solo este paquete?

Comment by chetan on 2011-06-24 15:33:25 +0000

Hello ,

We testing Openstack with single node environment , alll is going well , however having problem installing openstack-dashboard end up with error :

Installing custom SQL …

Installing indexes …

No fixtures found.

next we able to run WebUserInterFace however no way to login :shows erro 1110 [connection refused].

my local_setttng.py :

import os

DEBUG = True

TEMPLATE_DEBUG = DEBUG

PROD = False

USE_SSL = False

LOCAL_PATH = os.path.dirname(os.path.abspath(\__file__))

DATABASES = {

‘default’: {

‘ENGINE’: ‘django.db.backends.sqlite3’,

‘NAME’: os.path.join(LOCAL_PATH, ‘dashboard_openstack.sqlite3’),

},

}

CACHE_BACKEND = ‘dummy://’

# Send email to the console by default

EMAIL_BACKEND = ‘django.core.mail.backends.console.EmailBackend’

# Or send them to /dev/null

#EMAIL_BACKEND = ‘django.core.mail.backends.dummy.EmailBackend’

# django-mailer uses a different settings attribute

MAILER_EMAIL_BACKEND = EMAIL_BACKEND

EMAIL_HOST = ‘localhost’

EMAIL_PORT = 25

# Configure these for your outgoing email host

# EMAIL_HOST = ‘smtp.my-company.com’

# EMAIL_PORT = 25

# EMAIL_HOST_USER = ‘djangomail’

# EMAIL_HOST_PASSWORD = ‘top-secret!’

OPENSTACK_ADMIN_TOKEN = “999888777666”

OPENSTACK_KEYSTONE_URL = “http://localhost:5000/v2.0/&#8221;

TOTAL_CLOUD_RAM_GB = 30

NOVA_DEFAULT_ENDPOINT = ‘http://localhost:8773/services/Cloud&#8217;

NOVA_DEFAULT_REGION = ‘nova’

NOVA_ACCESS_KEY = ‘261c1aac-398c-4f5d-9b1e-0b6a58d8d90d:nubeblog’

NOVA_SECRET_KEY = ‘8dec5030-11a2-4569-b7a9-8ffbcc7f2c5d’

NOVA_ADMIN_USER = ‘diego’

NOVA_PROJECT = ‘nubelog’

Comment by ferdy on 2011-06-25 14:57:43 +0000

Chetan, I suggest you to open a ticket at the Dashboard for OpensStack Launchpad site.

Publicado en General | Etiquetado

Instalando Openstack

He estado jugando estos últimos dias con OpenStack, una plataforma IaaS de código abierto que nos permite la creación de recursos de computación (OpenStack Nova) y almacenamiento (OpenStack Swift) en la nube. El proyecto, liderado originalmente por Rackspace y la Nasa, y a los que se les han añadido últimamente una importante comunidad de desarrolladores, fue creado hace tan solo unos pocos meses (Diego nos explica en su blog la historia de este proyecto), y aunque a dia de hoy sigue estando inmaduro, la última versión liberada (Bexar) ya comienza a ser “usable”.

Si os animais a probarla, os detallo a continuación los pasos que hay que seguir para su instalación, aunque podeis encontrar mucha más información en la wiki o en los manuales del proyecto.

En primer lugar vamos a añadir el repositorio PPA de Launchpad. En mi caso, como me gusta jugar con fuego, voy a utilizar el repositorio donde se encuentran los paquetes “bleeding edge”, es decir, el repositorio donde se encuentran los últimos commits que se hayan hecho sobre el tronco:

~$ sudo apt-get install python-software-properties
~$ sudo add-apt-repository ppa:nova-core/trunk
~$ sudo apt-get update

(en caso de que querais utilizar la última versión estable, cambiad el ppa:nova-core/trunk por ppa:nova-core/release)

A continuación instalamos el paquete de nova junto con sus dependencias (es importante instalar primero el servidor de RabbitMQ):

~$ sudo apt-get install rabbitmq-server
~$ sudo apt-get install nova-common nova-doc nova-api nova-network nova-objectstore nova-scheduler nova-compute
~$ sudo apt-get install euca2ools unzip

El siguiente paso es configurar el paquete. En general, podeis dejar los ajustes por defecto (que se encuentran en /etc/nova/nova.conf), aunque en mi caso he tenido que realizar una pequeña modificación: si ejecutais el software en una máquina virtual (por ejemplo VirtualBox o Parallels), será necesario añadir al archivo nova.conf la siguiente línia:

--libvirt_type=qemu

Antes de comenzar a jugar, vamos a reiniciar por si acaso el servicio libvirt (la interfaz para interactuar con diferentes tecnologías de virtualización):

~$ sudo service libvirt-bin restart

Acto seguido configuramos una red para nuestras máquinas virtuales. En este caso utilizaremos la dirección CIDR 10.0.0.0/8, sobre la que crearemos 1 red virtual con 64 direcciones IP:

~$ sudo nova-manage network create 10.0.0.0/8 1 64

Ahora nos creamos un usuario (ferdy) y un proyecto (miproyecto), nos descargaremos las credenciales (que vendrán empaquetadas en el archivo nova.zip) y cargaremos en nuestro profile de usuario las variables necesarias para interactuar con el proyecto:

~$ cd
~$ mkdir proyecto-nova
~$ cd proyecto-nova
~/proyecto-nova$ sudo nova-manage user admin ferdy
~/proyecto-nova$ sudo nova-manage project create miproyecto ferdy
~/proyecto-nova$ sudo nova-manage project zipfile miproyecto ferdy
~/proyecto-nova$ unzip nova.zip
~/proyecto-nova$ . novarc

Llegados a este punto ya tenemos todo configurado. Es hora de descargarse una imagen y publicarla en un bucket (por ejemplo: mibucket). En este caso vamos a utilizar una imagen de Ubuntu Server de 64bits (en el repositorio de Ubuntu podeis encontrar más imagenes):

~/proyecto-nova$ wget http://uec-images.ubuntu.com/maverick/current/maverick-server-uec-amd64.tar.gz
~/proyecto-nova$ uec-publish-tarball maverick-server-uec-amd64.tar.gz mibucket

Como resultado nos informará del identificador de imagen (emi), el identificador de kernel (eki) y el identificador de ramdisk (eri):

emi="ami-dqay5v06"; eri="none"; eki="ami-7l5uc5w8";

Es importante recordar el identificador de imagen, ya que será el que utilizemos en la creación de instancias, pero si por cualquier razón lo olvidamos, con el comando euca-describe-images podremos ver las imagenes publicadas junto con su emi:

IMAGE <b>ami-dqay5v06</b> mibucket/maverick-server-uec-amd64.img.manifest.xml	miproyecto  available	private		x86_64	machine	ami-7l5uc5w8
IMAGE ami-7l5uc5w8 mibucket/maverick-server-uec-amd64-vmlinuz-virtual.manifest.xml miproyecto	available	private		x86_64	kernel	true

A continuación nos crearemos un par de claves (miclave) para poder acceder a nuestras máquinas virtuales:

~/proyecto-nova$ euca-add-keypair miclave > miclave.priv
~/proyecto-nova$ chmod 0600 miclave.priv

Y crearemos una regla en el grupo de seguridad por defecto para autorizar el trafico entrante por el puerto 22 (SSH):

~/proyecto-nova$ euca-authorize default -P tcp -p 22 -s 0.0.0.0/0

Llegados a este punto ya podemos instanciar la máquina virtual. En este caso utilizaremos una instancia de tipo pequeño (m1.tiny – Memory: 512MB, VCPUS: 1) y le asignaremos la credencial creada anteriormente (miclave). Acordaos de cambiar el identificador de la imagen por el vuestro:

~/proyecto-nova$ euca-run-instances <i>ami-dqay5v06</i> -k miclave -t m1.tiny

Que como resultado nos informará del identificador de instancia (i-nnnnnnnn) y el estado (en este caso scheduling):

RESERVATION	r-6nwfk587 miproyecto	default
INSTANCE	<b>i-00000001</b> ami-dqay5v06 <b>scheduling</b>	miclave (miproyecto, None) 0	 m1.tiny	2011-03-02T23:17:32Z	unknown zone

Ahora vamos a esperar a que la instancia arranque. Con el comando euca-describe-instances podemos conocer en que estado se encuentra y si se le ha asignado ya una dirección IP:

RESERVATION	r-6nwfk587 miproyecto	default
INSTANCE	i-00000001 ami-dqay5v06	<b>10.0.0.3</b>	10.0.0.3	<b>launching</b>	miclave (miproyecto, ubuntu)	0	m1.tiny	2011-03-02T23:17:32Z	nova

Una vez el estado pase a running:

RESERVATION	r-6nwfk587 miproyecto	default
INSTANCE	i-00000001 ami-dqay5v06	10.0.0.3	10.0.0.3	<b>running</b>	miclave (miproyecto, ubuntu)	0	m1.tiny	2011-03-02T23:17:32Z	nova

es hora de conectarnos a nuestra instancia. Para ello utilizaremos un SSH con las credenciales obtenidas anteriormente y la IP asignada a nuestra instancia:

~/proyecto-nova$ ssh -i miclave.priv root@<i>10.0.0.3</i>

Y finalmente, cuando os hayáis cansado de jugar, acordaos de apagar la instancia con el comando:

~/proyecto-nova$ euca-terminate-instances <i>i-00000001</i>

En el próximo post explicaré como manejar estas instancias desde una consola web en vez de la línea de comandos.

Comments

Comment by Carlos on 2011-06-29 00:17:42 +0000

Muy bueno tu blog

Mi nombre es Carlos me gustaria saber mas sobre este tema y poder implemetar Open Stack

No se si me puedes recomendar alguna pagina o libro en internet para poder informarme mejor muchas gracias y sigue adelante

Comment by ferdy on 2011-06-29 01:22:04 +0000

Carlos, la página de documentación de OpenStack es un buen lugar de inicio. Y si no quieres complicarte la vida instalando OpenStack manualmente, puedes utilizar la distro de StackOps.

Comment by Hernan Nina on 2011-10-03 04:15:16 +0000

Hola Ferdy,

Gracias por el Blog sobre OpenStack.

Que diferencia existe OpenStack con Adobe EC2

Saludos Gracias

Publicado en General | Etiquetado