Arquitecturas Cloud para TIC
Temas abordados
Arquitecturas Cloud para TIC
Temas abordados
Objetivos
De la asignatura
● Conocer los conceptos relacionados con el proceso de virtualización tanto de
software como de hardware y ponerlos en práctica.
● Justificar la necesidad de procesamiento virtual frente a real en el contexto de
una infraestructura TIC de una organización.
● Optimizar aplicaciones sobre plataformas virtuales.
● Conocer diferentes tecnologías relacionadas con la virtualización
(Computación Nube, Utility Computing, Software as a Service) e
implementaciones tales como Google AppSpot, OpenShift o Heroku.
Específicos
1. Comprender los ecosistemas de despliegue de aplicaciones modernos y su
relación con la nube.
2. Entender las diferentes arquitecturas de software modernas y su relación con
cloud computing.
3. Aprender diseños que se puedan usar más adelante en aplicaciones
desplegables en la nube.
Introducción
Puedes echarle un vistazo a esta colección de transpas con información de un par
de presentaciones sobre arquitectura moderna de aplicaciones. Aunque centrado en
microservicios, este conjunto de patrones menciona también algunos de los que
veremos aquí.
El panorama informático del siglo XXI está lleno de posibilidades: múltiples lugares
donde ejecutar una aplicación, múltiples servicios que se pueden usar desde ella,
todos conectados a través de Internet, y metodologías específicas para desarrollar
aplicaciones. Se hace difícil concretar en una arquitectura específica, entendiendo
por arquitectura una visión de bloques de los diferentes componentes de una
aplicación, su situación física y lógica y la relación entre ellos. Resulta bastante
claro, sin embargo, que una arquitectura monolítica con un cliente ejecutando el
interfaz de usuario y un servidor, replicado o no pero ejecutando todos los
componentes de una aplicación, no resulta adecuada para las aplicaciones
modernas ni por sus características de escalado ni por el reparto de tareas y datos
entre diferentes partes de un equipo de desarrollo.
Arquitecturas software
En gran parte, este apartado está sacado de Software Architecture Patterns, de
Mark Richards, un ebook gratuito que te puedes descargar dando tu email, lo que
aconsejo vivamente que hagas.
Arquitectura en capas
La arquitectura en capas o multilayer es el desarrollo natural de la arquitectura
cliente-servidor, creando 3 o más capas entre las que se suele incluir la capa de
presentación, la de aplicación, la de lógica de negocio y la de acceso a datos.
Muchos marcos de desarrollo modernos trabajan de esta forma y son relativamente
simples de desarrollar. El problema principal es que sólo permiten escalado dentro
de cada una de las capas, siendo al final alguna de ellas un cuello de botella.
Algunos marcos de aplicaciones como Java Swing usan este tipo de arquitectura.
Arquitectura microkernel
Se trata de una arquitectura más o menos monolítica, con un núcleo central al que
se pueden añadir funcionalidades mediante plugins. Un tipo de arquitectura clásico
que se usa en CMSs como Joomla o en sistemas de aprendizaje como Moodle. El
problema principal es la escalabilidad, ya que el núcleo puede representar un cuello
de botella.
Resumen
Todos los patrones anteriores se usan en la actualidad junto con el patrón de
aplicación cliente-servidor, que sigue perviviendo, pero que causa todo tipo de
problemas de escalado, sobre todo, aparte de la dificultad de desarrollo si no se
hace con cuidado.
En casi todos los casos en que se despliegue una arquitectura en la nube se tendrá
que hacer uso de este tipo de sistemas. Muchos orquestadores como Kubernetes
tienen los suyos propios, pero familiarizarse con otros como e tcd o c onsul puede
ayudar a entender su funcionamiento y, sobre todo, a usarlo en nuestras propias
arquitecturas que no usen orquestadores.
Objetivos de la asignatura
● Diseñar, construir y analizar las prestaciones de un centro de proceso de
datos virtual.
● Documentar y mantener una plataforma virtual.
● Realizar tareas de administración en infraestructura virtual.
Objetivos específicos
1. Aprender lenguajes de configuración usados en infraestructuras virtuales.
2. Saber cómo aplicarlos en un caso determinado.
3. Conocer los sistemas de gestión de la configuración, provisionamiento y
monitorización más usados hoy en día.
Introducción
Los gestores de configuraciones trabajan sobre máquinas virtuales ya creadas y en
funcionamiento, describiendo la configuración que necesitan para ejecutar una
aplicación determinada. Proporcionan infraestructura como código, permitiendo
describir los sistemas en los que se va a ejecutar código como si de un programa se
tratara, con todo lo que ello conlleva: control de código y testeo, por ejemplo.
Hay muchos gestores de configuraciones: Chef, Salt, Ansible, mgmt (este último un
poco experimental) y Puppet, por ejemplo. Todos son libres, pero tienen
características específicas que hay que tener en cuenta a la hora de elegir uno u
otro. En el caso específico de sistemas operativos, que es del que vamos a hablar
aquí, se trata de gestionar automáticamente todas las tareas de configuración de un
sistema, automatizando la edición de ficheros de configuración, instalación de
software y configuración del mismo, creación de usuarios y autenticación, de forma
que se pueda hacer de forma automática y masiva.
Para poder configurar máquinas virtuales específicas primero hay que instanciarlas.
Dejaremos para más adelante cómo hacerlo de forma independiente del proveedor
de tales servicios y veremos a continuación cómo preparar una máquina virtual para
ser provisionada.
Hay varios tutoriales que te permiten, con relativa rapidez, comenzar a trabajar con
Chef-solo en un servidor; este te proporciona una serie de ficheros que puedes usar
y este otro es más directo, dando una serie de órdenes. En todo caso, se trata
básicamente tener acceso a un servidor o máquina virtual, instalar una serie de
aplicaciones en él y ejecutarlas sobre un fichero de configuración
En esta página indican como descargar Chef para todo tipo de distribuciones.
Vamos a usar principalmente chef-solo, una herramienta que se tiene que ejecutar
desde el ordenador que queramos provisionar.
Vamos a empezar a escribir una recetilla del Chef. Generalmente, escribir una
receta es algo más complicado, pero comenzaremos por una receta muy simple que
instale el imprescindible e macs y le asigne un nombre al nodo. Creamos el directorio
chef en algún sitio conveniente y dentro de ese directorio irán diferentes ficheros.
package 'emacs'
directory '/home/jmerelo/Documentos'
file "/home/jmerelo/Documentos/LEEME" do
owner "jmerelo"
group "jmerelo"
mode 00544
action :create
content "Directorio para documentos diversos"
end
El nombre del fichero indica que se trata de la receta por omisión, pero el nombre de
la receta viene determinado por el directorio en el que se meta, que podemos crear
de un tirón con
mkdir -p chef/cookbooks/emacs/recipes
Este fichero tiene tres partes: instala el paquete emacs, crea un directorio para
documentos y dentro de él un fichero que explica, por si hubiera duda, de qué se
trata. Evidentemente, tanto caminos como nombres de usuario se deben cambiar a
los correspondientes en la máquina virtual que estemos configurando.
Este fichero hace referencia a un recetario, emacs y dado que no se especifica nada
más se ejecutará la receta por defecto.
file_cache_path "/home/jmerelo/chef"
cookbook_path "/home/jmerelo/chef/cookbooks"
json_attribs "/home/jmerelo/chef/node.json"
Una vez más, cambiando los caminos por los que correspondan. Para ejecutarlo,
(si se ejecuta desde el directorio raíz). Esta orden producirá una serie de mensajes
para cada una de las órdenes y, si todo va bien, tendremos este útil editor instalado.
Crear una receta para instalar nginx, tu editor favorito y algún directorio y fichero que
uses de forma habitual.
Para usar chef-solo hay simplemente que instalar unos cuantos programas, pero en
gran parte ya está automatizado: aquí explica como usarlo en Ubuntu, por ejemplo
basándose en este Gist (programas cortos en GitHub) que instala todas las
herramientas necesarias para comenzar a ejecutar chef.
Este curso en vídeo te enseña también a trabajar con Chef, aunque con la edad que
tiene es posible que esté un poco obsoleto.
{ "uno": "dos",
"tres": [ 4, 5, "Seis", { "siete": 8, "nueve": [ 10, 11 ] } ] }
Normalmente estas recetas van a estar bajo control de un sistema de gestión de
fuentes; de esta forma se pueden probar diferentes configuraciones, crear nuevas
versiones de la misma pero, sobre todo, tener claro en cada momento qué
configuración es la que se está ejecutando en producción, que será habitualmente la
que esté en una rama designada de la misma.
Una vez instalado salt-ssh, una de los principales problemas es que requiere una
cierta cantidad de configuración global. Generalmente vamos a usar un directorio tal
como ~ /lib/salt/ como directorio de trabajo y configuración; y este directorio va a
estar fuera del repositorio y en un directorio de superusuario por omisión. Se puede
usar el directorio local, pero en ese caso habrá que decir específicamente donde se
encuentra cada tipo de fichero. En el R EADME.md del bot vienen las instrucciones
necesarias para crear ese fichero de provisionamiento y la configuración global.
Pero para configurar nuestro propio sistema, uno de los más importantes es el
fichero roster:
app:
host: 104.196.9.185
user: one_user
sudo: True
Aquí no sólo se declara la dirección a la que vamos a conectar, sino también si hace
falta ser sudo o no. Con esto podemos ejecutar ya parte de la configuración que
vamos a ejecutar más adelante:
salt-ssh '*' --roster-file=./roster -r "sudo apt-get install python-apt" -c ~/lib/salt
--force-color
En este caso, se trata de ejecutar una orden para poder instalar python-apt, un
módulo para poder ejecutar órdenes de instalación de paquetes directamente desde
Python.
Pero para efectivamente provisionar se usan ficheros salt-stack. Por ejemplo, estos
ficheros instalan Java en la versión necesaria para poder instalar más adelante
Scala. Y Scala lo instalamos en este fichero
include:
- javasetup
scala:
pkg.installed
Este programa, como Ansible, actúa de manera descriptiva. Indica que el paquete
scala tiene que estar instalado, pero para ello tiene que cumplir una serie de
prerrequisitos incluidos en el fichero j avasetup.sls; el nombre de estado se tiene que
corresponder con el nombre del fichero en sí. Este a su vez requiere la instalación
de otra serie de paquetes, e incluye otro fichero. Lo bueno es que esos dos ficheros,
javasetup y j ava, se pueden usar para todos los paquetes que usen esa máquina
virtual; para instalar Scala sólo hay que crear este último fichero.
Todos estos, por cierto, tienen que ejecutarse desde directorios específicos, al
menos la forma más simple de hacerlo es copiar todos los ficheros .sls a
~/lib/salt/states y hacerlo desde ahí.
En general, y por la forma que tiene un poco rígida de hacer las cosas, resulta algo
más complicado usarlo que Ansible o incluso Chef. Sin embargo y limitado a
salt-ssh, una vez que la configuración está completa y si se tienen configuraciones
base, construir a partir de ellas es relativamente sencillo.
Provisionar una máquina virtual en algún entorno con los que trabajemos
habitualmente usando Salt.
Otros sistemas de gestión de configuración
Las principales alternativas a Chef son Ansible, Salt y Puppet. Todos ellos se
comparan en este artículo, aunque los principales contendientes son Puppet y Chef,
sin que ninguno de los dos sea perfecto.
De todas ellas, vamos a ver Ansible que parece ser uno de los que se está
desarrollando con más intensidad últimamente. Ansible es un sistema de gestión
remota de configuración que permite gestionar simultáneamente miles de sistemas
diferentes. Está basado en YAML para la descripción de los sistemas y escrito en
Python.
Cada máquina que se añada al control de Ansible se tiene que añadir a un fichero,
llamado inventario, que contiene las diferentes máquinas controladas por el mismo.
Por ejemplo
se puede ejecutar desde el shell para meter (echo) una cadena con una dirección
(en este caso, una máquina virtual de Azure) en el fichero ansible_hosts situado en
mi directorio raíz. El lugar de ese fichero es arbitrario, por lo que habrá que avisar a
Ansible donde está usando una variable de entorno:
export ANSIBLE_HOSTS=~/ansible_hosts
[azure]
iv-ansible.cloudapp.net
Esta orden usa un módulo de ansible y se puede ejecutar también de esta forma:
haciendo uso del módulo shell. Hay muchos más módulos a los que se le pueden
enviar comandos del tipo "variable = valor". Por ejemplo, se puede trabajar con
servidores web o copiar ficheros o incluso desplegar aplicaciones directamente
usando el módulo git
Desplegar los fuentes de una aplicación cualquiera, propia o libre, que se encuentre
en un servidor git público en la máquina virtual Azure (o una máquina virtual local)
usando a nsible.
Finalmente, el concepto similar a las recetas de Chef en Ansible son los playbooks,
ficheros en YAML que le dicen a la máquina virtual qué es lo que hay que instalar en
tareas, de la forma siguiente
---
- hosts: azure
sudo: yes
tasks:
- name: Update emacs
apt: pkg=emacs state=present
Esto se guarda en un fichero y se le llama, por ejemplo, emacs.yml, y se ejecuta con
ansible-playbook ../../ejemplos/ansible/emacs.yml
(recordando siempre el temita del nombre de usuario), lo que dará, si todo ha ido
bien, un resultado como el siguiente
En el fichero YAML lo que se está expresando es un array asociativo con las claves
udo y t asks. En el primero ponemos el bloque de servidores en el que vamos
hosts, s
a actuar, en el segundo si hace falta hacer sudo o no y en el tercero las tareas que
vamos a ejecutar, en este caso una sola. El apartado de tareas es un vector de
hashes, cada uno de los cuales tiene en n ame el nombre de la tarea, a título
informativo y en las otras claves lo que se va a hacer; a pt indicará que hay que
instalar un paquete (pkg) llamado e macs y que hay que comprobar si está presente o
no (state). El que se trabaje conestados y no de forma imperativa hace que los
playbooks sean idempotentes, es decir, si se ejecutan varias veces darán el mismo
resultado que si se ejecutan una sola vez.
Bibliografía
Uno de los libros más interesantes es Infrastructure as Code, de Kief Morris. Hace
un resumen muy acertado de todos los principios que rigen la gestión de
infraestructura virtual a través de código y un repaso de todas las herramientas
usadas en el mismo. También está disponible como recurso electrónico en la
biblioteca de la UGR.
A partir de aquí se puede seguir aprendiendo sobre DevOps en el blog o en IBM.
Libros como DevOps for Developers pueden ser también de ayuda. Esta
comparativa de sistemas de configuración te permite ver todos los que hay, ver la
última columna cuáles son los más recientemente actualizados y qué esperar de
cada uno de ellos. También en este gist explica las diferencias entre herramientas
en este área, incluyendo también Puppet e incluso Docker. En presentaciones como
esta se habla de CAPS: Chef, Ansible, Puppet and Salt como una categoría en sí.
En este artículo también los comparan y en este último llevan a cabo la
configuración de un servidor simple usando los cuatro.
Objetivos
1. Conocer las diferentes tecnologías y herramientas de virtualización tanto para
procesamiento, comunicación y almacenamiento.
2. Diseñar, construir y analizar las prestaciones de un centro de proceso de
datos virtual.
3. Documentar y mantener una plataforma virtual.
4. Realizar tareas de administración de infraestructuras virtuales.
Introducción
El objetivo de las plataformas de virtualización es, eventualmente, crear y gestionar
una máquina virtual completa que funcione de forma aislada del resto del sistema y
que permita trabajar con sistemas virtualizados de forma flexible, escalable y
adaptada a cualquier objetivo. Eventualmente, el objetivo de este este tema es
aprender a crear infraestructura como servicio tal como vimos en el primer tema.
Para ello necesitamos configurar una serie de infraestructuras virtuales,
especialmentealmacenamiento como se vio en el tema anterior.
Por encima de los hipervisores están los sistemas de gestión de máquinas virtuales
en la nube que, aunque se puedan usar desde las mismas herramientas y con el
mismo cometido, en realidad abstraen el trabajo del hipervisor y permiten trabajar
con un API uniforme independientemente del hipervisor real que esté por debajo.
Estos sistemas de gestión de máquinas virtuales pueden ser libres, como
OpenStack u OpenNebula, o privativos, como los que se usan en la mayoría de los
sistemas de la nube. Todos, sin embargo, permiten realizar una serie de tareas que
veremos a continuación.
nos muestra detalles sobre la imagen; entre otras cosas dónde está disponible y
sobre si es Premium o no (en este caso no lo es). Con esta (o con otra) podemos
crear una máquina virtual
La máquina todavía no está funcionando. Con azure vm list nos muestra las
máquinas virtuales que tenemos y el nombre que se le ha asignado y finalmente con
azure vm start se arranca la máquina y podemos conectarnos con ella usando
sshUna de las primeras cosas que hay que hacer cuando se arranque es actualizar
el sistema para evitar problemas de seguridad. A partir de ahí, podemos instalar lo
que queramos. El arranque tarda cierto tiempo y dependerá de la disponibilidad de
recursos; evidentemente, mientras no esté arrancada no se puede usar, pero
conviene de todas formas apagarla con
cuando terminemos la sesión y no sea necesaria, sobre todo porque, dado que se
pagan por tiempo de uso, se puede incurrir en costes innecesarios o en agotamiento
de los recursos gratuitos proporcionados.
Crear una máquina virtual Ubuntu e instalar en ella un servidor nginx para poder
acceder mediante web.
az vm image list
Si se añade --all te devolverá todas las imágenes disponibles, pero ahora mismo
hay un bug registrado porque no se pueden usar en realidad con la línea de
órdenes. Así que nos ceñiremos a las imágenes disponibles localmente.
Esta te filtrará sólo aquellas imágenes que contengan buntu (no sabemos si va a
estar en mayúsculas o minúsculas), devolviendo algo así:
De esta imagen hay que usar dos IDs: urn y urnAlias, que nos permitirán identificar la
imagen con la que vamos a trabajar a continuación:
az vm create -g CCGroupEU -n bobot --image UbuntuLTS
En este caso creamos la máquina virtual llamada bobot con una imagen de
UbuntuLTS y az usa una clave SSH pública de nuestro directorio y nuestro nombre
de usuario para copiarlo directamente a la instancia creada. Puede tardar un rato en
crear la instancia, eso sí, pero devolverá un JSON que incluirá metadatos y su IP
pública como p ublicIpAddress. Una vez hecho eso, te puedes conectar directamente
a ella con su dirección IP y ssh.
Crear una instancia de una máquina virtual Debian y provisionarla usando alguna de
las aplicaciones vistas en el tema sobre herramientas de aprovisionamiento
CLI de OpenStack
OpenStack es un sistema libre de gestión de nubes privadas que se ha hecho muy
popular incluso en revendedores de sistemas como IBM u otros, que en realidad
ofrecen este tipo de acceso. Se puede probar en alguna instalación disponible en la
Facultad o Escuela o bien en TryStack si te admiten.
Como arriba, hay también un sistema de línea de órdenes, inicialmente uno para
cada uno de los subsistemas de OpenStack pero últimamente unificado a una sola
penstack. Para trabajar con él, tras descargar el cliente, hay que configurar
orden, o
una serie de variables de entorno descargándose un fichero, que él mismo pone las
API keys y demás. Una vez ejecutado ese script de configuración se puede, por
ejemplo, crear una clave para acceder a las instancias que se vayan a crear
que crea una clave llamada Try y la guarda en un fichero de clave privada.
Sin embargo, al menos en esta instalación de prueba, es más fácil trabajar con el
interfaz gráfico que con la línea de órdenes. En este tutorial te explica cómo crear el
par de claves. Una vez creada
● Hay que añadir el puerto 22 de ssh al grupo de seguridad que se vaya a usar
● Se tiene que crear una red y una subred para conectar la instancia a la
subred.
● Se tiene que crear un router al cual se conecta la red.
● Finalmente, se crea la instancia. Esto sí se puede hacer desde línea de
órdenes
● La orden anterior crea una instancia llamada bobot-x con una imagen de
Ubuntu (una de las que hay por defecto) y una red cuyo ID se extrae desde el
interfaz gráfico. El flavor es el tipo de instancia, esta es una de las que hay
disponibles.
● Una vez creada la instancia, se le asigna una IP flotante para poder acceder
desde fuera, teóricamente de esta forma, aunque da error (Conflict) al menos
a mi
● Si eso falla, se puede asignar una IP flotante desde el interfaz gráfico, yendo
a la lista de instancias.
Objetivos de la asignatura
● Diseñar, construir y analizar las prestaciones de un centro de proceso de
datos virtual.
● Documentar y mantener una plataforma virtual.
● Realizar tareas de administración en infraestructura virtual.
Objetivos específicos
1. Aprender lenguajes de configuración usados en infraestructuras virtuales.
2. Saber cómo aplicarlos en un caso determinado.
3. Conocer los sistemas de orquestación de máquinas virtuales.
Introducción
Antes de poder provisionar una máquina o conjunto de máquinas virtuales, es
necesario poder crearlas a partir de imágenes de sistemas operativos, en un
remedo de arranque tal como se hace en una máquina real. En el espíritu DevOps,
tiene que haber una forma de hacerlo automáticamente y de forma reproducible con
código, usando este como infraestructura. También es deseable hacerlo de forma
que sea totalmente portable de una infraestructura a otra; en general, debe haber un
procedimiento para que las infraestructuras como servicio (IaaS) sean controladas
programáticamente, aparte de las otras dos formas que suelen ofrecer, a través de
la web y a través de los interfaces de línea de órdenes. Trabajar con la web no es
escalable y apenas es reproducible, porque sólo permite crear infraestructuras una
por una o por grupos si es que son similares; la segunda no es portable, porque
cada servicio cloud tiene sus propias órdenes como se ha visto en el tema de
automatizar servicios cloud. Sólo el trabajar con código desde una herramienta que
permita trabajar con cualquier servicio cloud permite reproducir configuraciones de
un vendedor a otro sin ningún problema.
Sigue las instrucciones en la web, para instalarte Vagrant, la versión 2.0.1 ha salido
en noviembre de 2017. Es una aplicación escrita en Ruby, por lo que tendrás que
tener una instalación preparada. Te aconsejamos que uses un gestor de versiones
como RVM o RBEnv para poder trabajar con él en espacio de usuario fácilmente.
Tendrás que tener algunas nociones de Ruby para trabajar con Vagrant, que no es
sino un DSL (Domain Specific Language) construido sobre él, al menos tendrás que
saber como instalar gemas (bibliotecas), que se usarán para los plugin de Vagrant y
también cómo trabajar con bucles y variables, que se usarán en el fichero de
definición de máquinas virtuales denominado V agrantfile.
Con Vagrant te puedes descargar directamente una máquina configurada de esta
lista o bien cualquier otra máquina configurada en el formato box, que es el que uno
de los que usa Vagrant.
Para conocer todos los comandos de vagrant, vagrant help o vagrant list-commands.
En este caso usamos un subcomando de vagrant box, que permite añadir nuevas
imágenes a nuestro gestor de máquinas virtuales; add añade uno nuevo en este
caso usando el gestor por omisión que es Virtual Box. El formato determinará en
qué tipo de hipervisor se puede ejecutar; en general, Vagrant usa VirtualBox, y los
.box se pueden importar directamente en esta aplicación; los formatos vienen
listados en la página anterior. Las boxes disponibles se pueden consultar en
Vagrantbox.es; en esa dirección hay diferentes sistemas operativos en diferentes
formatos, aunque generalmente la mayoría son para VirtualBox.
A continuación
vagrant up
En ese momento Virtual Box arrancará la máquina y te podrás conectar a ella
usando
vagrant ssh
Si quieres conectar por ssh desde algún otro programa, por ejemplo, Ansible,
tendrás que fijarte en cómo se configura la conexión y que puerto se usa.
Generalmente, una máquina virtual va a usar el puerto 2222 de ssh y para que
accedas desde fuera de Vagrant tendrás además que copiar tu clave pública, lo que
puedes hacer copiando y pegándola desde un terminal o bien usando el propio
Vagrantfile añadiendo las dos líneas siguientes:
Una vez creada la máquina, para que use estas líneas y se provisione hay que
hacer
vagrant provision
Hay que seguir teniendo en cuenta que se usa el puerto 2222, o sea que para
conectarte a la máquina (o usar un provisionador de forma externa a Vagrant)
tendrás que hacerlo así:
vagrant suspend
Esto dejará la máquina virtual en el estado en el que esté, que se podrá recuperar
en la próxima sesión. Cuando quieras deshacerte de ella,
vagrant destroy
Instalar una máquina virtual Debian usando Vagrant y conectar con ella.
que, igual que en el caso anterior, crea un fichero Vagrantfile (y así te lo dice; este
fichero será parecido a este que ya sabemos que permite trabajar y llevar a cabo
cualquier configuración adicional.
Podemos añadirle también la clave pública propia si queremos usarlo "desde fuera",
tal como también se ha hecho antes.
Una vez hecho eso ya podemos inicializar la máquina y trabajar con ella (pero antes
voy a apagar la máquina Azure que tengo ejecutándose desde que empecé a contar
lo anterior)
sudo vagrant up --provider=libvirt
Puede que tengas un problema con libvirt con "dhcp_leases: undefined method" o
similar comprobad la versión que tenéis. Si estáis usando la 0.0.36 desinstaladla e
instalad la 0.0.35 como indican en el mismo issue. Alternativamente, también se
puede pasar de este ejemplo, que era simplemente una forma de ilustrar diferentes
proveedores aparte del que aparece por defecto.
Y todos los demás comandos, también con sudo, por lo indicado anteriormente.
Instalar una máquina virtual ArchLinux o FreeBSD para KVM, otro hipervisor libre,
usando Vagrant y conectar con ella.
La provisión tiene lugar cuando se alza una máquina virtual (con vagrant up) o bien
explícitamente haciendo vagrant provision. En cualquier caso se lee del Vagrantfile y
se llevan a cabo las acciones especificadas en el fichero de configuración.
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "centos7"
config.vm.provision "shell",
inline: "yum install -y python"
end
y no sé por qué diablos pongo guiones si pongo shell, podía poner scripts de shell
directamente y todo el mundo me entendería, o guiones de la concha y nadie me
entendería
es que son específicos de un sistema operativo determinado. Por eso Vagrant
permite muchas otras formas de configuración, incluyendo casi todos los sistemas
de provisionamiento populares (Chef, Puppet, Ansible, Salt) y también Docker. La
ventaja de estos sistemas de más alto nivel es que permiten trabajar
independientemente del sistema operativo. Cada uno de ellos tendrá sus opciones
específicas, pero veamos cómo se haría lo anterior usando el provisionador
chef-solo.
Para empezar, hay que provisionar la máquina virtual para que funcione con
chef-solo y hay que hacerlo desde shell o Ansible; este ejemplo que usa este fichero
shell puede provisionar, por ejemplo, una máquina CentOS.
Lo que también podíamos haber hecho con una máquina que ya lo tuviera instalado,
de las que hay muchas en vagrantbox.es y de hecho es la mejor opción porque
chef-solo no se puede instalar en la versión 6.5 de CentOS fácilmente por no tener
una versión actualizada de Ruby)
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "centos7"
end
Este fichero usa un bloque de Ruby para pasarle variables y simplemente declara
que se va a usar la receta emacs, que previamente tendremos que haber creado en
un subdirectorio cookbooks que descienda exactamente del mismo directorio y que
contenga simplemente p ackage 'emacs' que tendrá que estar en un fichero
cookbooks/emacs/recipes/default.rb
Con todo esto se puede configurar emacs. Pero, la verdad, seguro que es más fácil
hacerlo en Ansible y/o en otro sistema operativo que no sea CentOS porque yo, por
lo pronto, no he logrado instalar chef-solo en ninguna de las máquinas
pre-configuradas de VagrantBoxes.
Desde Vagrant se puede crear también una caja base con lo mínimo necesario para
poder funcionar, incluyendo el soporte para ssh y provisionadores como Chef o
Puppet. Se puede crear directamente en VirtualBox y usar v agrant package para
empaquetarla y usarla para su consumo posterior.
token = open($new_discovery_url).read
data = YAML.load(IO.readlines('user-data')[1..-1].join)
yaml = YAML.dump(data)
File.open('user-data', 'w') { |file| file.write("#cloud-config\n\n#{yaml}") }
end
El Vagrantfile, por otro lado, realiza una serie de adaptaciones de la máquina virtual
usada y crea una red privada virtual que una a las tres máquinas, de forma que se
puedan comunicar de forma segura. Una vez ejecutado v agrant up se puede
acceder a las máquinas por ssh con el nombre definido (core-0x) pero también se
pueden usar para escalar aplicaciones basadas en contenedores en el cluster de
CoreOS creado, con el que puedes ejecutar múltiples copias de tu aplicación para
replicación o escalado automático.
Pero una de las más interesantes que podemos usar es RancherOS, otro sistema
operativo, como CoreOS, diseñado para ejecutar contenedores. En el repo dice que
ya no se apoya esa versión, pero se puede al menos ejecutar y probar si se desea.
También se puede probar NixOps, que aunque está diseñado especialmente para
una versión del sistema operativo llamado NixOS, puede usarse también para
orquestar máquinas virtuales en una serie de entornos.
Objetivos
Objetivos específicos
1. Entender cómo las diferentes tecnologías de virtualización se integran en la
creación de contenedores.
2. Crear infraestructuras virtuales completas.
3. Comprender los pasos necesarios para la configuración automática de las
mismas.
En esta presentación explica como los espacios de nombres son la clave para la
creación de contenedores y cuáles son sus ventajas frente a otros métodos de
virtualización
El mundo Linux no tendría capacidades similares hasta bien entrados los años 90,
con vServers, OpenVZ y finalmente LXC. Este último, LXC, se basa en el concepto
de grupos de control o CGROUPS, una capacidad del núcleo de Linux desde la
versión 2.6.24 que crea contenedores de procesos unificando diferentes
capacidades del sistema operativo que incluyen acceso a recursos, prioridades y
control de los procesos. Los procesos dentro de un contenedor están aislados de
forma que sólo pueden ver los procesos dentro del mismo, creando un entorno
mucho más seguro que las anteriores jaulas. Estos CGROUPS han sido ya vistos
en otro tema.
Un contenedor es, igual que una jaula, una forma ligera de virtualización, en el
sentido que no requiere un hipervisor para funcionar ni, en principio, ninguno de los
mecanismos hardware necesarios para llevar a cabo virtualización. Tiene la
limitación de que la máquina invitada debe tener el mismo kernel y misma CPU que
la máquina anfitriona, pero si esto no es un problema, puede resultar una alternativa
útil y ligera a la misma. A diferencia de las jaulas, combina restricciones en el
acceso al sistema de ficheros con otras restricciones aprovechando espacios de
nombres y grupos de control. l xc una de las soluciones de creación de contenedores
más fácil de usar hoy en día en Linux, sobre todo si se quiere usar desde un
programa a nivel de librería. Evidentemente, desde que ha salido Docker no es la
más popular, aunque es una solución madura y estable.
Esta virtualización ligera tiene, entre otras ventajas, una huella escasa: un
ordenador normal puede admitir 10 veces más contenedores (o tápers) que
máquinas virtuales; su tiempo de arranque es de unos segundos y, además, tienes
mayor control desde fuera (desde el anfitrión) del que se pueda tener usando
máquinas virtuales.
Usando lxc
No todas las versiones de los núcleos del sistema operativo pueden usar este tipo
de container; para empezar, dependerá de cómo esté compilado, pero también del
soporte que tenga el hardware. l xc-checkconfig permite comprobar si está preparado
para usar este tipo de tecnología y también si se ha configurado correctamente.
Parte de la configuración se refiere a la instalación de c groups, que hemos visto
antes; el resto a los espacios de nombres y a capacidades misceláneasrelacionadas
con la red y el sistema de ficheros.
Hay que tener en cuenta que si no aparece alguno de esas capacidades como
activada, LXC no va a funcionar.
Cuando queramos crear nuestro primer contenedor LXC usando las instrucciones
que se detallan en este tema es posible que nos dé un error diciéndonos que no
está disponible el comando d ebootstrap, solamente tendremos que instalarlo con la
orden s udo pacman -S debootstrap, y ya podremos crear contenedores LXC sin
problemas.
Una vez hecho esto podemos instalar LXC usando las instrucciones oficiales de
instalación en Debian con los comandos:
lxc-checkconfig
Lo que nos debería de dar todo enabled; también podemos comprobar la versión de
LXC instalada con
lxc-info --version
Entre ellas, varias de Alpine Linux, una distribución ligera precisamente dirigida a su
uso dentro de contenedores. También hay una llamada plamo, escrita en algún tipo
de letra oriental, posiblemente japonés. Se puede instalar, pero igual no se entiende
nada.
Podemos listar los contenedores que tenemos disponibles con lxc-ls, aunque en
este momento cualquier contenedor debería estar en estado STOPPED.
, donde -n es la opción para dar el nombre del contenedor que se va a iniciar.
Dependiendo del contenedor que se arranque, habrá una configuración inicial; en
este caso, se configuran una serie de cosas y eventualmente sale el login, que será
para todas las máquinas creadas de esta forma u buntu (también clave). Lo que hace
esta orden es automatizar una serie de tareas tales como asignar los CGROUPS,
crear los namespaces que sean necesarios, y crear un puente de red tal como
hemos visto anteriormente. En general, creará un puente llamado lxcbr0 y otro con
el prefijo veth.
Instalar una distro tal como Alpine y conectarse a ella usando el nombre de usuario
y clave que indicará en su creación
Una vez arrancados los contenedores, si se lista desde fuera aparecerá de esta
forma:
$ sudo lxc-ls -f
NAME STATE IPV4 IPV6 AUTOSTART
-----------------------------------------------
nubecilla RUNNING 10.0.3.171 - NO
una-caja STOPPED - - NO
Las órdenes que incluye el paquete permiten administrar las máquinas virtuales,
actualizarlas y explican cómo usar otras plantillas de las suministradas para crear
contenedores con otro tipo de sistemas, sean o no debianitas. Se pueden crear
sistemas basados en Fedora; también clonar contenedores existentes para que
vaya todo rápidamente.
La guía del usuario indica también cómo usarlo como usuario sin privilegios, lo que
mayormente te ahorra la molestia de introducir sudo y en su caso la clave cada vez.
Si lo vas a usar con cierta frecuencia, sobre todo en desarrollo, puede ser una mejor
opción.
En general, un SCM permite crear métodos para instalar una aplicación o servicio
determinado, expresando sus dependencias, los servicios que provee y cómo se
puede trabajar con ellos. Por ejemplo, una base de datos ofrece precisamente ese
servicio; un sistema de gestión de contenidos dependerá del lenguaje en el que esté
escrito; además, se pueden establecer relacionesentre ellos para que el CMS use la
BD para almacenar sus tablas.
Hay decenas de sistemas CMS, aunque hoy en día los hay que tienen cierta
popularidad, como Salt, Rex, Ansible, Chef, Juju y Puppet. Todos ellos tienen sus
ventajas e inconvenientes, pero para la configuración de tápers se puede usar
directamente Juju, creado por Canonical especialmente para máquinas virtuales de
ubuntu que se ejecuten en la nube de Amazon. En este punto nos interesa también
porque se puede usar directamente con contenedores LXC, mientras que no todos
lo hacen.
e iniciarlas con
Introducción a Docker
Docker es una herramienta que permite aislar aplicaciones, creando contenedores
que pueden almacenarse de forma permanente para permitir el despliegue de esas
mismas aplicaciones en la nube. Por lo tanto, en una primera aproximación, Docker
serían similares a otras aplicaciones tales como LXC/LXD o incluso las jaulas chroot,
es decir, una forma de empaquetar una aplicación con todo lo necesario para que
opere de forma independiente del resto de las aplicaciones y se pueda, por tanto,
replicar, escalar, desplegar, arrancar y destruir de forma también independiente.
Docker funciona mejor en Linux, fue creado para Linux y es donde tiene mejor
soporte a nivel de núcleo del sistema operativo. Desde la última versión de
Windows, la 10, funciona relativamente bien también en este sistema operativo. Si
no tienes esa versión no te molestes; en todo caso, también en Windows 10 puedes
usar el subsistema Linux (Ubuntu y últimamente OpenSuSE) para interactuar con
Docker. Finalmente, aunque es usable desde Mac, en realidad el sistema operativo
no tiene soporte para el mismo. Es mejor que en este caso se use una máquina
virtual local o en la nube.
Aunque en una primera aproximación Docker es, como hemos dicho arriba, similar a
otras aplicaciones de virtualización ligeracomo lxc/lxd, que lo precedieron en el
tiempo, sin embargo el enfoque de Docker es fundamentalmente diferente es
fundamentalmente diferente, aunque las tecnologías subyacentes de virtualización
por software son las mismas. La principal diferencia es que Docker hace énfasis en
la gestión centralizada de recursos y, en una línea que va desde la virtualización por
hardware hasta la generación de un ejecutable para su uso en cualquier otra
máquina, estaría mucho más cerca de ésta que de la primera, mientras que lxc/lxd
estarían más enfocados a empaquetar máquinas virtuales completas o casi. En la
práctica, muchas aplicaciones, como la creación de máquinas virtuales efímeras
para ejecución de aplicaciones, van a ser las mismas, pero los casos de uso son
también diferentes, con Docker tendiendo más hacia uso de contenedores de usar y
tirar y 'lxc/lxd' a una alternativa ligera al uso de máquinas virtuales completas.
A continuación vamos a ver cómo podemos usar Docker como simples usuarios,
para ver a continuación como se puede diseñar una arquitectura usándolo,
empezando por el principio, como instalarlo.
Conviene que, en este momento o un poco más adelante, tengas preparad una
instalación de un hipervisor o gestor de máquinas virtuales tipo VirtualBox o similar.
Sea porque quieras tener una máquina virtual Linux específica para esto, o para
tener varias máquinas virtuales funcionando a la vez.
Instalación de Docker
Instalar docker es sencillo desde que se publicó la versión 1.0, especialmente en
distribuciones de Linux. Por ejemplo, para Ubuntu hay que dar de alta una serie de
repositorios y no funcionará con versiones más antiguas de la 12.04 (y en este caso
sólo si se instalan kernels posteriores). En las últimas versiones, de hecho, ya está
en los repositorios oficiales de Ubuntu y para instalarlo no hay más que hacer
aunque la versión en los repositorios oficiales suele ser más antigua que la que se
descargue de la web o los repositorios adicionales. Este paquete incluye varias
aplicaciones: un daemon, d ockerd, y un cliente de línea de órdenes, d
ocker. La
instalación dejará este daemon ejecutándose y lo configurará para que se arranque
con el inicio del sistema. También una serie de imágenes genéricas con las que se
puede empezar a trabajar de forma más o menos inmediata.
Hay también diferentes opciones para instalar Docker en Windows o en un Mac.
Otra posibilidad para trabajar con Docker es usar el anteriormente denominado
CoreOS, ahora Container Linux. Container Linux es una distribución diseñada para
usar aplicaciones distribuidas, casi de forma exclusiva, en contenedores, y aparte de
una serie de características interesantes, como el uso de e tcd para configuración
distribuida, tiene un gestor de Docker instalado en la configuración base. Si es para
experimentar Docker sin afectar la instalación de nuestro propio ordenador, se
aconseja que se instale Container Linux en una máquina virtual.
Con cualquiera de las formas que hayamos elegido para instalar Docker, vamos a
comenzar desde el principio. Veremos a continuación cómo empezar a ejecutar
Docker.
comenzará a ejecutarlo.
De los pasos anteriores habrás deducido que se ha descargado una imagen cuyo
nombre es hello world y se ha creado un contenedor, en principio sin nombre.
Puedes listar las imágenes que tienes con
sudo docker ps -a
que borrará el contenedor creado una vez ejecutada la orden. Así se mantiene el
número de contenedores bajo y sobre todo se guardan sólo y exclusivamente los
que se piensen mantener o trabajar más adelante. Esta orden pone también de
manifiesto la idea de contenedores de usar y tirar. Una vez ejecutado el contenedor,
se dispone de la memoria y el disco que usa.
Como vemos, los contenedores pueden actuar como un ejecutable, una forma de
distribuir aplicaciones de forma independiente de la versión de Linux y de forma
efímera. De hecho, como tal ejecutable, se le pueden pasar argumentos por línea de
órdenes
que usa el contenedor daleksay para imprimir a un pulpo sonriente diciendo cosas.
Como vemos, se le pasa como argumentos -f smiling-octopus Uso argumentos, ea de
forma que el contenedor actúa, para casi todos los efectos, como el propio
programa al que aísla.
Buscar alguna demo interesante de Docker y ejecutarla localmente, o en su defecto,
ejecutar la imagen anterior y ver cómo funciona y los procesos que se llevan a cabo
la primera vez que se ejecuta y las siguientes ocasiones.
Esta orden descarga una imagen de Alpine Linux y la instala, haciéndola disponible
para que se creen, a partir de ella, contenedores. Como se ha visto antes, las
imágenes que hay disponibles en el sistema se listan con
Si acabas de hacer el pull anterior, aparecerá esa y otras que hayas creado
anteriormente. También aparecerá el tamaño de la imagen, que es solamente de
unos 4 megabytes. Otras imágenes, como las de Ubuntu, tendrán alrededor de 200
MBs, por lo que siempre se aconseja que se use este tipo de imágenes, mucho más
ligeras, que hace que la descarga sea mucho más rápida.
Se pueden usar, sin embargo, las imágenes que sean más adecuadas para la tarea,
el prototipo o la prueba que se quiera realizar. Hay muchas imágenes creadas y se
pueden crear y compartir en el sitio web de Docker, al estilo de las librerías de
Python o los paquetes Debian. Se pueden buscar todas las imágenes de un tipo
determinado, como Ubuntu o buscar las imágenes más populares. Estas imágenes
contienen no sólo sistemas operativos bare bones, sino también otros con una
funcionalidad determinada. Por ejemplo, una de las imágenes más populares es la
de n ginx, la de Redis o la de Busybox, un sustituto del shell que incluye también una
serie de utilidades externas y que se pueden usar como imagen base.
Si usas otra imagen, se tendrá que descargar lo que tardará más o menos
dependiendo de la conexión; hay también otro factor que veremos más adelante.
Una vez bajada, se pueden empezar a ejecutar comandos. Lo bueno de docker es
que permite ejecutarlos directamente, y en esto tenemos que tener en cuenta que
se va a tratar de comandos aislados y que, en realidad, no tenemos una máquina
virtual diferente.
Tras el sudo, hace falta el comando docker; run es el comando de docker que
estamos usando, --rm hace que la máquina se borre una vez ejecutado el comando.
alpine es el nombre de la máquina, el mismo que le hayamos dado antes cuando
hemos hecho pull y finalmente l s, el comando que estamos ejecutando. Este
comando arranca el contenedor, lo ejecuta y a continuación sale de él. Esta es una
de las ventajas de este tipo de virtualización: es tan rápido arrancar que se puede
usar para un simple comando y dejar de usarse a continuación, y de hecho hasta se
puede borrar el contenedor correspondiente.
Esta imagen de Alpine no contiene bash, pero si el shell básico llamado ash y que
está instalado en sh, por lo que podremos meternos en la misma ejecutando
Dentro de ella podemos trabajar como un consola cualquiera, pero teniendo acceso
sólo a los recursos propios.
Una de las primeras cosas que habrá que hacer es actualizar la distribución. Alpine
usa apk como gestor de paquetes, y la instalación base no permite hacer gran cosa,
así que para empezar conviene hacer
apk update
apk upgrade
Para que actualice la lista de paquetes disponibles. Después, se pueden instalar
paquetes, por ejemplo
Una vez añadido todo lo que queramos a la imagen, se puede almacenar o subir al
registro. En todo caso, apk search te permite buscar los ficheros y paquetes que
necesites para compilar o instalar algo. En algunos casos puede ser un poco más
complicado que para otras distros, pero merece la pena.
(donde hemos abreviado las opciones -i y -t juntándolas) crearía, a partir de la
imagen de Ubuntu, un nuevo contenedor.
En cualquiera de los casos, cuando se ejecuta exit o Control-D para salir del
contenedor, este deja de ejecutarse. Ejecutar
sudo docker ps -l
mostrará que ese contenedor está exited, es decir, que ha salido, pero también
mostrará en la primera columna el ID del mismo. Arrancarlo de nuevo no nos traerá
la línea de órdenes, pero sí se arrancará el entorno de ejecución; si queremos volver
a ejecutar algo como la línea de órdenes, tendremos que arrancarlo y a continuación
efectivamente ejecutar algo como el shell
sudo docker start 6dc8ddb51cd6 && sudo docker exec -it 6dc8ddb51cd6 sh
Sin embargo, en este caso simplemente salir del shell no dejará de ejecutar el
contenedor, por lo que habrá que pararlo
Las imágenes que se han creado se pueden examinar con inspect, lo que nos da
información sobre qué metadatos se le han asignado por omisión, incluyendo una
IP.
te dirá toda la información sobre la misma, incluyendo qué es lo que está haciendo
en un momento determinado.
Hasta ahora el uso de docker no es muy diferente de lxc, pero lo interesante es que
se puede guardar el estado de un contenedor tal como está usando commit
que guardará el estado del contenedor tal como está en ese momento,
convirtiéndolo en una nueva imagen, a la que podemos acceder si usamos
El hacer commit de una imagen crea una capa adicional, identificada por un SHA
específico, en el sistema de ficheros de Docker. Por ejemplo, si trabajamos con una
imagen cualquiera y hacemos commit de esta forma
creamos una nueva imagen, que vamos a llamar jjmerelo/bbtest. Esta imagen
contendrá, sobre la capa original, la capa adicional que hemos creado. Este
comando devolverá un determinado SHA, de la forma:
sha256:d092d86c2bcde671ccb7bb66aca28a09d710e49c56ad8c1f6a4c674007d912f3
sudo jq '.'
/var/lib/docker/image/aufs/imagedb/content/sha256/d092d86c2bcde671ccb7bb66aca28
a09d710e49c56ad8c1f6a4c674007d912f3
nos mostrará un JSON bien formateado (por eso usamos jq, una herramienta
imprescindible) que, en el elemento diff_ids, nos mostrará las capas. Si repetimos
esta operación cada vez que hagamos un commit sobre una nueva imagen, nos
mostrará las capas adicionales que se van formando.
En general, salvo que haya algún problema crítico de prestaciones, es mejor usar el
driver que se use por defecto; dependerá de la implementación de Docker (CE o
EE) y de la versión del kernel. En esta página se indica como configurar el driver
que se va a usar.
Hay una forma de usar contenedores sólo para almacenar datos, sin que haya
ningún proceso que se ejecute en ellos usando los llamados volúmenes. Se crea
usando volume create
Igual que un contenedor Docker es algo así como un proceso con esteroides, un
volumen de Docker es una especie de disco transportable, que almacena
información y que puedes llevar de un lado a otro. De la misma forma, la
arquitectura de las aplicaciones varía. No vamos a tener una aplicación monolítica
que escriba en el log, lo analice y lo lea, sino diferentes contenedores que
interaccionarán no directamente, sino a través de este contenedor de
almacenamiento.
Por ejemplo, podemos usar un volumen para montar el /app de diferentes sistemas
operativos, de forma que podamos probar una aplicación determinada en los
mismos. Hagamos
Una vez dentro, se puede crear un minibenchmark, que diga por ejemplo el número
de ficheros ls -R / | wc y se guarda en /app. Una vez hecho eso, puedes ejecutar ese
programa en cualquier distro, de esta forma:
En este caso, con -p le indicamos los puertos que tiene que usar; antes de : será el
puerto "externo" y tras él el puerto que usa internamente. El volumen se usa con -v
log:/log; el primer parámetro es el nombre del volumen externo que estamos
usando, en el segundo el nombre del directorio o sistema de ficheros interno en el
que se ha montado.
Lo que se hace en este caso es que log actúa como un volumen de datos,
efectivamente. Y ese volumen de datos es persistente, por lo que los datos que se
escriben ahí se pueden guardar o enviar; también se puede usar simultáneamente
por parte de otro contenedor, montándolo de esta forma:
Una vez más, el volumen de docker log se monta en el directorio /log, un nombre
arbitrario, porque igual que los puntos de montaje del filesystem de Linux, puede ser
en uno cualquiera; el OverlayFS crea ese directorio y lo hace accesible a un
programa, en este caso un programa también dockerizado que pasa del formato en
texto plano de los logs de Dancer2 a un formato JSON que puede ser almacenado
incluso en otro volumen si se desea.
FROM busybox
WORKDIR /data
VOLUME /data
COPY hitos.json .
Esta orden escribe un número hexa en la consola, que habrá que tener en cuenta
por que es el CONTAINER ID, lo que vamos a usar más adelante. Como se ve, se
ejecuta como daemon - d y se ejecuta simplemente s h. En este contenedor se estará
ejecutando de forma continua ese proceso, lo que puede ser interesante a la hora
de monitorizarlo, pero lo interesante de él es que se va a usar para cargar ese
fichero de configuración desde diferentes contenedores, de esta forma:
Como se ve, se ejecutan varios pasos uno de los cuales implica "tomar" un ID e
usarlo más adelante en el montaje. No es difícil de resolver con un script del shell,
pero como es una necesidad habitual se han habilitado otras herramientas para
poder hacer esto de forma ágil: compose
version: '2'
services:
config:
build: config
web:
build: .
ports:
- "80:5000"
volumes_from:
- config:ro
La especificación de la versión indica de qué versión del interfaz se trata. Hay hasta
una versión 3, con cambios sustanciales. En este caso, esta versión permite crear
dos servicios, uno que denominamos c onfig, que será el contenedor que tenga la
configuración en un fichero, y otro que se llama w eb. YAML se organiza como un
hash o diccionario, de forma que s ervicestiene dos claves c onfig y w
eb. Dentro de
cada una de las claves se especifica como se levantan esos servicios. En el primer
uild o construir el servicio a partir del Dockerfile, y se especifica el
caso se trata de b
directorio donde se encuentra; sólo puede haber un Dockerfile por directorio, así que
para construir varios servicios tendrán que tendrán que ponerse en directorios
diferentes, como en este caso. El segundo servicio está en el mismo directorio que
el fichero, que tiene que llamarse d ocker-compose.yml, pero en este estamos
indicando un mapeo de puertos, con el 5000 interno cambiando al 80 externo (que,
recordemos, es un puerto privilegiado) y usando v olumes_from para usar los
volúmenes, es decir, los datos, contenidos en el fichero correspondiente.
Para ejecutarlo,
docker-compose up
services:
- docker
env:
- DOCKER_COMPOSE_VERSION=1.17.0
before_install:
- sudo rm /usr/local/bin/docker-compose
- curl -L
https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION
}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
- docker-compose up
script:
- docker ps -a | grep -q web
Estos tests se pueden hacer también con simples Dockerfile, y de hecho sería
conveniente combinar los tests de los servicios conjuntos con los tests de
Dockerfile. Cualquier infraestructura es código, y como tal si no está testeado está
roto.
Simplicidad
Los contenedores deben de ser lo más simples posible, y llevar esta regla desde el
principio al final. Idealmente, los contenedores ejecutarán un solo proceso. Esto
facilita el escalado mediante replicación, y permite también separar las tareas en
diferentes contenedores, que pueden ser desplegados o actualizados de forma
totalmente independiente. Esto también facilita el uso de contenedores estándar,
bien depurados y cuya configuración sea lo más segura posible.
Esto también implica una serie de cosas: usar la distribución más ligera que soporte
la configuración, por ejemplo. El usar una distribución ligera y adaptada a
contenedores como Alpine Linux o Atomic Host hará que se creen contenedores
mucho más ligeros y rápidos de cargar y que tengan toda la funcionalidad que se
necesita. También conviene eliminar toda aquella funcionalidad que no se necesite y
que se haya usado solamente para construir el contenedor, tales como
compiladores o ficheros intermedios.
Seguridad
Los contenedores docker se ejecutan de forma aislada del resto del sistema
operativo, pero eso no significa que no se pueda penetrar en ellos y llevar a cabo
diferentes actividades no deseadas. Es importante, por ejemplo, que siempre que
sea posible se ejecute la aplicación como un usuario no privilegiado.
Usando Dockerfiles
La infraestructura se debe crear usando código, y en Docker pasa exactamente
igual. Tiene un mecanismo llamado Dockerfiles que permite construir contenedores
o tápers de forma que lo que quede en control de versiones sea el código en sí, no
el contenedor, con el consiguiente ahorro de espacio. La ventaja además es que en
el Docker hub hay multitud de contenedores ya hechos, que se pueden usar
directamente. Veamos un ejemplo, como es habitual para el bot en Scala que
hemos venido usando.
FROM frolvlad/alpine-scala
MAINTAINER JJ Merelo <[email protected]>
WORKDIR /root
CMD ["/usr/local/bin/sbt"]
Las siguientes órdenes son todas apk, el gestor de paquetes de Alpine. No tiene
tantos empaquetados como las distros más conocidas, pero sí los básicos; siempre
al principio habrá que actualizar los repos para que no haya problemas.
El resto son otras órdenes RUN, que ejecutan directamente órdenes dentro del
contenedor, y que en este caso descargan un paquete, que es la forma como se
distribuye s bt, y lo ponen como ejecutable. Hay que hacer una cosa adicional: copiar
mediante C OPY un par de ficheros locales, el . jar que contiene el programa y el
fichero de hitos que se va a usar para responder al usuario.
(o el nick que tengas en GitHub). El -t es, como es habitual, para asignar un tag, en
este caso uno que se puede usar más adelante en el Docker Hub. Tardará un rato,
sobre todo por la descarga de unas cuantas bibliotecas por parte de sbt, lo que se
hace en la última línea. Una vez hecho esto, si funciona la construcción, se podrá
ejecutar con
sudo docker run --rm -t --env BOBOT_TOKEN=un:token:tocho jjmerelo/bobot
donde --env se usa para pasar la variable de entorno de Telegram que necesita el
bot para funcionar.
Por ejemplo, esta, llamada alpine-perl6 que se puede usar en lugar del intérprete de
Perl6 y usa como base la distro ligera Alpine:
FROM alpine:latest
MAINTAINER JJ Merelo <[email protected]>
WORKDIR /root
ENTRYPOINT ["perl6"]
#Basic setup
RUN apk update
RUN apk upgrade
#Build moar
RUN rakudobrew build moar
#Mount point
RUN mkdir /app
VOLUME /app
Como ya hemos visto anteriormente, usa apk, la orden de Alpine para instalar
paquetes e instala lo necesario para que eche a andar el gestor de intérpretes de
Perl6 llamado r akudobrew. Este gestor tarda un buen rato, hasta minutos, en
construir el intérprete a través de diferentes fases de compilación, por eso este
contenedor sustituye eso por la simple descarga del mismo. Instala además alguna
utilidad relativamente común, pero lo que lo hace trabajar "como" el intérprete es la
orden E NTRYPOINT ["perl6"]. E
NTRYPOINT se usa para señalar a qué orden se va a
concatenar el resto de los argumentos en la línea de órdenes, en este caso,
tratándose del intérprete de Perl 6, se comportará exactamente como él. Para que
esto funcione también se ha definido una variable de entorno en:
ENV PATH="/root/.rakudobrew/bin:${PATH}"
que añade al PATH el directorio donde se encuentra. Con estas dos características
se puede ejecutar el contenedor con:
Por otro lado, otra característica que tiene este contenedor es que, a través de
VOLUME, hemos creado un directorio sobre el que podemos montar un directorio
externo, tal como hacemos aquí:
En este caso, además, usamos --rm para borrar el contenedor una vez se haya
usado y -t en vez de -it para indicar que sólo estamos interesados en que se asigne
un terminal y la salida del mismo, no vamos a interaccionar con él.
Con ls listamos las máquinas virtuales que hemos gestionado, así como alguna
información adicional:
$ sudo docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
maquinilla - virtualbox Running tcp://192.168.99.104:2376 v1.12.5
vbox-test - virtualbox Running tcp://192.168.99.100:2376 v1.12.5
Aquí hay dos máquinas, cada una con una dirección IP virtual que vamos a usar
para conectarnos a ellas directamente o desde nuestro cliente docker. Por ejemplo,
hacer ssh
Si queremos usarlo más en serio, desde nuestra línea de órdenes, tenemos que
ejecutar
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.104:2376"
export DOCKER_CERT_PATH="/home/jmerelo/.docker/machine/machines/maquinilla"
export DOCKER_MACHINE_NAME="maquinilla"
# Run this command to configure your shell:
# eval $(docker-machine env maquinilla)
Esa orden exporta las variables anteriores, que le indicarán a docker qué tiene que
usar en ese shell explícitamente. Cada nuevo shell tendrá también que exportar
esas variables para poder usar la máquina virtual. Las órdenes docker que se
ejecuten a continuación se ejecutarán en esa máquina; por ejemplo,
De la misma forma podemos operar con servidores en la nube, con sólo usar los
drivers correspondientes.
Crear con docker-machine una máquina virtual local que permita desplegar
contenedores y ejecutar en él contenedores creados con antelación.
Limpieza de contenedores
Una vez que se lleva trabajando con Docker un rato, puede que nos encontremos
con diferentes contenedores en diferente estado de construcción, así como las
imágenes a partir de las cuales se han creado esos contenedores. Todo eso ocupa
una cierta cantidad de espacio, y conviene de vez en cuando liberarlo para que no
acaben llenando el disco duro de la máquina que se use para desarrollo. Antes de
llegar a eso, conviene recordar la opción - -rm para ejecutar órdenes dentro del
contenedor, que limpia automáticamente el contenedor y lo elimina cuando se sale
del mismo:
Por otro lado, la Open Container Initiative está todavía en una fase muy preliminar.
Aunque contiene especificaciones tanto apara ejecutarlos como para especificar
imágenes, por lo pronto no hay muchas implementaciones de referencia que se
puedan usar. Si acaba cuajando puede hacer que el campo de los contenedores
evite monopolios, así que habrá que estar atentos al mismo. Hay trabajo en curso
para comprobar imágenes, por ejemplo.
Descripción
En este hito 0 del proyecto se trata de poner a punto las herramientas que se van a
usar para comunicar los objetivos, los ejercicios y las prácticas durante el resto del
curso. Durante el mismo, se busca también que se interioricen una serie de buenas
it. Para ello, se creará un
prácticas a la hora de trabajar con repositorios de g
repositorio que se usará durante el resto de la asignatura para mostrar el avance el
proyecto de despliegue de una aplicación en diferentes hitos. El repositorio
contendrá
Prerrequisitos
Tras darse de alta en el grupo de Telegram de la asignatura y dar al profesor la
cuenta de Google para ver las notas, enviar también por Telegram el nick de GitHub
y cumplimentar los objetivos de la primera sesión.
Explicación
Primero, hay que configurar correctamente el entorno, lo que incluye
Avanza la tarea #1
● No incluir en el repositorio ningún fichero que pueda ser generado a partir del
mismo, incluir un procedimiento para generar tales ficheros. Por ejemplo,
ningún fichero compilado a partir de otros, o un PDF generado a partir de los
ficheros LaTeX, o los ficheros generados por los entornos virtuales de ciertos
lenguajes. Esos ficheros, además, se tendrán que incluir en . gitignore para
que no aparezcan como "no seguidos" cuando se haga g it status.
● No incluir en el repositorio ningún código que no sea propio, incluir en el
mismo el procedimiento para incluir ese código en la compilación o
instalación, generalmente en forma de fichero de requisitos. Si el código
sobre el que se va a trabajar es directamente de otro repositorio, hacer un
fork del mismo, no copiar los ficheros. La estructura de un repositorio siempre
tiene que respetarse, y la mejor forma de atribuir correctamente los cambios
es trabajar sobre el repositorio original modificado.
● Usar desde el principio un fichero . gitignore para evitar añadir
accidentalmente ficheros que no deban estar en el repositorio, como ficheros
de respaldo o ficheros generados en compilación o construcción.
● No incluir ficheros binarios en el repositorio, aunque se necesiten en el
proyecto. Para ello están los releases.
● Si se va a usar algún proyecto anterior, hacer un fork del mismo, no copiar los
ficheros y subirlos como contribución propia. Las contribuciones, siempre que
sea posible, deben estar firmadas por la persona que las haya creado, por
eso no se deben copiar simplemente los ficheros, sino forkear los repositorios
correspondientes.
● Siempre comprobar, antes de hacer un pull request, que se está trabajando
sobre la última copia del fichero para evitar conflictos que imposibiliten que se
lleve a cabo la fusión por parte de la persona encargada del mismo.
Práctica 2: Provisionamiento de
máquinas virtuales
Descripción
Se trata de escribir un fichero que despliegue la infraestructura virtual para los
servicios que se van a usar en el proyecto de la asignatura.
Prerrequisitos
Haber alcanzado el 80% de los objetivos de las ocho primeras semanas de la
asignatura.
Explicación
El primer paso será crear una instancia de una máquina virtual sea localmente o en
algún sistema cloud y dotarla de un sistema operativo básico, aunque para algunos
sistemas de aprovisionamiento como Chef habrá que usar imágenes específicas
que tengan un cliente de c hef-solo ya instalado.
Una vez que se tiene una instancia de una máquina virtual creada y funcionando, lo
siguiente es dotarla de la infraestructura necesaria para ejecutar nuestro programa.
A priori puede que no sepamos en concreto qué es lo que vamos a usar, pero al
menos tendremos una idea de las aplicaciones y bibliotecas que se van a usar,
aparte de la infraestructura básica que necesitará cualquier aplicación, tal como
instalación de git, creación de un usuario y de los directorios que se van a usar
desde nuestra aplicación.
Para configurar esta máquina virtual se usarán scripts de Chef, Ansible, Salt, Rex,
Puppet o el programa de gestión de configuraciones que se desee. Como es una
continuación del hito anterior, se tendrán que desplegar la infraestructura necesaria
para que funcionen tales programas.
Descripción
En este hito se trata de usar los clientes de línea de órdenes de los servicios en la
nube para crear instancias de máquinas virtuales en la nube, que posteriormente se
puede provisionar.
Prerrequisitos
Haber alcanzado el 60% de los objetivos del tema correspondiente.
Explicación
Generalmente el proceso de provisionamiento y despliegue comienza con la
descripción a alto nivel de la infraestructura virtual que se vaya a usar, incluyendo la
creación de las máquinas virtuales y la descripción de las mismas. Usando
herramientas de orquestación como se verán más adelante se puede trabajar de
forma independiente del proveedor de nube; sin embargo, en algunos casos hay
características específicas de un proveedor que no están disponibles en
herramientas de propósito general.
Todos los proveedores de cloud usan un API para acceder al mismo; estas
herramientas CLI se pueden usar desde tal API para crear servicios, monitorizarlos
y manejarlos. En esta práctica usaremos las herramientas libres para hacer este tipo
de tareas de creación de nodos completos de máquinas virtuales y su posterior
provisionamiento con las herramientas creadas en el hito anterior.
Estas herramientas permite también elegir la imagen que se va a usar, de forma que
se puede automatizar la creación, desde cero, usando shell scripts o usando el CLI
como una biblioteca que se puede incluir desde diferentes lenguajes de
programación, con preferencia, claro, de aquél en el que está escrito la propia
biblioteca.
Entrega de la práctica
Subir los fuentes a GitHub y editar este fichero enlazando el último commit en el que
se indique claramente el nombre del alumno y la dirección donde se ha subido el
fuente. Para aceptarse el PR, tendrá que pasar los tests, como es natural.
La explicación del proyecto deberá incluir los criterios usados para elegir la imagen
base. Esta documentación se incluirá en ficheros MarkDown en el sitio que se haya
elegido para la misma, preferiblemente un subdirectorio d ocs que se haya publicado
desde GitHub.
Descripción
En este hito se trata de usar Vagrant para provisionar una o preferiblemente varias
máquinas virtuales usando un proveedor de servicios cloud.
Prerrequisitos
Haber alcanzado el 60% de los objetivos de las sesiones correspondientes.
Explicación
El proceso de provisionamiento y despliegue comienza generalmente con la
descripción a alto nivel de la infraestructura virtual que se vaya a usar, incluyendo la
creación de las máquinas virtuales y la descripción de las mismas, incluyendo el
aprovisionamiento correspondiente.
Esto se puede hacer usando los SDK o interfaces de línea de órdenes del proveedor
de nube, pero en esta práctica usaremos Vagrant para hacer este tipo de tarea.
Vagrant es un sistema de orquestación de máquinas virtuales que permite usar
diferentes tipos de provisionamiento para configurar las máquinas, así como la
conexión entre las mismas. Vagrant también permite hacer cosas como copiar
ficheros o crear usuarios, que aunque se pueden hacer en el momento del
provisionamiento, puede que sea más conveniente hacerlo en el momento anterior
al provisionamiento porque puede haber algún elemento que tenga que estar
presente antes de que los provisionadores comiencen a funcionar. Finalmente,
permite también elegir la imagen que se va a usar, de forma que se puede
automatizar la creación, desde cero; esta imagen es independiente del proveedor,
siempre que use alguno de los formatos estándar y también provisonarla usando
uno de los muchos sistemas de provisionamiento que existen, tales como Chef o
Ansible.
Salvo que las imágenes pueden formato diferente, en principio debería ser posible
cambiar simplemente el proveedor de Vagrant y poder desplegar en diferentes
entornos, aunque la infraestructura básica puede también tener alguna variación. En
todo caso y como en casos anteriores, se pide al estudiante que use Vagrant en
varios entornos, aunque uno de ellos puede ser un hipervisor local y otro en la nube.
Uno de ellos será siempre el proveedor en la nube de alguno al que el estudiante
tenga acceso.
Entrega de la práctica
Subir los fuentes a GitHub y editar este fichero enlazando el último commit en el que
se indique claramente el nombre del alumno y la dirección donde se ha subido el
fuente. El commit se referirá al número de issue que se haya propuesto en el
repositorio propio. Si se va a hacer en coordinación con otros proyectos se puede
indicar en el mismo R EADME.md.
El Vagrantfile y todos los ficheros que precise estarán en un subdirectorio llamado
orquestacion. La IP a la que se ha desplegado, que se comprobará igual que en el
hito anterior, estará en una línea de este tipo
Descripción
Antes de desplegarse a producción, las aplicaciones tienen que probarse en un
entorno aislado. Generalmente se denomina staging a esta etapa en el desarrollo y
despliegue de la aplicación, y se usa algún tipo de entorno, similar en todo menos
en los usuarios al entorno de despliegue definitivo.
Prerrequisitos
Haber alcanzado el 60% de los objetivos del material correspondiente de la
asignatura. En el caso de que no se haya hecho, no se calificará este hito del
proyecto. Haber superado el hito anterior.
Explicación
El principal objetivo de esta práctica es familiarizarse con este tipo de infraestructura
virtual que se usa generalmente para dar un acceso limitado a una aplicación o un
servicio tal como un servidor web o a un usuario, que pueda acceder por ejemplo
sólo para depositar ficheros. Además de usarse para entorno de prueba, se puede
usar también como entorno de producción, en caso necesario, por ejemplo,
poniendo la aplicación en un contenedor de forma que se pueda desplegar con
seguridad en cualquier entorno IaaS o PaaS. De hecho, muchos PaaS usan docker
(o algún tipo de infraestructura similar, como l xc) para crear contenedores con los
que se ejecutan las aplicaciones.
Entrega de la práctica
Subir los fuentes a GitHub y hacer un pull request al documento de entregas como
es habitual. El documento tendrá que incluir el nombre del proyecto y un enlace a un
repositorio de contenedores docker o máquina virtual Azure o Amazon donde se
haya desplegado (o cualquier otro sistema). En caso de que el proyecto no sea
visible, una captura de pantalla, que como todas las capturas tendrá que ir en la
rama de documentación, es suficiente.
El URL del servicio web desplegado en un contenedor se pondrá en una sola línea
de esta forma
Contenedor: https://dirección.url
Como en la práctica anterior, esta dirección tendrá que tener instalado un servicio
web que devuelva status: OK, pero en este caso, en la ruta status, no en el directorio
principal; es decir, se tendrá que desplegar, como mínimo, el servicio web del hito
anterior del proyecto.
Descripción
Cuando una aplicación no cabe en un solo contenedor por la existencia de varios
tier, o simplemente nodos que sirven para almacenar datos, es necesario usar
Docker compose para describir de forma repetible la forma como se van a conectar
tales contenedores.
En esta práctica se trata de diseñar, usando Docker compose y describiendo la
infraestructura mediante un fichero docker-compose.yml, un servicio que incluya
varios contenedores, incluyendo uno cuyo contenido exclusivo sea almacenar datos.
Prerrequisitos
Haber alcanzado el 60% de los objetivos del material correspondiente de la
asignatura. En el caso de que no se haya hecho, no se calificará este hito del
proyecto. Haber superado el hito anterior.
Explicación
Docker-compose es una herramienta que, si bien no se usa en producción de forma
habitual, sí es muy útil en entornos de desarrollo o de prueba. También se puede
usar en producción, siempre que no se requieran escalado de cada uno de los
nodos u algún tipo de orquestación complicada, para lo que habría que usar
Kubernetes.
Entrega de la práctica
Subir los fuentes a GitHub y hacer un pull request al documento de entregas como
es habitual. El documento tendrá que incluir el nombre del proyecto y un enlace a un
repositorio de contenedores docker o máquina virtual Azure o Amazon donde se
haya desplegado (o cualquier otro sistema). En caso de que el proyecto no sea
visible, una captura de pantalla, que como todas las capturas tendrá que ir en la
rama de documentación, es suficiente.
El URL del servicio web desplegado en un contenedor se pondrá en una sola línea
de esta forma
Hito6: http://dirección.url
Como en la práctica anterior, esta dirección tendrá que tener instalado un servicio
web que devuelva status: OK, pero en este caso, en la ruta status, no en el directorio
principal; es decir, se tendrá que desplegar, como mínimo, el servicio web del hito
anterior del proyecto. Esto tendrá que implementarse como un servicio REST, y se
tendrá que devolver con el tipo MIME a pplication/JSON.
Hypervisors are virtualization platforms that create and manage virtual machines, allowing multiple operating systems to share a single physical host . They are classified as Type I, running directly on hardware, or Type II, running on top of an existing OS . In contrast, containers are lightweight and isolate applications within the same OS kernel rather than virtualizing entire machines, which makes them more efficient but less isolative than VMs .
Docker's 'copy on write' file system allows changes to be written on top of existing files without altering the original, thus conserving storage and making processes more efficient . This enables multiple containers to share common files while maintaining unique changes, facilitating quick and efficient container launches and management .
Configuration management tools like Chef and Ansible provide infrastructure as code, allowing systems to be described as programs with control over code and testing . They help automate configuration tasks such as software installation, configuration file editing, and user authentication. These tools enable efficient, reproducible, and scalable management of virtual infrastructures .
Using containerized applications allows for more efficient resource utilization, simplified application deployment, and consistent environments across development and production . Containers provide modularity and portability, reducing infrastructure dependency and facilitating CI/CD implementation, potentially leading to faster innovation and reduced operational costs .
Docker volumes allow data to be decoupled from containers, acting like transportable disks that can be moved and used with different containers . Unlike traditional storage where applications manage logs directly, Docker volumes store data independent of container lifecycle, enabling easier data sharing and persistence across different containers .
Microservices architecture allows for building applications as a collection of small, independently deployable services . PaaS platforms support this architecture by providing a scalable environment to deploy and manage these services efficiently, simplifying the deployment process and handling infrastructure concerns . This combination improves the agility and scalability of software development and deployment .
'Infrastructure as code' refers to managing and provisioning computing infrastructure through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools . This approach supports cloud automation by making infrastructure management more consistent, scalable, and repeatable, facilitating deployment across multiple cloud providers without manual intervention .
Orchestration tools coordinate and manage complex configurations across multiple VM clusters, automating tasks such as deployment, scaling, and management . They enable consistent policy application, resource optimization, and minimize manual interventions, thus enhancing overall operational efficiency and reliability .
Understanding the differences among these tools is crucial because each has unique features, strengths, and weaknesses that impact performance, scalability, and ease of use . Choosing the right tool depends on specific project requirements, existing infrastructure, and team expertise, which can significantly affect operational efficiency and automation success .
Docker containers offer greater deployment flexibility as they are lightweight, allowing faster startup and less resource consumption compared to VMs . They enable easy scalability and integration with CI/CD pipelines. VMs, on the other hand, provide better isolation and compatibility with varying operating systems but are heavier and slower to deploy and scale .