LIBRO - DevOps y Seguridad Cloud. Caparrós, Cubero, Guijarro (2017)

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 198

DevOps y

seguridad cloud
PID_00241996

Joan Caparrós Ramírez


Lorenzo Cubero Luque
Jordi Guijarro Olivares

Material docente de la UOC


© FUOC • PID_00241996 DevOps y seguridad cloud

Joan Caparrós Ramírez Lorenzo Cubero Luque Jordi Guijarro Olivares

Ingeniero superior en Informática Ingeniero superior en Informática Ingeniero en Informática por la


por la UAB, máster en Seguridad de por la UPC y máster en Gestión de UOC, ingeniero técnico en Informá-
las TIC por la UOC y máster en Dise- las tecnologías de la información tica de Sistemas por la UAB y más-
ño y programación de aplicaciones por La Salle. Ha desarrollado proyec- ter en Gestión de tecnologías de la
móviles por La Salle. Desarrollador tos de implantación de metodolo- información por la URL. Jefe de ope-
Fullstack web & mobile especializa- gías ágiles en equipos DevOps. Ac- raciones y seguridad tecnológica en
do en entornos de alto rendimien- tualmente lidera el equipo respon- el CSUC, donde lidera las activida-
to y seguridad. Actualmente realiza sable de los servicios TI de una mul- des técnicas en los ámbitos de infra-
funciones de técnico de proyectos tinacional suiza dedicada al marke- estructuras cloud y ciberseguridad
en el Área de Cálculo y Aplicaciones ting digital, Netcentric AG. del consorcio. También coordina
del Consorci de Serveis Universitaris el equipo de ciberseguridad CSUC-
de Catalunya (CSUC). @lj_cubero CSIRT de la red académica y de in-
https://www.linkedin.com/in/loren- vestigación catalana (Anella Científi-
https://www.linkedin.com/in/joan- ca), y colabora en proyectos a nivel
caparros zocubero
europeo en grupos de trabajo como
IRIS-CLOUD y la TF-CSIRT de la red
académica y de investigación euro-
pea GéANT.
@jordiguijarro
https://es.linkedin.com/in/jordigui-
jarro

El encargo y la creación de este material docente han sido coordinados


por el profesor: Josep Jorba Esteve (2017)

Primera edición: marzo 2017


© Joan Caparrós Ramírez, Lorenzo Cubero Luque, Jordi Guijarro Olivares
Todos los derechos reservados
© de esta edición, FUOC, 2017
Av. Tibidabo, 39-43, 08035 Barcelona
Diseño: Manel Andreu
Realización editorial: Oberta UOC Publishing, SL
Depósito legal: B-7.639-2017

Ninguna parte de esta publicación, incluido el diseño general y la cubierta, puede ser copiada,
reproducida, almacenada o transmitida de ninguna forma, ni por ningún medio, sea éste eléctrico,
químico, mecánico, óptico, grabación, fotocopia, o cualquier otro, sin la previa autorización escrita
de los titulares del copyright.
© FUOC • PID_00241996 3 DevOps y seguridad cloud

Contenidos

Módulo didáctico 1
Infraestructura DevOps
Joan Caparrós Ramírez, Lorenzo Cubero Luque y Jordi Guijarro Olivares
1. Introducción a DevOps
2. Fundamentos avanzados de DevOps
3. Infraestructura PaaS privada basada en contenedores: el caso Docker
4. Infraestructura PaaS pública: Cloud9, Heroku

Módulo didáctico 2
Casos de uso PaaS y de automatización completa
Joan Caparrós Ramírez, Lorenzo Cubero Luque y Jordi Guijarro Olivares
1. Caso de uso 1: Docker Machine y OpenNebula
2. Caso de uso 2: Docker Swarm Cluster con Consul sobre OpenNebula
3. Caso de uso 3: Balanceo transparente con Docker Swarm, Compose y
Consul
4. Herramientas de automatización completa y testing: Jenkins

Módulo didáctico 3
Introducción a la seguridad en cloud computing
Joan Caparrós Ramírez, Lorenzo Cubero Luque y Jordi Guijarro Olivares
1. Principales riesgos, patrones y mitigación proactiva de amenazas
2. Gestión de riesgos e incidentes de seguridad en cloud
3. Caso de Uso I: Seguridad en entornos IaaS públicos
4. Caso de uso II: Seguridad en entornos PaaS privados basados en Docker
5. Herramientas de seguridad
Infraestructura
DevOps
PID_00241997

Joan Caparrós Ramírez


Lorenzo Cubero Luque
Jordi Guijarro Olivares

Tiempo mínimo de dedicación recomendado: 7 horas


© FUOC • PID_00241997 Infraestructura DevOps

Ninguna parte de esta publicación, incluido el diseño general y la cubierta, puede ser copiada,
reproducida, almacenada o transmitida de ninguna forma, ni por ningún medio, sea éste eléctrico,
químico, mecánico, óptico, grabación, fotocopia, o cualquier otro, sin la previa autorización escrita
de los titulares del copyright.
© FUOC • PID_00241997 Infraestructura DevOps

Índice

Objetivos....................................................................................................... 5

1. Introducción a DevOps..................................................................... 7
1.1. El origen de la cultura DevOps ................................................... 7
1.2. Metodologías sobre las que trabaja DevOps ............................... 8

2. Fundamentos avanzados de DevOps............................................. 11


2.1. Introducción ................................................................................ 11
2.2. Gestión de la configuración ....................................................... 12
2.2.1. Ansible ........................................................................... 13
2.3. Integración continua ................................................................... 14
2.3.1. Buenas prácticas de integración continua ..................... 16
2.3.2. Beneficios de la integración continua ........................... 19
2.3.3. Jenkins en detalle .......................................................... 21
2.4. Estrategias de testing..................................................................... 22
2.4.1. Los cuadrantes del Agile Testing ................................... 24
2.4.2. La pirámide del testing.................................................... 26
2.4.3. Test Driven Development (TDD) ................................... 27
2.4.4. Acceptance Test Driven Development (ATDD) ............. 28
2.4.5. Behaviour Driven Development (BDD) ......................... 28
2.4.6. Testing exploratorio ........................................................ 29
2.4.7. Automatización de pruebas de regresión ...................... 29
2.4.8. Automatización de pruebas unitarias ............................ 29
2.5. Entrega continua ......................................................................... 29
2.5.1. Desplegando vía Jenkins ............................................... 30
2.5.2. Desplegando vía gestor de configuración ...................... 34
2.5.3. Estrategias para el despliegue ........................................ 35
2.6. Gestión de infraestructura y entornos ........................................ 36
2.6.1. Entornos involucrados en el desarrollo de software ...... 36
2.6.2. Gestión de la infraestructura ......................................... 37
2.6.3. Automatización de la configuración continua .............. 38
2.6.4. Detalle de una herramienta: SaltStack ........................... 39
2.7. Recomendaciones sobre gestión de los datos en entornos
DevOps ........................................................................................ 40
2.7.1. Versionado de la base de datos ..................................... 40
2.7.2. Objetivo: Evitar la pérdida de datos .............................. 41
2.7.3. Gestión de los datos de test .......................................... 41
2.7.4. Gestión de datos de test en la Deployment pipeline ..... 42

3. Infraestructura PaaS privada basada en contenedores: el


caso Docker.......................................................................................... 43
© FUOC • PID_00241997 Infraestructura DevOps

3.1. Introducción a Docker ................................................................ 43


3.1.1. Un poco de historia ....................................................... 43
3.1.2. Requisitos mínimos ....................................................... 43
3.1.3. Características ................................................................ 44
3.1.4. Ventajas y desventajas ................................................... 44
3.1.5. Usos y recomendaciones ............................................... 45
3.1.6. Arquitectura ................................................................... 45
3.1.7. Componentes ................................................................. 47
3.1.8. Diferencias con las máquinas virtuales ......................... 48
3.2. Instalación de Docker ................................................................. 49
3.2.1. Instalación en Ubuntu 14.04 ........................................ 49
3.2.2. Configuración opcional ................................................. 51
3.3. Administración de Docker .......................................................... 54
3.3.1. Principales comandos Docker ....................................... 55
3.3.2. Imágenes ........................................................................ 57
3.3.3. Trabajando con imágenes .............................................. 58
3.3.4. Ejecución de contenedores ............................................ 60
3.3.5. Creando imágenes Docker ............................................. 63
3.3.6. Detached o Background ................................................ 64
3.3.7. Mapeo de puertos .......................................................... 66
3.3.8. Docker Hub .................................................................... 67
3.3.9. Links................................................................................. 68
3.3.10. Volúmenes ..................................................................... 69
3.3.11. Variables de entorno ...................................................... 70
3.3.12. Configuración de red ..................................................... 70
3.3.13. Eliminar contenedores ................................................... 70
3.3.14. Dockerfile ....................................................................... 71

4. Infraestructura PaaS pública: Cloud9, Heroku......................... 80


4.1. Cloud9 ......................................................................................... 80
4.2. Heroku ......................................................................................... 82

Bibliografía................................................................................................. 85
© FUOC • PID_00241997 5 Infraestructura DevOps

Objetivos

Formar al estudiante en los principales conceptos avanzados de DevOps y mos-


trar cómo esta práctica fomenta y desarrolla los principios del cloud computing
para el uso de infraestructuras y el despliegue de aplicaciones en condiciones
de integración continua y plataformas colaborativas.
© FUOC • PID_00241997 7 Infraestructura DevOps

1. Introducción a DevOps

1.1. El origen de la cultura DevOps

Hoy en día las organizaciones que adoptan los principios y prácticas DevOps Enlace de interés
son capaces de realizar a diario centenares e incluso miles de cambios en sus
Si queréis saber más sobre
sistemas de producción. La ventaja competitiva de las empresas aumenta pro- Lean, podéis consultar el
porcionalmente a su time to market o capacidad de adaptar su producto al mer- siguiente enlace: <http://
www.lean.org/WhatsLean>.
cado lo antes posible; las organizaciones que no se preparen para acometer un
gran volumen de cambios diarios en su producto están condenadas a perder
en el mercado en el que compiten, incluso a quedarse fuera de este a largo
plazo, como ya ocurrió en el sector industrial con las empresas que no adop-
taron los principios Lean[1].

En las organizaciones TI que aún no han adoptado los principios y prácticas


DevOps existe un conflicto inherente entre el Departamento de Desarrollo y
el Departamento de Operaciones TI. A partir de ahora, nos referiremos a estos
departamentos como Desarrollo y Operaciones.

El resultado de este conflicto se refleja en un incremento del time to market para


nuevos productos y funcionalidades, reducción de la calidad, aumento de los
costes de servicio y, lo que es peor, una deuda técnica que no para de crecer. El
término deuda técnica fue acuñado por primera vez por Ward Cunningham[2].
Análogamente a la deuda financiera, la deuda técnica describe cómo las deci-
siones que tomamos provocan problemas que se van haciendo más difíciles
de solucionar con el tiempo. A menudo uno de los factores que contribuyen
a ello son los objetivos confrontados de Desarrollo y Operaciones. Las organi-
zaciones TI tienen numerosas responsabilidades, entre las que destacan:

• Responder al entorno competitivo, que cambia rápidamente (responsabi-


lidad de Desarrollo).

• Proporcionar un servicio estable, fiable y seguro al cliente (responsabilidad


de Operaciones).

De aquí la incapacidad de conseguir objetivos comunes entre Desarrollo y


Operaciones.

Resolviendo este conflicto, la puesta en práctica de DevOps nos permite al


mismo tiempo mejorar el rendimiento organizacional y ayudar a los distintos
roles de TI (Desarrollo, Calidad, Operaciones, Seguridad, etc.) a conseguir ob-
jetivos comunes.
© FUOC • PID_00241997 8 Infraestructura DevOps

La práctica de DevOps se basa en equipos relativamente pequeños que traba-


jan independientemente, implementando nuevas funcionalidades, validando
su corrección en entornos previos y desplegando el código a producción de
manera ágil, estable y segura. Los despliegues de código son rutinarios y pre-
visibles. En vez de hacer los despliegues a producción los viernes por la noche
y trabajar todo el fin de semana hasta que estén acabados, estos tienen lugar
durante la semana sin que los clientes lo noten, excepto cuando ven nuevas
funcionalidades o errores corregidos.

1.2. Metodologías sobre las que trabaja DevOps

Una parte de la comunidad considera los actuales fundamentos DevOps como


una derivación del movimiento Lean y la Teoría de Restricciones. Por otra
parte, hay quien considera DevOps como una evolución de la cultura Agile[3].
Esto se debe a que DevOps contiene tanto componentes de una vertiente como
de la otra; veamos los más importantes.

Del movimiento Lean, DevOps toma las técnicas Value Stream Mapping, los
Kanban Board y el Total Productive Maintenance.

El Value�Stream�Mapping, o mapeo de la cadena de valor, es un método para


analizar el estado actual y diseñar un estado futuro para la serie de eventos
que un producto o servicio requiere desde el inicio hasta que llega al cliente.
Este método analiza los artefactos materiales y el flujo de información.

Aplicado a la mejora del proceso de desarrollo de software de análisis de arte-


factos, tendría que ver con requerimientos de software, casos de uso, peticio-
nes de cambios o defectos durante el proceso de desarrollo.

Típicamente, se miden los tiempos que añaden valor al producto y los tiempos
que no añaden ningún valor; estos últimos se denominan pérdida o muda.

El Kanban�Board, o tablero Kanban, aplicado al desarrollo de software es una


herramienta en soporte físico o digital donde las tareas están representadas
por tarjetas organizadas en columnas de manera que podemos visualizar fácil-
mente su estado actual.

Consideremos la siguiente figura.


© FUOC • PID_00241997 9 Infraestructura DevOps

Figura 1. Tablero Kanban donde una tarea ha sido testada y espera a ser desplegada

Fuente: http://kanbanblog.com/explained/.

Permite visualizar las tareas y su estado actual dentro del flujo de trabajo, lo
que ayuda a entender cómo avanza el flujo de trabajo. La utilización de un
Kanban Board va asociada a una reducción de las tareas actualmente en proce-
so, focalizando así los esfuerzos en finalizar tareas en vez de empezar nuevas, lo
que aumentaría el número de tareas pendientes. Permite dirigir y gestionar el
flujo por medio de la supervisión, medición y realización de informes de tra-
bajo a nivel de estado. Por último, cabe comentar que esta es una herramienta
excelente para promover mejoras, puesto que al restringir el número de tareas
en circulación se destacan las áreas con problemas y esto facilita su resolución.

El Mantenimiento�Productivo�Total (TPM, en sus siglas en inglés) es un sis-


tema para mantener y mejorar la integridad de los sistemas de producción y
de calidad a través de las máquinas, equipos, procesos y personas que añaden
valor para el negocio de una organización. TPM se centra en mantener todo
el equipo en óptimas condiciones de funcionamiento para evitar averías y re-
trasos en los procesos de fabricación.

El Manifiesto� para� el� desarrollo� ágil de software fue firmado en 2001 por
los principales pensadores de desarrollo de software de la época. Estos querían
crear un conjunto ligero de valores y principios en contra de los procesos de
desarrollo tradicionales, como por ejemplo el método de desarrollo en cascada
o metodologías como el Proceso Racional Unificado.
© FUOC • PID_00241997 10 Infraestructura DevOps

Uno de los principios principales es entregar con frecuencia software que fun-
cione, desde un par de semanas hasta un par de meses, con preferencia por la
escala de tiempo más corta, haciendo clara alusión a su inclinación a desarro-
llar pequeños cambios o, dicho de otro modo, a entregar al cliente versiones
incrementales de manera frecuente.

Este manifiesto también aboga por equipos de trabajo pequeños y automoti-


vados, que trabajan en un entorno gestionado de manera que los empleados
crean en su trabajo.

La aplicación de este manifiesto y, por lo tanto, de metodologías ágiles ha in-


crementado drásticamente la productividad de muchas organizaciones dedi-
cadas al desarrollo de software.

El concepto de entrega�continua destaca por ser una de las técnicas funda-


mentales en la cultura DevOps. Se trata de una práctica utilizada para automa-
tizar y mejorar el proceso de entrega del software. Se utilizan técnicas como la
automatización de los test, la integración continua o el despliegue automático.
Esto permite desarrollar el software, proceder a su empaquetado y desplegar
en los entornos correspondientes de manera ágil. Como resultado, se adquiere
rapidez y fiabilidad en el proceso de mejora del software, ya sea por corrección
de errores o por desarrollo de nuevas funcionalidades, dado que el proceso se
repite de manera frecuente. También implica una minimización de los riesgos,
puesto que el proceso es altamente conocido, y reduce los recursos dedicados
respecto al proceso manual.
© FUOC • PID_00241997 11 Infraestructura DevOps

2. Fundamentos avanzados de DevOps

2.1. Introducción

Una vez vistos los conceptos básicos sobre DevOps, entramos en esta sección
en la materia necesaria para tener una visión más avanzada sobre el enfoque
del rol de DevOps.

• Uno de los puntos en los que centraremos nuestra atención es la gestión


de� la� configuración, que nos permitirá acercar todos los entornos que
utilizaremos para que sean lo más parecidos posible al entorno de produc-
ción final.

• Uno de los pilares de DevOps es la integración� continua, que permite


agregar los pequeños cambios realizados por los desarrolladores al conjun-
to de software desarrollado de manera que puedan ser testados y desple-
gados en entornos de desarrollo lo antes posible.

• Veremos también diferentes estrategias�de�testing, todas ellas con el ob-


jetivo de minimizar los posibles errores que puedan producirse en los en-
tornos productivos. Asimismo, se intentan detectar los errores en etapas
tempranas del desarrollo cuando su corrección es más sencilla y menos
costosa.

• Como continuación de la integración continua veremos el concepto de


entrega�continua en su aplicación más práctica, donde aprovecharemos
para explicar un extenso ejemplo.

Como consecuencia de los conceptos anteriores, también veremos cómo


afrontar los siguientes retos:

• La gestión�de�infraestructura y de los diferentes entornos resultado de


las distintas etapas de la entrega continua. Tanto la infraestructura como
los diferentes entornos deben ser extremadamente flexibles para adaptarse
rápidamente a los cambios que se puedan producir en las diferentes etapas
del desarrollo.

• La gestión�de�los�datos también representa un reto en cuanto que deben


ser persistentes y estar disponibles a pesar de que el software que da acceso
a ellos va cambiando constantemente.
© FUOC • PID_00241997 12 Infraestructura DevOps

Cabe mencionar también que durante este capítulo está en el ánimo de los
autores que se vayan examinando herramientas específicas y ejemplos donde
el lector pueda ir viendo aplicaciones directas de los conceptos vistos.

2.2. Gestión de la configuración

En los entornos empresariales actuales podemos encontrar distintas formas de


operar.

Algunas poseen máquinas físicas donde estas ejecutan el rol de servidor y ofre-
cen acceso a las aplicaciones desarrolladas. Esta forma de disposición de servi-
dores es una visión clásica y simple, muy utilizada durante años, con obvias
dificultades durante procesos habituales de migraciones de entorno y cambios
o ampliaciones exigidos en el hardware utilizado.

Una visión más moderna, con una perspectiva más amplia sobre los sistemas,
intentaría desvincular las máquinas físicas de los entornos de despliegue de
servidores, haciendo que estos sistemas sean más flexibles mediante la utili-
zación de herramientas de virtualización, como VMware, Xen, KVM, Virtual-
Box, entre otras.

Hemos descrito distintas formas de visión sobre los entornos de producción y


cómo se pueden presentar, pero ¿y los equipos de los entornos de desarrollo?
Imaginaos un equipo donde cada miembro trabaja en su propio ordenador,
algunos utilizando portátiles, otros con equipos de sobremesa, con configu-
raciones diferentes entre ellos, incluso con sistemas operativos distintos, ¿no
cabría esperar problemas derivados de esta diversidad?

Para la filosofía DevOps, los entornos de despliegue, tanto en desarrollo co-


mo en producción, toman una especial importancia. No solo es importante
poseer un entorno de servidor funcional donde desplegar una aplicación; co-
mo hemos visto, muchos de los problemas durante la puesta en producción
del software no derivan de fallos durante el proceso de desarrollo, sino que
se presentan durante el despliegue en entornos donde estos difieren en espe-
cificaciones: distintos sistemas operativos, versiones de software y paquetería,
configuraciones de seguridad, etc.

Para solucionar esta necesidad de homogeneización de entornos aparecen he-


rramientas como Chef y Puppet, que nos permitirán que los sistemas utiliza-
dos por el equipo de desarrollo sean exactamente iguales a los que se utilizarán
a posteriori durante el proceso de despliegue en entornos de producción. De
esta manera se eliminará cualquier error de incompatibilidades y los entornos
utilizados habrán sido testados durante las primeras fases del desarrollo del
proyecto.
© FUOC • PID_00241997 13 Infraestructura DevOps

Estas soluciones implican un cambio de concepto de todos los equipos impli-


cados en el desarrollo y despliegue de un proyecto, ya que la coordinación
para la construcción de un sistema inicial será una tarea compartida entre los
equipos de diseño de software y los equipos de operaciones encargados de la
gestión de máquinas y sistemas.

Existe una multitud de herramientas especializadas en la gestión de la confi-


guración donde los DevOps pueden apoyarse, entre las que destacan Puppet,
Chef y Ansible. En esta sección explicaremos algunos ejemplos introductorios
para la utilización de estas herramientas enfocadas a la disposición de entor-
nos homogéneos desarrollo-producción.

2.2.1. Ansible

Ansible es una plataforma de software libre (GPLv3) desarrollada en python Enlace de interés
y ofrecida comercialmente por AnsibleWorks. Brinda una forma simple de au-
Para saber más sobre Ansi-
tomatización de procesos TI. Puede configurar sistemas, realizar despliegues ble, podéis consultar el si-
de software y efectuar tareas avanzadas de despliegues continuos. guiente enlace: <https://
www.ansible.com/how-ansi-
ble-works>.
Estas son quizá sus características más importantes:

• Excelente rendimiento sin necesidad de instalación ni despliegues de


agentes.
• Bajo coste operativo (overhead muy bajo).
• Método de autenticación por ssh (preferiblemente con claves) en paralelo.
• No necesita usuario root (permite la utilización de sudo).
• Permite utilizar comandos básicos.
• Acepta comandos en casi cualquier lenguaje de programación.

Ansible puede utilizarse en modo Ad-Hoc o mediante playbook. El modo Ad-


Hoc nos permitirá ejecutar comandos en una sola línea sobre todos los hosts;
este método es utilizado cuando se pretenden realizar tareas simples sobre to-
dos nuestros hosts, mientras que para tareas más complejas los playbooks re-
sultarán mucho más cómodos.

Los playbooks son ficheros escritos en formato YAML, que pueden presentarse
en forma de un solo fichero o siguiendo un modelo estructurado, y contienen
todos los parámetros necesarios para realizar una determinada tarea sobre un
grupo de servidores.
© FUOC • PID_00241997 14 Infraestructura DevOps

Figura 2. Flujo de datos en Ansible

Fuente: <https://terry.im/wiki/terry/Ansible.html>.

2.3. Integración continua

El proceso de integración continua (continuous integration, CI) es un modelo


propuesto por Martin Fowler, científico de ThoughtWorks y considerado uno
de los gurús del desarrollo de software ágil y orientado a objetos, allá por el
año 2000.

Martin Fowler expuso:

«La integración continua es una práctica de desarrollo de software en la cual los miem-
bros de un equipo integran su trabajo frecuentemente, como mínimo de forma diaria.
Cada integración se verifica mediante una herramienta de construcción automática para
detectar los errores de integración tan pronto como sea posible. Muchos equipos creen
que este enfoque lleva a una reducción significativa de los problemas de integración y
permite a un equipo desarrollar software cohesivo de forma más rápida».

Martin Fowler (2006). «Continuous Integration».

La integración continua afecta especialmente al proceso de desarrollo del pro-


ducto, añadiendo nuevas prácticas y automatizando las que ya existían.

Durante el desarrollo de un nuevo proyecto, los desarrolladores integran nue-


vos cambios dentro del código original. Sabemos que todas estas nuevas apor-
taciones tienen que ser puestas en los entornos de producción frecuentemen-
te para asegurar un correcto desarrollo de las funcionalidades de nuestro pro-
yecto, y es aquí donde la idea de la integración continua toma sentido. Todo
proceso de integración continua comienza con la construcción de un proceso
continuo de integraciones automáticas de un proyecto lo más a menudo po-
sible; este proceso completo se conoce con el nombre de pipeline.

Las nuevas aportaciones serán dispuestas dentro del control de versiones (CVS,
Git, Subversion, Mercurial o Microsoft Visual SourceSafe) donde se guardarán
en el respectivo repositorio. El propósito de la integración continua será el de
© FUOC • PID_00241997 15 Infraestructura DevOps

procesar esta nueva versión, compilando el código, desplegando y testando de


manera automática, y devolviendo un informe a los desarrolladores con los
posibles errores que se hayan producido dentro del proyecto durante la fase
de test de este.

En este momento se produce una retroalimentación del sistema donde los


desarrolladores ejecutan un bucle de cambio de versión-compilación-test-co-
rrección, ya que los errores durante el proceso de integración son descubiertos
con rapidez, generalmente en cuestión de minutos u horas, según la planifi-
cación de la frecuencia establecida del proceso de integración.

Una vez que los cambios superan todas las pruebas, estos como tales pueden
ser integrados en el control de versiones de manera definitiva. La forma más
sencilla de ver reflejado este proceso se encontraría en la ejecución de estos test
donde el repositorio utilizado es el local y hasta no haber superado todas las
fases de comprobaciones estos no serán subidos al repositorio remoto. Estos
procesos pueden abstraerse a los repositorios remotos; ya existen métodos para
ejecutar el código durante el llamado pull-request antes de asimilarlos dentro
de la rama principal del proyecto.

En este punto, el código se ha visto testado e integrado al código final del


proyecto, podemos decir que está listo para la puesta en producción.

Figura 3. Flujo de trabajo en integración continua

Fuente: <http://www.retrieverconsulting.com/Continuous%20Integration%20Workflow.jpg>.
© FUOC • PID_00241997 16 Infraestructura DevOps

2.3.1. Buenas prácticas de integración continua

1)�Mantener�un�único�repositorio�de�código�fuente

El software de control de versiones es una herramienta indispensable para al-


macenar nuestro código fuente, y nos aportará información para hacer el se-
guimiento de todos los cambios que el código haya sufrido desde el inicio del
proyecto, reflejando qué ficheros han sido modificados y por quién.

Dentro del repositorio habrá que incluir todos aquellos ficheros necesarios
para poder construir nuestro proyecto. Hay que dar la posibilidad de que, una
vez descargada la última versión, cualquier usuario pueda compilar, desplegar
y ejecutar el proyecto de forma íntegra.

2)�Automatizar�la�construcción�del�proyecto

Construir un proyecto puede resultar una tarea laboriosa, ya que requiere en


muchas ocasiones la compilación del código fuente, y en el caso de sistemas
avanzados, la creación de una base de datos, carga de esquemas, populación
de la base de datos, carga de configuraciones, etc.

La automatización de construcción mediante scripts o herramientas como Ma-


ven y Ant será indispensable en todos los proyectos, y habrá que centrar todos
los esfuerzos en la fase de desarrollo.

3)�Elaboración�y�ejecución�de�los�test�dentro�de�la�construcción�del�pro-
yecto

Se deberá incluir dentro del proceso de desarrollo la elaboración del conjunto


de pruebas que certificarán que nuestro producto se comporta de una manera
adecuada. Cualquier error será detectado en esta fase y se dará la oportunidad
a los desarrolladores de modificar el código.

Existen numerosas herramientas para la construcción de test que simplifican la


creación de estos; algunas de las más conocidas serían JUnit para Java, Simple-
Test y PHPUnit para PHP, CPPUnit para C/C++, NUnit para la plataforma .NET,
PyUnit para python, etc.

4)�Integrar�como�mínimo�una�vez�al�día�los�cambios�en�la�línea�principal

Mantener la línea principal de código al día será fundamental para mantener a


los desarrolladores al día de los cambios que este vaya sufriendo. Si esta prácti-
ca se ejecuta cada poco tiempo, los desarrolladores deberán primero actualizar
su repositorio local, resolviendo cualquier conflicto existente antes de subir
los cambios que tengan preparados.
© FUOC • PID_00241997 17 Infraestructura DevOps

Manteniendo esta filosofía de actualizaciones de repositorio local y remoto,


se contribuirá a la resolución de conflictos cuando estos todavía son fáciles de
arreglar. Así pues, la integración de los cambios diariamente será básica para la
elaboración de un software donde los errores derivados de las actualizaciones
se detectan casi de manera inmediata.

5)�Construir�la�línea�principal�en�la�máquina�de�integración

A pesar de las continuas integraciones de los desarrolladores, todavía pueden


surgir problemas causados por la diferencia de plataformas de desarrollo entre
los miembros del equipo de desarrollo.

Será importante construir el proyecto dentro de la máquina de integración


para asegurar que nuestro código es funcional y que no contiene errores de
ejecución en la máquina de integración.

Las construcciones podrán realizarse de forma manual (en este caso el desa-
rrollador construirá el proyecto y quedará pendiente del resultado de este) o
mediante la utilización de un servidor de integración continua en el que se
construirán todas las aportaciones integradas a la línea principal de proyecto
y que reportará automáticamente a los desarrolladores cualquier error que du-
rante el proceso de construcción haya detectado.

6)�Mantener�una�ejecución�rápida�de�la�construcción�del�proyecto

Para asegurar un proceso de construcción y validación ágiles, se recomienda


dentro de lo posible mantener procesos de construcción rápidos, que no deben
superar los diez minutos.

En caso de que nuestro proceso de construcción y test supere el tiempo reco-


mendado, deberemos agilizar el tiempo de ejecución de la construcción del
proyecto. Para ello, limitaremos las pruebas dejando las más exhaustivas y
complicadas por ejemplo para ejecuciones elaboradas durante la noche. Así, se
agilizará el proceso de integración continua y cada día se poseerá un informe
completo del estado de todas las pruebas sobre la línea principal.

7)�Mantener�las�pruebas�de�integración�en�máquinas�réplicas�del�entorno
de�producción

Será importante que el lugar en el que se realicen las pruebas de construcción


y la ejecución del proyecto sea una réplica exacta del modelo de producción,
ya que cada posible diferencia entre entornos puede suponer un riesgo para la
correcta ejecución del código desarrollado.
© FUOC • PID_00241997 18 Infraestructura DevOps

Idealmente, las máquinas donde se realizará la integración continua deberán


ser una réplica, o por lo menos, en el caso de que no sea posible, lo más pareci-
das al entorno de producción en cuanto a sistema operativo, configuraciones,
versión de base de datos, etc., solo así podremos asegurar que el código, una
vez puesto en producción, no sufra errores no detectados con anterioridad.

8)�Almacenar�los�ejecutables�de�las�versiones�del�proyecto

Durante cada fase de prueba y construcción exitosa dispondremos de bina-


rios de los cuales podemos asegurar que han pasado los conjuntos de pruebas
unitarias y que se han probado en un entorno similar al de producción sin
ningún error; así pues, en cualquier etapa del sprint o iteración estaremos en
disposición de mostrar la última versión plenamente funcional, sin ningún
esfuerzo añadido.

Será importante mantener almacenados estos binarios para que todo el equipo
involucrado en el desarrollo del software pueda ejecutar la última versión,
facilitando las demostraciones y revisiones de los últimos cambios en la línea
principal del proyecto.

9)�Percepción�rápida�del�estado�y�cambios�del�sistema

Todos los miembros del equipo deben saber el estado en el que se encuentra la
línea principal del proyecto, Las herramientas web de los actuales servidores
de integración continua también tienen como misión la de informar en qué
estado se encuentra el proyecto, si se han aplicado cambios y si se han encon-
trado errores durante el proceso.

La comunicación del estado del proyecto es una de las partes más importantes,
y para ello existen soluciones elaboradas y creativas pero igual de efectivas
usando luces, lámparas de lava verdes y rojas totalmente integradas dentro del
sistema, semáforos de estado del servidor y una multitud de ideas para hacer
de este un proceso visible para todo el equipo.
© FUOC • PID_00241997 19 Infraestructura DevOps

Figura 4. Semáforo integrado con Jenkins basado en Raspberry Pi

Fuente: <https://en.wikipedia.org/wiki/Build_light_indicator>.

10)�Automatizar�el�despliegue

Para implementar una integración continua se necesita disponer de distintos


entornos: entornos de desarrollo, entornos de integración y entornos de pro-
ducción; estos ejecutarán las tareas de construcción y test varias veces al día,
por lo que se tiene que automatizar al máximo la fase de despliegue de apli-
caciones.

2.3.2. Beneficios de la integración continua

La configuración de una integración continua y el entorno de despliegue con-


tinuo añaden una cierta sobrecarga para el proyecto, pero los beneficios son
muy superiores.

Se incrementa la calidad del producto mediante la colaboración entre los desa-


rrolladores, lo que hace más simple la resolución de problemas de integración
de forma continua, y evita problemas durante las sucesivas fases de entrega
del producto.
© FUOC • PID_00241997 20 Infraestructura DevOps

Se incrementa la calidad del proceso: la automatización y la monitorización


de las pruebas continuas por parte del servidor de integración permiten crear
un proceso limpio de retroalimentación con los desarrolladores, que definirán
una filosofía de desarrollo óptima, que reducirá al mínimo cualquier error en
el producto final.

Se incrementa la calidad de las personas: la implementación de la integración


continua permite a los equipos trabajar en el desarrollo y la mejora continua
de pruebas, así como ejercer buenas prácticas de programación que a la vez
repercutirán en un código de mayor calidad. El proceso da seguridad al equipo,
ya que en todo momento sabrá que el proyecto está funcionando.

Vistas las ventajas de la integración continua, cabe señalar que existen distin-
tas herramientas que nos permitirán efectuar esta tarea. En este módulo co-
mentaremos una de las más usadas: Jenkins, que permite la elaboración com-
pleta del pipeline, desde la incorporación de código hasta el despliegue en los
distintos entornos.

A continuación se citan algunas de las herramientas más populares para rea-


lizar las tareas de integración continua (Reyes y Barroso, «Integración Conti-
nua», 2012, pág. 15).

• CruiseControl.
• CruiseControl.NET.
• CruiseControl.rb.
• Cruise.
• CI Factory.
• Drumbeat CI.
• Tinderbox & Tinderbox2.
• BuildBot.
• Anthill Professional.
• Anthill.
• Bamboo.
• Luntbuild professional.
• LuntBuild.
• Gump.
• Continuum.
• Sin.
• OpenMake Meister.
• OpenMake Mojo.
• Parabuild.
• Tinderbox3.
• Pulse.
• TeamCity(EAP).
• Jenkins.
• FinalBuilder Server.
• Zed.
© FUOC • PID_00241997 21 Infraestructura DevOps

• easyCIS.
• RedJack.

2.3.3. Jenkins en detalle

Jenkins es un software de integración continua open source escrito en Java, es-


tá basado en el proyecto Hudson y proporciona integración continua para el
desarrollo de software. Es un sistema corriendo en un servidor que es un con-
tenedor de servlets, como Apache Tomcat. Soporta herramientas de control de
versiones, como CVS, Subversion, Git o Mercurial, y puede ejecutar proyectos
basados en Apache Ant y Apache Maven, así como scripts de shell, etc.

Una de las características de Jenkins es que es tremendamente flexible, con


más de 350 plugins disponibles. Por ejemplo, es posible tener varios proyectos
configurados en el mismo servidor que utilicen diferentes versiones de JAVA
en el momento de la compilación.

Por otro lado, Jenkins es fácilmente clusterizable, lo que implica que se pueden
tener varios esclavos configurados en el mismo servidor maestro. La ventaja
más obvia es que se puede balancear la carga de los diferentes proyectos en
varios servidores; otra ventaja es que los esclavos pueden basarse en diferentes
arquitecturas, con lo cual se pueden compilar aplicaciones basadas en Linux
y otras en Windows bajo el mismo servidor maestro.

Otra característica de Jenkins son sus integraciones con Git, JMeter, SOAP-UI,
JUnit, Sonar, Nexus, etc. Esto permite ejecutar, por ejemplo, una batería de
test antes de proceder a la compilación del código con el objetivo de asegurar
un cierto grado de calidad, llegando incluso a abortar la compilación si los
resultados de los test no son satisfactorios.

Por último, Jenkins está diseñado para estar en constante comunicación con
los desarrolladores, y para ello consta de un potente sistema de notificaciones
para seguir el estado de los diferentes proyectos. Jenkins es capaz de enviar
correos, tuitear, activar señales luminosas o incluso sonoras, y mucho más
gracias a su amplia API.
© FUOC • PID_00241997 22 Infraestructura DevOps

Figura 5. Flujo de datos en Jenkins

Fuente: <https://code2read.files.wordpress.com/2015/11/jenkins.png>.

2.4. Estrategias de testing

Hemos visto que la integración continua va unida a una filosofía de agilización Enlace de interés
de los métodos adoptados por todos los miembros involucrados en el proyecto,
Para saber más sobre
pero ¿qué hay de la calidad del software? Es obvio que la calidad del producto estrategias de testing,
desarrollado tendrá que cumplir con los requerimientos funcionales acordados podéis consultar el si-
guiente enlace: <http://
en todas las fases de entrega. www.carlescliment.com/pu-
blications/calidad-e-integra-
cion-continua-enero-2012>.
En muchas ocasiones habremos escuchado «la fase de pruebas del proyecto se
ejecutará al final» o «no hay tiempo para poder aplicarlos de forma correcta»,
dando a entender que el proceso de QA demora el tiempo de desarrollo; este
modo de pensar no existe dentro de la metodología de integración continua.

En un entorno tradicional, los equipos de Testing solían ser un área indepen-


diente dentro de la empresa y formaban parte del ciclo de vida del producto.
Estos, mediante el uso de checklist, ejecutaban una y otra vez las mismas prue-
bas en cada nueva versión para asegurar que no se produjeran errores causados
por el cambio de versión. Como hemos visto, la metodología DevOps tratará
de asimilar esta forma de trabajar dentro de su fase de desarrollo.
© FUOC • PID_00241997 23 Infraestructura DevOps

Para asegurar en todo momento la calidad (valor) de nuestro proyecto, se defi-


nirán métodos ágiles de testing (agile testing) para acelerar las pruebas, testando
y analizando el código desarrollado. Cualquier versión no apta para pasar a
producción será desechada tan pronto como sea posible, con lo que nos aho-
rraremos pérdidas de tiempo que una mala integración hubiera supuesto.

La elaboración de los test cumplirá con la definición del acrónimo en inglés


FIRST:

1) Fast (rápido). Cuanto más rápidos se ejecuten los test, mayor será la fre-
cuencia con la que se ejecutarán. Los desarrolladores –mediante la ejecución
de subconjuntos de pruebas– pueden agilizar la fase de pruebas. Cabe remarcar
que antes de que el proyecto pase a producción se tendrán que haber pasado
el total de las pruebas; de lo contrario, no se podrá verificar que el software
desarrollado esté perfectamente acoplado, ya que se habrán testado sus partes
pero no en su totalidad.

Algunas de las herramientas destinadas al continual testing (CT), como Infini-


test, calculan qué test son más apropiados mediante el análisis de las depen-
dencias de código.

2) Isolated (aislado). Cada test debe tener una sola razón para fallar. El diseño
de cada prueba tiene que ser independiente de los factores externos e indepen-
diente de los resultados de test anteriores. La ordenación de pruebas unitarias
para mejorar el tiempo de ejecución es una señal de falta de aislamiento.

3) Repeatable (repetible). Los test deben devolver información sobre si han te-
nido éxito o no, y deben obtener los mismos resultados cada vez que se eje-
cutan. Ocasionalmente, las pruebas pueden fallar intermitentemente, debido
a razones de sobre-especificación en la fase de test, lentitud en la carga de de-
pendencias, uso de threads y procesos no deterministas, volatilidad de datos,
etc. En cualquier caso, los fallos ocasionales o intermitentes serán difíciles de
definir.

Para asegurar el correcto funcionamiento, se añadirán precondiciones que,


en el caso de no cumplirse, detendrán las pruebas antes de que estas puedan
empezar a ejecutarse.

4) Self-validating (autoverificado, sin ambigüedad). Para que un buen test veri-


fique que se ha superado de forma correcta, debe dar un resultado inequívoco,
descartando cualquier ambigüedad. Cuando todos los test son superados con
éxito, podemos tener una total confianza en el código desarrollado y pasar al
siguiente nivel. Si uno de los test fallase, el código sería puesto en disposición
del equipo de desarrollo para corregirlo.
© FUOC • PID_00241997 24 Infraestructura DevOps

Si alguno de los resultados de los test dejara aspectos ambiguos abiertos a la


interpretación humana, la validación de estos se convertiría en un lastre para
la productividad de los desarrolladores. Por tanto, se descartará cualquier tipo
de pruebas que puedan resultar ambiguas, ya que dejarán de ser útiles.

5) Timely (oportuno). ¿Cuando se deben escribir las pruebas?, ¿antes de escribir


el código o una vez está preparado para su construcción (build)?

Las pruebas deben desarrollarse en el momento oportuno. El desarrollo de los


test deberá realizarse antes del desarrollo del producto. Estos definirán el com-
portamiento del código que se pretende construir; así, ayudarán a entender en
todo momento lo que se pretende de las partes del código desarrollado.

Las pruebas escritas a posteriori requieren un esfuerzo adicional para los desa-
rrolladores, que deberán refactorizar el código hasta tener una batería de test
que cumplan con los principios mencionados (FIRST). Este modo de trabajar
da una sensación de invertir demasiado tiempo en el «pulido» de código y
puede desembocar en un abandono del desarrollo de pruebas.

2.4.1. Los cuadrantes del Agile Testing

Brian Marick en el 2003 expuso por primera vez en su blog la idea de clasificar
los diferentes tipos de pruebas ejecutadas durante el desarrollo del producto en
cuatro cuadrantes. Posteriormente, esta idea fue mejorada hasta resultar en la
imagen actual de los cuadrantes del Agile Testing. La misión fundamental de
la clasificación de las pruebas es ayudar a contextualizar y guiar a los equipos
durante la integración de las pruebas para garantizar la calidad del producto
desarrollado.

Figura 6. Cuadrantes del Agile Testing


© FUOC • PID_00241997 25 Infraestructura DevOps

Así pues, se presenta una matriz 2 x 2 donde los ejes definirán las pruebas
desde los diferentes puntos de vista posibles:

• El eje vertical definirá la orientación de las pruebas, pudiendo ser orienta-


das al negocio (business-facing), comprensibles por el usuario, o tomadas
desde el punto de vista tecnológico (technology-facing), descritas en lengua-
je de los desarrolladores para evaluar si el código se comporta de una ma-
nera correcta.

• El eje horizontal definirá el tipo de pruebas, basadas en el soporte de los


desarrolladores (supporting development) mediante la evaluación del código
interno o por los que critican el producto (critiquing the solution) a través
de la evaluación del sistema en contra de las necesidades del usuario.

La enumeración de los cuadrantes Q1, Q2, Q3 y Q4 no determina la impor-


tancia ni el orden del uso de las pruebas. Estos nombres no pretenden esta-
blecer ningún orden determinado de ejecución y están dispuestos de manera
arbitraria.

• Cuadrante�Q1: Contiene las pruebas unitarias y componentes. Estas prue-


bas, escritas por los desarrolladores, se ejecutan antes y después de cada
cambio en el código y sirven para confirmar que el sistema funciona co-
rrectamente. La automatización reducirá el tiempo dedicado en la fase de
test por parte de los desarrolladores y permitirá asegurar la calidad del pro-
ducto.

• Cuadrante�Q2: Contiene las pruebas funcionales (pruebas de aceptación


de usuario). Estas pruebas no unitarias basadas en la abstracción de histo-
rias de usuarios permiten validar el sistema desde un punto de vista más
técnico de lo que podría realizar un usuario final y son fácilmente auto-
matizables.

• Cuadrante� Q3: Contiene las pruebas de aceptación a nivel de sistema.


Estas serán ejecutadas de forma manual debido a la implicación de las
pruebas de aceptación del usuario, pruebas exploratorias y pruebas basadas
en los diferentes escenarios definidos validando si el comportamiento del
sistema cumple con los requisitos funcionales.

• Cuadrante�Q4: Contiene las pruebas de calidad del sistema y verifica si


este cumple con los requisitos no funcionales (NFR). Estas pruebas son fá-
cilmente automatizables y existen un amplio abanico de herramientas que
permiten realizar pruebas de rendimiento, pruebas de usabilidad, pruebas
de seguridad, pruebas de estabilidad, etc.
© FUOC • PID_00241997 26 Infraestructura DevOps

2.4.2. La pirámide del testing

La pirámide del Agile Testing es una manera práctica de describir la diferencia


entre las pruebas de software tradicional y las pruebas durante el desarrollo
iterativo. Este concepto fue descrito por primera por Mike Cohn.

Figura 7. Pruebas tradicionales frente a Agile Testing

Fuente: <http://www.pmoinformatica.com/2015/03/que-es-el-agile-testing.html>.

Las pruebas tradicionales pueden ser descritas por la pirámide de la izquierda.


La mayoría de los test se llevan a cabo utilizando planes de prueba de forma
manual que implican el uso de la interfaz gráfica. En la parte central, algunos
de los test serán lanzados automáticamente para poner a prueba los servicios
del producto, y finalmente en última posición encontraríamos algunos test
unitarios.

Esta forma de pensar fue diseñada para encontrar errores, dentro de una men-
talidad tradicional por etapas en las que se codifica y se corrige. Los desarrolla-
dores parten de la idea de que su código es perfecto, y a continuación el equipo
de test prueba a conciencia el producto para reportar cualquier problema en
caso de ser detectado, lo que alarga considerablemente la fase de codificación
y prueba.

Desde el punto de vista del Agile Testing, la pirámide aparece de forma inver-
tida (lado derecho de la figura 7). Esta nueva manera de enfocar las pruebas
presenta una base sólida, donde la automatización adquirirá un peso impor-
tante y con ello una mayor contribución por parte de los desarrolladores para
evitar errores. La parte superior de la pirámide es muy pequeña, la interfaz del
usuario es un elemento cambiante, cualquier modificación significa un cam-
© FUOC • PID_00241997 27 Infraestructura DevOps

bio en los test, con el consecuente gasto de tiempo en el desarrollo. El mante-


nimiento de la capa de test puede superar fácilmente al valor de las pruebas
en la capa de la interfaz y deberá mantenerse como una capa con test básicos.

La automatización de los procesos de test implica una visión clara del sistema
y cómo este debe ejecutarse, asegurando que cada vez que se pasan los test, el
código desarrollado cumpla las especificaciones funcionales de forma correcta.
La esencia del nivel medio de la pirámide recaerá en la capa lógica de nuestro
software (reglas de negocio, servicios...), que encontraremos inmediatamente
por debajo de la interfaz gráfica; así, en esta capa las pruebas automatizadas
pueden ser ejecutadas asegurando que estas funcionan correctamente sin tener
que utilizar la interfaz de usuario con herramientas tipo Selenium.

La pirámide Agile requiere un cambio de mentalidad en las organizaciones: los


desarrolladores validarán su propio trabajo mediante los juegos de test unita-
rios e incluirán una etapa de decisión sobre las herramientas que utilizar para
efectuarlos. Dependiendo del lenguaje usado en la codificación del software,
podremos elegir por ejemplo implementaciones típicas dentro de la familia
xUnit.

En esta fase aparecen diferentes enfoques sobre cómo realizar las pruebas, ba-
sándose en distintas prácticas relacionadas con el Agile Testing.

2.4.3. Test Driven Development (TDD)

Mediante el desarrollo dirigido por pruebas orientamos el enfoque primero


a la elaboración de los test para después desarrollar el código. Tras el primer
cambio de mentalidad este método es muy productivo, ya que obliga a enfren-
tarse al problema desde el punto de vista del resultado, y una vez finalizado el
desarrollo, ya se dispone del conjunto de pruebas que ejecutar.

Los bugs detectados servirán para ampliar el conjunto de pruebas y hacerlas


a su vez más robustas.

La granularidad de la codificación permitió escribir las conocidas tres leyes del


TDD:

• No se deberá escribir ningún código antes de haber escrito un test unitario


que falle.

• No se deberá escribir más de una prueba que falle en ejecución o en com-


pilación.

• No se deberá escribir más código que el suficiente para hacer pasar el test
actual.
© FUOC • PID_00241997 28 Infraestructura DevOps

Ejecutando estas tres leyes se entrará en un ciclo rápido, en el que será nece-
sario iterar varias docenas de veces antes de finalizar una unidad de test com-
pleta.

Red�-�Green�-�Refactor

Este método se interpreta como un microciclo dentro del desarrollo dirigido Cita
por pruebas, y es ejecutado en cada comprobación total de los test o cada n
«Make it work. Make it right.
ciclos de estos. El proceso empezará con la definición de una prueba que falle, Make it fast». Ken Beckt
fase que es conocida como Red por el color en el que se suelen mostrar los «Getting software to work is
only half of the job». Robert C.
resultados fallidos en las herramientas de testing. Martin

Dado un test fallido, el segundo paso será implementar el código mínimo para
hacer que este lo pase; en este momento nos encontraremos en fase Green.

El último paso dentro del ciclo Red - Green - Refactor se centra en la limpieza
de código, eliminando duplicidades y refactorizando el código.

Esta filosofía está basada en la idea de que nuestra mente está limitada y no es
capaz de llevar a cabo dos objetivos simultáneamente: hacer que el software
funcione correctamente y que el software posea una estructura correcta.

2.4.4. Acceptance Test Driven Development (ATDD)

Se describe el ATDD como la práctica en la que todo el equipo, clientes, desa-


rrolladores y testers analizan y discuten conjuntamente los criterios de acepta-
ción. Esta tarea dará como resultado un conjunto de pruebas aceptables de las
que los desarrolladores dispondrán antes de empezar con su tarea. Poniendo
las ideas en común se asegura que todos los miembros comparten una misma
visión del proyecto y de lo que se espera obtener de él.

2.4.5. Behaviour Driven Development (BDD)

También conocido como Story Driven Development, es una evolución en la


forma de pensar que encontramos detrás del TDD y el ATDD. Este enfoque se
inicia con el análisis de una prueba funcional o una historia de usuario que es
desarrollada mediante las fases del TDD hasta que se superan todas las pruebas.
BDD establece que:

• Solo se desarrollarán aquellos comportamientos que contribuyan directa-


mente a satisfacer las pruebas que superar con el fin de minimizar código
residuo o no utilizado.

• Se describirán los comportamientos en una notación común para los ana-


listas, los desarrolladores y los testers con el fin de mejorar la comunica-
ción.
© FUOC • PID_00241997 29 Infraestructura DevOps

2.4.6. Testing exploratorio

El testing exploratorio se define como un enfoque simultáneo del aprendizaje


de la funcionalidad, el diseño de pruebas y la ejecución de pruebas. Este es un
método que valora a los testers como una parte integral del proceso, y ayuda
a los desarrolladores a mantenerse al día con el desarrollo de los proyectos de
software ágiles, cambiando la mentalidad de la visión estructurada de la fase
de la construcción del proyecto al hacerla más global.

2.4.7. Automatización de pruebas de regresión

La ejecución de las fases del TDD define una continua modificación del códi-
go, donde en cualquier momento del desarrollo pueden surgir carencias de
funcionalidades o comportamientos no esperados del software. Las pruebas
de regresión intentan descubrir los errores producidos por cambios dentro del
proyecto. Estos errores normalmente son producidos por errores en la contex-
tualización, que exponen fragilidades del rediseño de nuestra aplicación.

Tanto la integración continua como la refactorización deberán incluir pruebas


de regresión automatizadas para asegurar un correcto funcionamiento de la
aplicación en todo momento.

2.4.8. Automatización de pruebas unitarias

Mediante la utilización de herramientas de la familia XUnit, los desarrollado-


res dispondrán de un framework completo donde poder elaborar pruebas uni-
tarias y en el que asegurar que cada componente de la aplicación produce una
salida determinada para una entrada dada.

Las pruebas serán ejecutadas en cada modificación del código automáticamen-


te y notificadas al equipo para asegurar que todas las funcionalidades devuel-
ven un valor esperado.

2.5. Entrega continua

Hoy en día, la entrega continua se entiende como la evolución lógica de la in-


tegración continua, de tal modo que para que los cambios realizados en Desa-
rrollo puedan ser susceptibles de ser entregados en Producción en el menor
tiempo posible, minimizando los riesgos de implantación.

Gracias a este proceso, podemos evitar largas puestas en producción, las sor-
presas de última hora y los cambios muy grandes y costosos, evitando que
haya demasiada incertidumbre a la hora de la entrega y teniendo un mayor
control sobre todo el proceso.
© FUOC • PID_00241997 30 Infraestructura DevOps

Esta metodología es usada por grandes compañías, como Flickr, con varios
despliegues diarios; Amazon, liberando en producción una versión cada 11,6
segundos de media; y Facebook, desplegando la compilación de código en
producción al menos una vez al día con cambios menores o una vez a la se-
mana con cambios mayores.

Figura 8. Flujo de datos en la entrega continua

Fuente: <https://s3.amazonaws.com/media-p.slid.es/uploads/stevenmaguire/images/723464/chart-continuous-delivery.png>.

Una vez vistos los conceptos de control de versiones, la integración continua


y las diferentes estrategias de test, ahora pondremos el foco en las diferentes
estrategias de despliegue en producción.

En cuanto a herramientas, se pueden utilizar tanto las propias herramientas


de integración continua como el propio servidor Jenkins; y también se pueden
utilizar las propias herramientas de gestión de configuración como Puppet o
Chef.

2.5.1. Desplegando vía Jenkins

En este caso, Jenkins nos ofrece la flexibilidad tanto de acceder a los servidores
de producción para hacer la transferencia de la nueva versión del software, por
ejemplo en el caso de desplegar código php en una aplicación basada en web,
como de utilizar uno de los muchos plugins que ofrece Jenkins.

El siguiente ejemplo corresponde a la configuración XML de un proyecto Ma-


ven que compila el código JAVA de un repositorio Git y lo despliega en el en-
torno de producción:
© FUOC • PID_00241997 31 Infraestructura DevOps
© FUOC • PID_00241997 32 Infraestructura DevOps
© FUOC • PID_00241997 33 Infraestructura DevOps

Hasta el momento, para conseguir una pipeline de integración continua usan-


do Jenkins, teníamos que definir dependencias entre proyectos. De esta ma-
nera, se ejecutaban en orden y se lograba la pipeline deseada. La versión 2.0 de
Jenkins soluciona las limitaciones anteriores porque permite definir las fases
del flujo: Checkout, Build, Test y Deploy gracias al plugin Pipeline; de esta
manera, se pueden ejecutar en paralelo acciones correspondientes a la misma
fase.

Cabe destacar que dicha pipeline puede ser generada mediante código, lo que
permite hacer cambios muy fácilmente y usar control de versiones sobre las
pipelines.

Figura 9. Flujo definido usando el plugin Pipeline

Fuente: <https://jenkins.io/doc/book/pipeline/overview/>.

Para finalizar el ejemplo de despliegue basado en Jenkins veamos la nueva


interfaz Blue Ocean, que nos muestra de una manera visual las diferentes fases
y sus partes.
© FUOC • PID_00241997 34 Infraestructura DevOps

Figura 10. Visualización del flujo mediante la interfaz Blue Ocean

2.5.2. Desplegando vía gestor de configuración

Veamos ahora el uso de un gestor de configuración para realizar el despliegue


en un entorno de testing. En este caso, igual que en el anterior, debemos reali-
zar previamente el proceso de integración continua donde se genera una ver-
sión nueva; en este ejemplo generamos un fichero instalable tipo RPM Packa-
ge Manager, en adelante rpm. Este fichero es transferido a un servidor de dis-
tribución tipo Nexus Repository OSS accesible por el gestor de configuración,
que en este caso actúa de herramienta de aprovisionamiento.

Figura 11. Despliegue mediante Nexus y un gestor de configuración

En el caso de utilizar Puppet, el Puppet master será el encargado de distribuir


el paquete. Los nodos del entorno de testing que así lo tengan configurado
verán su versión del software automáticamente actualizada. El detalle de la
configuración sería el siguiente:
© FUOC • PID_00241997 35 Infraestructura DevOps

Figura 12. Detalle de la configuración de un nodo de test

Como podemos ver, tendríamos una clase test donde definimos que queremos
instalar siempre la última versión del paquete ejemplo. Esta clase la aplicare-
mos a tantos nodos como queramos (en la anterior figura se ha aplicado al
nodo servidor-test).

2.5.3. Estrategias para el despliegue

El despliegue en producción es el paso más crítico. Se puede hacer desplegando


código nuevo directamente o implementando un cambio de configuración, y
esto se puede realizar de varias maneras:

• Implementando una instalación paralela de una nueva versión del código


y pasar a la nueva instalación con un cambio de configuración.

• Desplegando una nueva versión del código con el comportamiento anti-


guo y un indicador de característica, y cambiar al nuevo comportamiento
con un cambio de configuración.

• Mediante el despliegue de servidores independientes (uno que ejecute el


código antiguo, y uno nuevo) y redirigir el tráfico del antiguo al nuevo
con un cambio de configuración en el nivel de enrutamiento de tráfico.
Estos a su vez pueden hacerse de una vez o gradualmente.

La implementación de una nueva versión generalmente requiere un reinicio, a


menos que el intercambio en caliente sea posible y, por lo tanto, requiere una
interrupción en el servicio o implementar redundancia: reiniciando las ins-
tancias detrás de un balanceador de carga o iniciando nuevos servidores antes
de tiempo y luego simplemente redirigir el tráfico a los nuevos servidores.

Al implementar una nueva versión en producción, en lugar de implementarla


inmediatamente en todas las instancias o usuarios, puede desplegarse en una
sola instancia o fracción de usuarios primero y, a continuación, desplegarse a
todos o gradualmente desplegarse en fases para captar cualquier tipo de pro-
© FUOC • PID_00241997 36 Infraestructura DevOps

blema. Esto agrega complejidad debido a que múltiples versiones se ejecutan


simultáneamente, pero reduce el impacto en caso de que aparezcan problemas
en producción.

2.6. Gestión de infraestructura y entornos

La gestión�de�infraestructura y de los diferentes entornos debe dar respuesta


al diseño de las diferentes etapas de la entrega continua. Tanto la infraestruc-
tura como los diferentes entornos deben ser extremadamente flexibles para
adaptarse rápidamente a los cambios que se puedan producir, ya que las etapas
de desarrollo son tremendamente dinámicas.

2.6.1. Entornos involucrados en el desarrollo de software

Para dar cobertura al desarrollo basado en DevOps, debemos definir diferentes


entornos donde se realizarán distintas tareas de validación que nos permitan
progresar al siguiente entorno.

Empecemos viendo una configuración de entornos típica en escenarios De-


vOps:

Figura 13. Detalle de una configuración de entornos típica

Fuente: <https://www.infoq.com/articles/Continous-Delivery-Patterns>.

1)�Desarrollo�local

Normalmente empezamos en el ordenador del desarrollador, donde el nuevo


código generado se compila localmente y se realiza una prueba inicial. Para
esto se utilizan herramientas como Virtualbox o Vagrant, que permiten des-
plegar el nuevo código en un entorno parecido al entorno de producción. Fi-
nalmente, se traslada el nuevo código al entorno de integración.

2)�Entorno�de�integración

En este entorno es donde se guardan los nuevos cambios y se compilan para


integrarlos con el resto del código. Para ello, se utilizan herramientas como
Git para la gestión del código fuente y Jenkins como servidor de integración.
En este paso el propio servidor de integración normalmente incorpora como
mínimo una batería de pruebas unitarias.

3)�Entorno�de�test
© FUOC • PID_00241997 37 Infraestructura DevOps

En este entorno es donde se producen los test de regresión y funcionales. Co-


mo hemos visto, con estos test aseguramos que no se ha dañado ninguna fun-
cionalidad disponible en el software y que las nuevas funcionalidades se ajus-
tan a los requerimientos.

4)�Entorno�de�preproducción

El entorno de preproducción o staging es una réplica del entorno de produc-


ción. En este entorno se dan por probadas las funcionalidades del software y
el objetivo es realizar las pruebas de integración con otras piezas de software;
probar la instalación, configuración y scripts de migración; y realizar test de
rendimiento, en concreto pruebas de carga, ya que estas son muy dependien-
tes del entorno.

5)�Entorno�de�producción

Por último, tenemos el entorno de producción, donde los usuarios interactúan


con el software desplegado.

2.6.2. Gestión de la infraestructura

Una vez vistos los diferentes entornos, veamos cómo se gestiona mediante
código la infraestructura sobre la que corren dichos entornos.

Infrastructure�as�code es el proceso de gestión y aprovisionamiento de la in-


fraestructura (procesos, servidores bare-metal, servidores virtuales, etc.) y su
configuración a través de archivos de definición de infraestructura procesables
por una máquina, en lugar de la configuración física del hardware o el uso de
configuración interactiva. Los archivos de definición pueden encontrarse en
un sistema de control de versiones. IaC se basa en definiciones declarativas,
en lugar de procesos manuales de gestión de la infraestructura.

Los enfoques de infraestructura como código se han ido extendiendo con la


adopción del cloud computing, que a veces se comercializa como «infraestruc-
tura como servicio» (IaaS). IaC apoya IaaS, pero son conceptos distintos que
no deben confundirse.

El valor de la infraestructura como código puede desglosarse en tres categorías


medibles: coste, velocidad y riesgo. La reducción de costes tiene como objetivo
ayudar no solo a la empresa financieramente, sino también en términos de
personas y esfuerzo, lo que significa que mediante la eliminación del compo-
nente manual, las personas son capaces de reorientar sus esfuerzos hacia otras
tareas empresariales. La automatización de la infraestructura permite una eje-
cución más rápida a la hora de configurar su infraestructura y tiene como obje-
tivo proporcionar visibilidad para ayudar a otros equipos a trabajar de manera
rápida y eficiente. La automatización elimina el riesgo asociado con el error
humano, como la configuración errónea manual, y eliminarlo puede reducir
© FUOC • PID_00241997 38 Infraestructura DevOps

el tiempo de inactividad y aumentar la fiabilidad. Estos resultados y atributos


ayudan a la empresa a avanzar hacia la implementación de una cultura de
DevOps, el trabajo combinado de Desarrollo y Operaciones.

Generalmente, hay tres enfoques para IaC: declarativo o funcional, imperati-


vo o procedimental e inteligente o consciente del entorno. El enfoque decla-
rativo se centra en lo que debería ser la configuración final de destino. El im-
perativo se centra en cómo se va a cambiar la infraestructura para satisfacerla.
Y el enfoque inteligente se centra en por qué la configuración debe ser una
cierta manera en la consideración de todas las relaciones y dependencias de
múltiples aplicaciones que se ejecutan en la misma infraestructura.

El enfoque declarativo define el estado deseado y el sistema ejecuta lo que


necesita suceder para lograr ese estado deseado. El imperativo define coman-
dos específicos que deben ejecutarse en el orden adecuado para finalizar con
la conclusión deseada. Y el inteligente determina el estado correcto deseado
antes de que el sistema ejecute lo que necesita suceder para lograr un estado
deseado que no afecta a las aplicaciones dependientes.

La infraestructura como código es clave en la práctica de DevOps. Los desarro-


lladores se involucran más en la definición de la configuración y los equipos
de operaciones se involucran más temprano en el proceso de desarrollo. Las
herramientas que utilizan IaC aportan visibilidad al estado y configuración de
los servidores y, en última instancia, brindan visibilidad a los usuarios dentro
de la empresa, con el objetivo de reunir equipos para maximizar sus esfuerzos.
La automatización, en general, tiene como objetivo tomar la confusión y el
aspecto propenso a errores de los procesos manuales y hacerlo más eficiente
y productivo. También, permitir que el software y las aplicaciones sean crea-
dos con flexibilidad, menos tiempo de inactividad y una forma globalmente
rentable para la empresa. IaC pretende reducir la complejidad que mata la efi-
ciencia de la configuración manual. La automatización y la colaboración se
consideran puntos centrales en DevOps. Las herramientas de automatización
de la infraestructura a menudo se incluyen como componentes de una cadena
de herramientas de DevOps.

2.6.3. Automatización de la configuración continua

Todas las herramientas de automatización de configuración continua (CCA)


pueden considerarse como una extensión de los marcos IaC tradicionales.
Aprovecha IaC para cambiar, configurar y automatizar la infraestructura, pero
también proporciona visibilidad, eficiencia y flexibilidad en el manejo de su
infraestructura.

Un aspecto importante al considerar las herramientas de CCA, si son de códi-


go abierto, es el contenido de la comunidad. Como afirma Gartner, el valor
de las herramientas de CCA es «tan dependiente del contenido y el apoyo
aportados por la comunidad de usuarios como lo es la madurez comercial y
© FUOC • PID_00241997 39 Infraestructura DevOps

el rendimiento de la herramienta de automatización». Vendedores como Pup-


pet y Chef han creado sus propias comunidades: Chef tiene Chef Community
Repository y Puppet tiene PuppetForge; otros proveedores confían en comu-
nidades adyacentes y aprovechan otros marcos IaC, como PowerShell DSC.
Aparecen nuevos proveedores que no son impulsados por el contenido, sino
por el modelo con la inteligencia del producto para ofrecer contenido. Estos
sistemas visuales orientados a objetos funcionan bien para los desarrollado-
res, pero son especialmente útiles para operaciones orientadas a entornos de
producción que valoran versiones de modelos de versiones de contenido. A
medida que el campo continúa desarrollándose y cambiando, el contenido
basado en la comunidad será cada vez más importante para la forma en que
se utilizan las herramientas de IaC.

Las herramientas CCA incluyen: Ansible, CFEngine, Chef, Puppet, Otter o Sal-
tstack.

2.6.4. Detalle de una herramienta: SaltStack

SaltStack es una herramienta de código abierto basada en Python para la ges-


tión de configuración mediante un motor de ejecución remota. Da apoyo al
enfoque de «Infraestructura como código» para la implementación del cloud.

En cuanto a su arquitectura, se puede desplegar en modo master: un servidor


master y sus correspondientes minions (agentes en los nodos esclavos); o bien
en modo masterless. Si se opta por el modo master, es posible prescindir de
los minions, en este caso el master se conecta a los nodos esclavos vía Secure
Shell o SSH.

En cuanto a la configuración del propio SaltStack para la gestión de los dife-


rentes minions, se compone de un fichero principal que hace referencia a otros
ficheros de configuración específicos llamados fórmulas.

En el siguiente ejemplo vemos cómo todos los minions tienen definidas unas
fórmulas por defecto y luego, dependiendo del rol del minion en cuestión, se
le aplican unas fórmulas u otras. En concreto, a todos los minions se les aplican
las fórmulas: vim, scripts y users; a los minions con rol web: apache, python y
django; y a los minions con rol db: mysql.

Vemos que en las fórmulas se pueden instalar paquetes y aplicar ficheros de


configuración, como en el caso de la fórmula para vim. También se pueden
instalar y configurar servicios, como en el caso de apache, donde incluso se
marca el servicio para que se ejecute en tiempo de arranque del minion.
© FUOC • PID_00241997 40 Infraestructura DevOps

Figura 14. Fichero principal y fórmulas de SaltStack


Enlace de interés

Si queréis aprender más so-


bre SaltStack, os recomen-
damos que lo instaléis y
empecéis a practicar. En
https://docs.saltstack.com/
en/getstarted/fundamen-
tals/install.html encontraréis
una guía para la instalación
inicial.

2.7. Recomendaciones sobre gestión de los datos en entornos


DevOps

2.7.1. Versionado de la base de datos

Una buena práctica es la automatización de la gestión de las versiones me-


diante scripts de migración; estos:

• Inicializan el esquema, las credenciales y los datos.


• Realizan una copia temporal de tablas para facilitar el roll-back de datos.
• Utilizan una de las tablas para almacenar la versión actual de la base de
datos.

Veamos un ejemplo del uso de los scripts de migración por los que pasamos de
la versión base de base de datos FW hasta la versión 0.3 actual de desarrollo.
© FUOC • PID_00241997 41 Infraestructura DevOps

Figura 15. Ejemplo detallado del uso de scripts de migración

Fuente: <http://comunidad.iebschool.com/perezmvictoria/2014/05/01/proceso-del-versionado-para-bases-de-datos/>.

Dicha automatización permite la ejecución de scripts sucesivos para versionar


hacia adelante (x + 1) o hacia atrás (x).

2.7.2. Objetivo: Evitar la pérdida de datos

En caso de roll-back, el objetivo principal es evitar la pérdida de datos. Algunos


scripts de roll-back pueden perder datos. Para evitar esta situación, se puede:

• Grabar y reproducir las transacciones desde el «transaction log».

• Usar despliegues «blue-green». Los usuarios vuelven a la versión «blue» en


caso de roll-back y se reproducen las transacciones nuevas de «green».

• Despliegues desacoplados de aplicación y datos. Permiten desplegar el


cambio a la BD una vez que se ha estabilizado el cambio de versión.

2.7.3. Gestión de los datos de test

Para controlar el rendimiento de los test, tenemos:

• Test unitarios: uso de la base de datos en memoria, por ejemplo usando


el patrón DAO.

• Test de aceptación: uso de data-sets moderados, inferiores a los de produc-


ción.
© FUOC • PID_00241997 42 Infraestructura DevOps

Acoplamiento entre test y datos: los juegos de pruebas deben inicializar el


estado de los datos al comenzar y restaurarlo al acabar. Las estrategias más
comunes son:

• Aislamiento: los test se pueden ejecutar en cualquier orden o en paralelo.


Se puede conseguir utilizando las transacciones de la BD (roll-backs). Es la
opción más flexible y segura.

• Adaptativos: los test calculan los resultados esperados de salida a partir


del «estado» encontrado.

• Secuencia: cada test genera el estado de entrada del siguiente.

2.7.4. Gestión de datos de test en la Deployment pipeline

1)�Sobre�los�datos�para�los�test�de�commit

Son datos más bien livianos para que los test sean rápidos. Esto se consigue
no sobreelaborando la definición de entradas y salidas para mantener la inde-
pendencia sobre implementaciones concretas.

2)�Sobre�los�datos�para�los�test�de�aceptación

Son más realistas y complejos. Para gestionarlos de manera eficiente, se pueden


agrupar como:

• Específicos del test: son creados y modificados por el test.


• Referenciados del test: son creados por la suite y consultados por el test:
– Los datos para los test de capacidad.
– Generales que requiere la aplicación para funcionar e independientes
del test.

Cabe indicar que los test de aceptación requieren un gran volumen de datos
de entrada y datos referenciados, y estos deben obtenerse a partir de datos y
proporciones reales.
© FUOC • PID_00241997 43 Infraestructura DevOps

3. Infraestructura PaaS privada basada en


contenedores: el caso Docker

3.1. Introducción a Docker

Docker es un proyecto de código abierto que permite automatizar el despliegue


de aplicaciones dentro de «contenedores». Este contenedor empaqueta todo
lo necesario para que uno o más procesos (servicios o aplicaciones) funcionen:
código, herramientas del sistema, bibliotecas del sistema, dependencias, etc.
Esto garantiza que siempre se podrá ejecutar, independientemente del entorno
en el que queramos desplegarlo. No hay que preocuparse de qué software ni
versiones tiene nuestra máquina, ya que nuestra aplicación se ejecutará en el
contenedor.

3.1.1. Un poco de historia

Salomon Hykes comenzó Docker como un proyecto interno dentro de dot-


Cloud, empresa enfocada a PaaS (plataforma como servicio). Fue liberado co-
mo código abierto en marzo de 2013. Con el lanzamiento de la versión 0.9
(en marzo de 2014) Docker dejó de utilizar LXC como entorno de ejecución
por defecto y lo reemplazó con su propia librería, libcontainer (escrita en Go),
que se encarga de hablar directamente con el kernel. Actualmente es uno de los
proyectos con más estrellas en GitHub, con miles de forks y de colaboradores.

3.1.2. Requisitos mínimos

Docker funciona de forma nativa en entornos Linux a partir de la versión 3.8


del kernel. Algunos kernels a partir de la versión 2.6.x y posteriores podrían
ejecutar Docker, pero los resultados pueden variar, por lo que oficialmente no
está soportado. Otro requisito es que solo está preparado para arquitecturas
de 64 bits (actualmente x86_64 y amd64). Para usar Docker en entornos Win-
dows o MAC, han creado una herramienta, Boot2Docker, que no es más que
una máquina virtual ligera de Linux con Docker ya instalado. Dicha imagen
la arrancamos con Virtualbox, Vmware o con la herramienta que tengamos
instalada.

Otra manera es con un instalador «todo en uno» para MAC y Windows. Este
instalador contiene un cliente para Windows, la imagen de una máquina vir-
tual Linux, Virtualbox y msys-git unix tools.
© FUOC • PID_00241997 44 Infraestructura DevOps

3.1.3. Características

Las principales características de Docker son:

• Portabilidad: el contenedor Docker podemos desplegarlo en cualquier sis-


tema, sin necesidad de volver a configurarlo o realizar las instalaciones
necesarias para que la aplicación funcione, ya que todas las dependencias
son empaquetadas con la aplicación en el contenedor.

• Ligereza: los contenedores Docker solo contienen lo que los diferencia del
sistema operativo en el que se ejecutan, no se virtualiza un SO completo.

• Autosuficiencia: un contenedor Docker no contiene todo un sistema ope-


rativo completo, solo aquellas librerías, archivos y configuraciones nece-
sarias para desplegar las funcionalidades que contenga.

3.1.4. Ventajas y desventajas

Usar contenedores Docker permite a desarrolladores y administradores de sis-


temas probar aplicaciones o servicios en un entorno seguro e igual al de pro-
ducción, lo que reduce los tiempos de pruebas y adaptaciones entre los entor-
nos de prueba y producción.

Las principales ventajas de usar contenedores Docker son:

• Las instancias se inician en pocos segundos.

• Son fácilmente replicables.

• Es fácil de automatizar y de integrar en entornos de integración continua.

• Consumen menos recursos que las máquinas virtuales tradicionales.

• Mayor rendimiento que la virtualización tradicional, ya que corre directa-


mente sobre el kernel de la máquina en la que se aloja, evitando al hyper-
visor.

• Ocupan mucho menos espacio.

• Permiten aislar las dependencias de una aplicación de las instaladas en el


host.

• Existe un gran repositorio de imágenes ya creadas sobre miles de aplica-


ciones, que además pueden modificarse libremente.
© FUOC • PID_00241997 45 Infraestructura DevOps

Por todo esto, Docker ha entrado con mucha fuerza en el mundo del desarro-
llo, ya que permite desplegar las aplicaciones en el mismo entorno que tienen
en producción o viceversa, permite desarrollarlas en el mismo entorno que
tendrán en producción.

No obstante, también tiene algunas desventajas:

• Solo puede usarse de forma nativa en entornos Unix con kernel igual o
superior a 3.8.

• Solo soporta arquitecturas de 64 bits.

• Como es relativamente nuevo, puede haber errores de código entre ver-


siones.

3.1.5. Usos y recomendaciones

El uso de Docker está recomendado:

• En entornos de integración continua, es decir, cuando el paso de desarrollo


a producción en un proyecto sea lo más a menudo posible, para así poder
detectar fallos cuanto antes.

• Para garantizar la integridad de las aplicaciones en diferentes entornos.

• Cuando necesitemos tener entornos fácilmente desplegables, portables y


desechables.

• Cuando necesitemos un entorno fácilmente escalable.

3.1.6. Arquitectura

Docker usa una arquitectura cliente-servidor. El cliente de Docker habla con el


demonio de Docker, que hace el trabajo de crear, correr y distribuir los conte-
nedores. Ambos pueden ejecutarse en el mismo sistema, o se puede conectar
un cliente a un demonio Docker remoto. El cliente Docker y el demonio se
comunican vía sockets o a través de una RESTful API (imagen página oficial).
© FUOC • PID_00241997 46 Infraestructura DevOps

Expliquemos un poco el orden de la arquitectura o funcionamiento de Docker:

• El cliente de Docker (Docker Client) es la principal interfaz de usuario pa-


ra Docker. Acepta comandos del usuario y se comunica con el demonio
Docker.

• El demonio Docker (Docker Engine) corre en una máquina anfitriona


(host). El usuario no interactúa directamente con el demonio, sino que lo
hace a través del cliente Docker.

Figura 16. Representación gráfica de la arquitectura de Docker

Fuente: <https://en.wikipedia.org/wiki/Docker_(software)>.

El demonio Docker levanta los contenedores haciendo uso de las imágenes,


que pueden estar en local o en el Docker Registry. Cada contenedor se crea a
partir de una imagen y es un entorno aislado y seguro donde se ejecuta nuestra
aplicación.
© FUOC • PID_00241997 47 Infraestructura DevOps

3.1.7. Componentes

Según la documentación oficial, Docker tiene dos componentes principales:

1)�Docker. Plataforma open source de virtualización con contenedores.

2)�Docker�Hub. Plataforma de software como servicio (SaaS, software-as-a-ser-


vice) para compartir y administrar contenedores Docker.

Pero también necesitamos conocer otros componentes y conceptos:

1)�Docker�Engine. Es el demonio que se ejecuta dentro del sistema operativo


(Linux) y que expone una API para la gestión de imágenes, contenedores, vo-
lúmenes o redes. Sus funciones principales son:

• La creación de imágenes Docker.

• La publicación de imágenes en Docker Registry.

• La descarga de imágenes desde Docker Registry.

• La ejecución de contenedores usando las imágenes.

• La gestión de contenedores en ejecución (pararlo, arrancarlo, ver logs, ver


estadísticas).

2)�Docker�Client. Se trata de cualquier software o herramienta que hace uso


de la API del demonio Docker, pero suele ser el comando docker, que es la
herramienta de línea de comandos para gestionar Docker Engine. Este cliente
puede configurarse para hablar con un Docker local o remoto, lo que permite
administrar nuestro entorno de desarrollo local como nuestros servidores de
producción.

3)�Docker�Images. Son plantillas de solo lectura que contienen el sistema ope-


rativo base (más adelante entraremos en detalle en ello) donde correrá nues-
tra aplicación, además de las dependencias y el software adicional instalado,
necesario para que la aplicación funcione correctamente. Las plantillas son
usadas por Docker Engine para crear los contenedores Docker.

4)�Docker�Registries. Los registros de Docker guardan las imágenes. Pueden


ser repositorios públicos o privados. El registro público lo provee el Hub de
Docker, que sirve tanto imágenes oficiales como las subidas por usuarios con
sus propias aplicaciones y configuraciones. Así, tenemos disponibles para to-
dos los usuarios imágenes oficiales de las principales aplicaciones (MySQL,
MongoDB, Apache, Tomcat, etc.) y no oficiales de infinidad de aplicaciones
© FUOC • PID_00241997 48 Infraestructura DevOps

y configuraciones. DockerHub ha supuesto una gran manera de distribuir las


aplicaciones. Es un proyecto open source que puede ser instalado en cualquier
servidor. Además, nos ofrecen un sistema SaaS de pago.

5)�Docker�Containers. El contenedor de Docker aloja todo lo necesario para


ejecutar un servicio o aplicación. Cada contenedor es creado de una imagen
base y es una plataforma aislada. Un contenedor es simplemente un proceso
para el sistema operativo, que se aprovecha de él para ejecutar una aplicación.
Dicha aplicación solo tiene visibilidad sobre el sistema de ficheros virtual del
contenedor.

6)�Docker�Compose. Es otro proyecto open source que permite definir aplica-


ciones multicontenedor de una manera sencilla. Es una alternativa más cómo-
da al uso del comando docker run, para trabajar con aplicaciones con varios
componentes. Es una buena herramienta para gestionar entornos de desarro-
llo y de pruebas o para procesos de integración continua.

7)�Docker�Machine. Es un proyecto open source para automatizar la creación


de máquinas virtuales con Docker instalado, en entornos Mac, Windows o Li-
nux, pudiendo administrar así un gran número de máquinas Docker. Incluye
drivers para Virtualbox, que es la opción aconsejada para instalaciones de Doc-
ker en local, en vez de instalar Docker directamente en el host. Esto simplifica
y facilita la creación o la eliminación de una instalación de Docker, facilita la
actualización de la versión de Docker o trabajar con distintas instalaciones a
la vez.

Usando el comando docker-machine podemos iniciar, inspeccionar, parar y


reiniciar un host administrado, actualizar el Docker client y el Docker daemon,
y configurar un cliente para que hable con el host anfitrión. A través de la
consola de administración podemos administrar y correr comandos Docker
directamente desde el host. Este comando docker-machine automáticamente
crea hosts, instala Docker Engine en ellos y configura los clientes Docker.

3.1.8. Diferencias con las máquinas virtuales

La principal diferencia es que una máquina virtual necesita tener virtualizado


todo el sistema operativo, mientras que el contenedor Docker aprovecha el
sistema operativo sobre el que se ejecuta, compartiendo el kernel e incluso
parte de sus bibliotecas. Para el SO anfitrión, cada contenedor no es más que
un proceso que corre sobre el kernel.

El concepto de contenedor o «virtualización ligera» no es nuevo. En Linux,


LXC (Linux Containers) es una tecnología de virtualización a nivel de sistema
operativo que utiliza dos características del kernel, cgroups (que permite aislar
y rastrear el uso de recursos) y namespaces (que permite a los grupos separar-
se, así no pueden verse unos a otros), para poder ejecutar procesos ligeros in-
dependientes en una sola máquina, aislados unos de otros, cada uno con su
© FUOC • PID_00241997 49 Infraestructura DevOps

propia configuración de red. Ejemplos de esto son las jaulas de FreeBSD, Ope-
nSolaris o Linux Vservers. Otra diferencia es el tamaño: una máquina virtual
convencional puede ocupar bastante, sin embargo, los contenedores Docker
solo contienen lo que las diferencia del sistema operativo en el que se ejecu-
tan, y ocupan una media de 150-250 Mb. En cuanto a recursos, el consumo
de procesador y memoria RAM es mucho menor al no estar todo el sistema
operativo virtualizado.

3.2. Instalación de Docker

Podemos distinguir entre la instalación para el desarrollo local y la instalación


en servidores en producción. Para los servidores en producción, la mayoría de
los proveedores de servicio (AWS, GCE, Azure, Digital Ocean...) disponen de
máquinas virtuales con versiones de Docker preinstaladas.

En nuestro caso vamos a instalar Docker en Linux bajo la distribución Ubuntu,


pero en la página oficial vienen guías de instalación para múltiples distribu-
ciones Linux (Ubuntu, Red Hat, CentOS, Fedora, Arch Linux, Gentoo, Oracle
Linux, etc.).

3.2.1. Instalación en Ubuntu 14.04

En la documentación oficial podemos ver las distribuciones de Ubuntu que


están soportadas. Aquí vamos a instalar Docker en Ubuntu Trusty 14.04 (LTS).

Primero vamos a comprobar los requisitos, que son arquitectura de 64 bits y


un kernel igual o superior a 3.10.

root@cloud-jguijarro:~# uname -a
Linux cloud-jguijarro 3.13.0-44-generic #73-Ubuntu SMP Tue Dec 16 00:22:43 UTC 2014 x86_64
x86_64 x86_64 GNU/Linux

Los pasos que deberemos seguir para la instalación son estos:

1) Actualizamos los paquetes del sistema:

root@cloud-jguijarro:~# apt-get update

2) Instalamos los paquetes para https y certificados CA:

root@cloud-jguijarro:~# apt-get install apt-transport-https ca-certificates

3) Añadimos una nueva clave GPG:

[email protected]:~# sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80


--recv-keys 58118E89F3A912897C070ADBF76221572C52609D
© FUOC • PID_00241997 50 Infraestructura DevOps

4) Abrimos /etc/apt/sources.list.d/docker.list. Si apt-get no existe, lo creamos,


y si existe, borramos su contenido. Y añadimos el repositorio:

deb https://apt.dockerproject.org/repo ubuntu-trusty main

5) Actualizamos la lista de paquetes:

root@cloud-jguijarro:~# apt-get update

6) Si tuviéramos una versión antigua, deberíamos eliminarla:

root@cloud-jguijarro:~# apt-get purge lxc-docker

7) Comprobamos el candidato para la instalación:

Figura 17. Detalle del paquete candidato para la instalación de Docker

Fuente: Jordi Guijarro.

8) La documentación oficial recomienda para nuestra versión de Ubuntu ins-


talar el paquete linux-image-extra, que permite utilizar los drivers de almace-
namiento aufs (AnotherUnionFS), que es una versión alternativa de UnionFS,
un servicio de archivos que implementa una unión para montar sistemas de
archivos Linux.

Y también recomienda instalar el paquete apparmor, que es una extensión de


seguridad que provee de una variedad de políticas de seguridad para el kernel
de Linux. Es una alternativa a SELinux.

root@cloud-jguijarro:~# apt-get install linux-image-extra-3.13.0.65-generic apparmor

9) Instalamos Docker Engine:

root@cloud-jguijarro:~# apt-get install docker-engine

10) Iniciamos el demonio Docker:

root@cloud-jguijarro:~# service docker start

11) Comprobamos que Docker está instalado correctamente:

root@cloud-jguijarro:~# docker run hello-world


Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
© FUOC • PID_00241997 51 Infraestructura DevOps

c04b14da8d14: Pull complete


Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Downloaded newer image for hello-world:latest

Hello from Docker!


This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:


1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com

For more examples and ideas, visit:


https://docs.docker.com/engine/userguide/

3.2.2. Configuración opcional

La documentación oficial nos ofrece una serie de configuraciones y procedi-


mientos para que Ubuntu trabaje mejor con Docker.

1) Crear el grupo Docker si no existe.

El demonio Docker se comunica a través del socket de Unix en vez de por un


puerto TCP.

Por defecto, el socket Unix es propiedad del usuario root, por lo que el demonio
Docker siempre corre como el usuario root.

Para evitar tener que usar sudo cuando se utilice el comando docker, se crea un
grupo llamado Docker y se añaden usuarios a él. Cuando el demonio Docker se
inicie con un usuario perteneciente al grupo Docker, lo hará con los permisos
de lectura y escritura equivalentes a root:

root@cloud-jguijarro:~# groupadd docker


root@cloud-jguijarro:~# usermod -aG docker user1

Reiniciamos la sesión del usuario ‘user1’ y comprobamos:


© FUOC • PID_00241997 52 Infraestructura DevOps

ubuntu@cloud-jguijarro:~$ docker run hello-world


Hello from Docker. This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the executable that
produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com
For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/
ubuntu@cloud-jguijarro:~$

2) Ajustar la memoria y la swap.

Dice la documentación que a veces aparece un mensaje de warning de la me-


moria swap para Cgroup. Para evitar estos mensajes, activamos la memoria de
intercambio en nuestro sistema.

Editamos el fichero /etc/default/grub y actualizamos el valor


GRUB_CMDLINE_LINUX:

Y lo dejamos:

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

Luego actualizamos GRUB y reiniciamos el sistema.

root@cloud-jguijarro:/home/ubuntu# update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.13.0-65-generic
Found initrd image: /boot/initrd.img-3.13.0-65-generic
done
© FUOC • PID_00241997 53 Infraestructura DevOps

3) Configurar las políticas del firewall.

Docker usa un bridge para gestionar las redes de contenedores, por lo que si
tenemos un firewall (UFW) que por defecto elimine el tráfico de forwarding,
habrá que configurarlo adecuadamente.

Comprobamos el estado de nuestro firewall:

root@cloud-jguijarro:/home/ubuntu# ufw status


Status: inactive

En este caso está inactivo. Si estuviera activo, los pasos que deberíamos seguir
serían los siguientes:

a) Editar el fichero /etc/default/ufw y actualizar la siguiente política a “AC-


CEPT”:

DEFAULT_FORWARD_POLICY="ACCEPT"

b) Reiniciar el firewall y permitir las conexiones entrantes en el puerto de Doc-


ker:

$ sudo ufw reload


$ sudo ufw allow 2375/tcp

4) Configurar un servidor DNS para Docker.

Sistemas como Ubuntu generalmente usan la 127.0.0.1 como servidor DNS por
defecto en el fichero /etc/resolv.conf. El NetworkManager también configura
el dnsmasq para que use el servidor local. Al iniciar contenedores en máquinas
con esta configuración, Docker nos mostrará la siguiente advertencia:

Esto ocurre porque los contenedores Docker no usan el DNS local, sino que
usan uno externo. Para evitar esta advertencia, podemos especificar un servi-
dor DNS para que lo usen los contenedores. Esto se hace editando el fiche-
ro /etc/default/docker y especificando uno o más servidores DNS públicos de
Google en la siguiente línea:

DOCKER_OPTS="--dns 8.8.8.8"

Y reiniciamos el demonio Docker.


© FUOC • PID_00241997 54 Infraestructura DevOps

Si usáramos NetworkManager con dnsmasq, tendríamos que deshabilitarlo co-


mentando en el fichero /etc/NetworkManager/NetworkManager.conf la línea:

# dns=dnsmasq

Y reiniciando NetworkManager y Docker.

5) Configurar Docker para iniciar en el arranque.

Ubuntu usa systemd como su gestor de arranque. Para configurar el demonio


de Docker para arrancar en el inicio:

$ systemctl enable docker

3.3. Administración de Docker

Ya tenemos instalado Docker en nuestra máquina anfitriona cuyo SO es Ubun-


tu 14.04 LTS. Si escribimos «docker version» en la línea de comandos, nos da
la versión del cliente y del servidor, además de la versión de la API y de Go
(lenguaje de programación en el que está escrito Docker):

root@cloud-jguijarro:#docker version
Client:
Version: 1.12.3
API version: 1.24
Go version: go1.6.3
Git commit: 6b644ec
Built: Wed Oct 26 21:44:32 2016
OS/Arch: linux/amd64
Server:
Version: 1.12.3
API version: 1.24
Go version: go1.6.3
Git commit: 6b644ec
Built: Wed Oct 26 21:44:32 2016
OS/Arch: linux/amd64

Con «docker –v» vemos solo la versión de Docker instalada:

root@cloud-jguijarro:~# docker -v
Docker version 1.12.3, build 6b644ec
© FUOC • PID_00241997 55 Infraestructura DevOps

3.3.1. Principales comandos Docker

Antes de empezar a usar Docker en la máquina que hemos preparado, vamos


a familiarizarnos con los comandos que nos ofrece. Escribiendo «docker» en
la terminal nos aparece una lista de las opciones disponibles:

• attach: para acceder a la consola de un contenedor que está corriendo.

• build: construye un contenedor a partir de un Dockerfile.

• commit: crea una nueva imagen de los cambios de un contenedor.

• cp: copia archivos o carpetas desde el sistema de ficheros de un contenedor


al host.

• create: crea un nuevo contenedor.

• daemon: crea un proceso demonio.

• diff: comprueba cambios en el sistema de ficheros de un contenedor.

• events: muestra eventos en tiempo real del estado de un contenedor.

• exec: ejecuta un comando en un contenedor activo.

• export: exporta el contenido del sistema de ficheros de un contenedor a


un archivo .tar.

• history: muestra el historial de una imagen.

• images: lista las imágenes que tenemos descargadas y disponibles.

• import: crea una nueva imagen del sistema de archivos vacío e importa el
contenido de un fichero .tar.

• info: muestra información sobre los contenedores, imágenes, versión de


Docker.

• inspect: muestra informaciones de bajo nivel del contenedor o la imagen.

• kill: detiene a un contenedor activo.

• load: carga una imagen desde un archivo .tar.

• login: para registrarse en un servidor de registro de Docker, por defecto


«https://index.docker.io/v1/».
© FUOC • PID_00241997 56 Infraestructura DevOps

• logout: se desconecta del servidor de registro de Docker.

• logs: obtiene los registros de un contenedor.

• network connect: conecta un contenedor a una red.

• network create: crea una nueva red con un nombre especificado por el
usuario.

• network disconnect: desconecta un contenedor de una red.

• network inspect: muestra información detallada de una red.

• network ls: lista todas las redes creadas por el usuario.

• network rm: elimina una o más redes.

• pause: pausa todos los procesos dentro de un contenedor.

• port: busca el puerto público, el cual está nateado, y lo hace privado.

• ps: lista los contenedores.

• pull: descarga una imagen o un repositorio del servidor de registros Docker.

• push: envía una imagen o un repositorio al servidor de registros de Docker.

• rename: renombra un contenedor existente.

• restart: reinicia un contenedor activo.

• rm: elimina uno o más contenedores.

• rmi: elimina una o más imágenes.

• run: ejecuta un comando en un nuevo contenedor.

• save: guarda una imagen en un archivo .tar.

• search: busca una imagen en el índice de Docker.

• start: inicia un contenedor detenido.

• stats: muestra el uso de los recursos de los contenedores.

• stop: detiene un contenedor.


© FUOC • PID_00241997 57 Infraestructura DevOps

• tag: etiqueta una imagen en un repositorio.

• top: busca los procesos en ejecución de un contenedor.

• unpause: reanuda un contenedor pausado.

• update: actualiza la configuración de uno o más contenedores.

• version: muestra la versión de Docker instalada.

• volume create: crea un volumen.

• volume inspect: devuelve información de bajo nivel de un volumen.

• volume ls: lista los volúmenes.

• volume rm: elimina un volumen.

• wait: bloquea hasta detener un contenedor, entonces muestra su código


de salida.

Y si queremos saber cómo funciona un comando concreto, debemos escribir


«docker COMMAND --help». Veamos, por ejemplo, cómo usar el comando
save:

ubuntu@cloud-jguijarro:~$ docker save --help


Usage: docker save [OPTIONS] IMAGE [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
--help Print usage
-o, --output Write to a file, instead of STDOUT

3.3.2. Imágenes

Las imágenes son plantillas de solo lectura que usamos como base para lanzar
un contenedor. Una imagen Docker se compone de un sistema de archivos en
capas una sobre la otra. En la base tenemos un sistema de archivos de arran-
que, bootfs (parecido al sistema de archivos de Linux), sobre el que arranca la
imagen base. Cada imagen, también conocida como repositorio, es una suce-
sión de capas. Es decir, al arrancar un contenedor lo hacemos sobre una ima-
gen, a la que llamamos imagen base. Con el contenedor corriendo, cada vez
que realizamos un cambio en el contenedor Docker añade una capa encima de
la anterior con los cambios, pero dichas modificaciones no serán persistentes,
los cambios no los hacemos en la imagen (recordemos que es de solo lectura),
por lo que deberemos guardarlos creando una nueva imagen con los cambios.
© FUOC • PID_00241997 58 Infraestructura DevOps

Docker monta un sistema de ficheros de lectura y escritura en la parte superior


de las capas. Aquí es donde los procesos de nuestro contenedor Docker serán
ejecutados (container). Cuando Docker crea un contenedor por primera vez,
la capa inicial de lectura y escritura está vacía. Cuando se producen cambios,
estos se aplican a esta capa, por ejemplo, si desea cambiar un archivo, entonces
ese archivo se copia desde la capa de solo lectura inferior a la capa de lectura y
escritura. Seguirá existiendo la versión de solo lectura del archivo, pero ahora
está oculto debajo de la copia.

3.3.3. Trabajando con imágenes

Como hemos explicado anteriormente, los contenedores se construyen a par-


tir de imágenes, que se pueden encontrar en local, en el Docker Hub o en re-
positorios privados. Más adelante veremos Docker Hub con un poco más de
detalle.

Para comprobar las imágenes que tenemos en local, hemos de ejecutar:

docker images

Figura 18. Detalle de las imágenes de Docker

Fuente: Jordi Guijarro.

Ahora mismo solo tenemos la imagen que se descargó cuando comprobamos


que se había instalado correctamente Docker. Podemos buscar la imagen que
queremos con el comando search. Por ejemplo, si queremos saber qué imáge-
nes hay disponibles de Ubuntu.

Vemos una lista con las imágenes disponibles.


© FUOC • PID_00241997 59 Infraestructura DevOps

Figura 19. Detalle de la búsqueda de la imagen de wordpress

Fuente: Jordi Guijarro.

Para descargar una imagen, debemos hacerlo con el comando pull (también
podemos hacerlo con el comando run, como veremos más adelante, pero esta
es la forma correcta).

Sintaxis:

docker pull [options] NAME[:TAG] |


[REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]

Donde las opciones disponibles son:

• -a, --all-tags: descarga todas imágenes etiquetadas en el repositorio.


• --disable-content-trust=true: se salta la verificación de la imagen.
• --help: muestra ayuda sobre el comando.

Si no especificamos el tag, se descargará la última versión. Vamos a probarlo.

Figura 20. Detalle de la descarga de una imagen Docker

Fuente: Jordi Guijarro.

Si nos fijamos en la descarga, vemos 5 líneas que ponen «pull complete». Esto
es que la imagen está formada por 5 capas o layers. Estas capas pueden ser re-
utilizadas por otras imágenes, que evitan así el tener que volver a descargarlas,
por ejemplo si descargamos otra imagen de Ubuntu. En la descarga también
vemos una línea que pone Digest. Este código sirve si queremos asegurarnos
© FUOC • PID_00241997 60 Infraestructura DevOps

de usar una versión de la imagen en concreto, y no la última por ejemplo,


como sucede si usamos el nombre y el tag. Comprobamos las imágenes dispo-
nibles ahora.

Figura 21. Detalle de las imágenes de Docker

Fuente: Jordi Guijarro.

Para ver los detalles de una imagen, ejecutamos el siguiente comando:

Figura 22. Consulta de los detalles de una imagen de Docker

Fuente: Jordi Guijarro.

Una vez que tenemos disponible una imagen, podemos ejecutar cualquier con-
tenedor.

3.3.4. Ejecución de contenedores

Comando run

Podemos crear un contenedor con el comando run.

Sintaxis:

docker run [OPTIONS] IMAGE [COMMAND] [ARG....]

Entre las opciones se encuentran:

• -a, --attach: para conectarnos a un contenedor que está corriendo.


© FUOC • PID_00241997 61 Infraestructura DevOps

• -d, --detach: corre un contenedor en segundo plano.


• -i, --interactive: habilita el modo interactivo.
• --name: le pone nombre a un contenedor.

Ahora vamos a ejecutar un contenedor sobre la imagen de ubuntu que tene-


mos descargada.

ubuntu@cloud-jguijarro:~$ docker run ubuntu echo hello world


hello world

El comando run primero crea una capa del contenedor sobre la que se puede
escribir y, a continuación, ejecuta el comando especificado. Con este comando
hemos ejecutado un contenedor, sobre la imagen Ubuntu, que ha ejecutado el
comando echo. Cuando ha terminado de ejecutar el comando que le hemos
pedido se ha detenido. Los contenedores están diseñados para correr un único
servicio, aunque podemos correr más si hiciera falta. Cuando ejecutamos un
contenedor con run, debemos especificarle un comando que ejecutar en él, y
dicho contenedor solo se ejecuta durante el tiempo que dura el comando que
especifiquemos, funciona como un proceso.

Algo que hemos de tener en cuenta es que si la imagen que estamos poniendo
en el comando run no la tuviéramos en local, Docker primero la descargaría
y la guardaría en local y luego seguiría con la construcción capa por capa del
contenedor. Vamos a ver los contenedores que tenemos en nuestro host con
el comando ps.

Figura 23. Consulta de los contenedores Docker activos en nuestro host

Fuente: Jordi Guijarro.

No nos aparece ningún contenedor, y esto es porque el contenedor ya no está


activo. Para ver todos los contenedores (activos e inactivos) usamos el flag -a.

Figura 24. Consulta de todos los contenedores Docker en nuestro host

Fuente: Jordi Guijarro.

Vemos el ID del contenedor, la imagen del contenedor, el comando que se ha


ejecutado, cuándo se creó, el estado, el mapeo de puertos y el nombre. Este ID
es abreviado; para verlo completo, tenemos que ejecutar:
© FUOC • PID_00241997 62 Infraestructura DevOps

Figura 25. Consulta de todos los detalles de los contenedores Docker en nuestro host

Fuente: Jordi Guijarro.

También vemos que Docker genera automáticamente un nombre al azar por


cada contenedor que creamos. Si queremos especificar un nombre en particu-
lar, podemos hacerlo con el parámetro --name.

ubuntu@cloud-jguijarro:~$ docker run --name micontainer ubuntu echo prueba nombre

Con «docker ps –a» veremos el contenedor con el nombre que hemos puesto.

Modo interactivo

Como hemos visto, cuando creamos un contenedor con run, debemos espe-
cificar un comando que se va a ejecutar, y cuando se acabe su ejecución el
contenedor se detendrá.

Básicamente, el contenedor se crea para ejecutar dicho comando.

Tenemos la opción de ejecutar un contenedor en modo interactivo con los


flags:

• -t: ejecuta una terminal.


• -i: nos comunicamos con el contenedor en modo interactivo.

Como vemos en la imagen, estamos conectados al contenedor. Si abrimos otra


terminal y ejecutamos un docker ps, vemos que tenemos el contenedor co-
rriendo.

Pero si nos salimos de la shell del contenedor, este se detendrá:

ubuntu@cloud-jguijarro:~$ docker run -it ubuntu /bin/bash

O conectarnos a él vía otro terminal:

ubuntu@cloud-jguijarro:~$ docker attach tiny_turing


root@dfb581bd638c:/#

O ejecutar con exec comandos dentro de un contenedor activo, por ejemplo


una shell:

ubuntu@cloud-jguijarro:~$ docker exec -it dfb /bin/sh


# exit
ubuntu@cloud-jguijarro:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
© FUOC • PID_00241997 63 Infraestructura DevOps

STATUS PORTS NAMES


dfb581bd638c ubuntu "/bin/bash" 3 hours ago
Up 19 seconds tiny_turing

Vemos que cuando salimos el contenedor no se detiene. Podemos abrir


otra terminal y parar el contenedor con su identificador «docket stop
635cacb8d75c».

Pero no resulta muy funcional un contenedor que se pare cuando terminemos


de actuar sobre él. Nos interesa que continúe ejecutándose con el servicio que
queramos. Para ello, está el modo detached, que veremos un poco más ade-
lante.

3.3.5. Creando imágenes Docker

Las imágenes, como hemos visto, son plantillas de solo lectura, que usamos de
base para lanzar contenedores. Por tanto, lo que hagamos en el contenedor so-
lo persiste en ese contenedor, las modificaciones no las hacemos en la imagen.

Si queremos que dichos cambios sean permanentes, debemos crear una nueva
imagen con el contenedor personalizado. Veamos las imágenes que tenemos
disponibles:

ubuntu@cloud-jguijarro:~$ docker images

Vamos a realizar un ejemplo. Tenemos la imagen base de ubuntu. Lanzamos


un contenedor con esa imagen base en el modo interactivo que vimos ante-
riormente e instalamos una serie de paquetes:

root@cloud-jguijarro:~# docker run -it --name micontainer ubuntu /bin/bash


root@635cacb8d77c:/# apt-get update
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
Get:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [94.5 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial-security InRelease [94.5 kB]
Get:4 http://archive.ubuntu.com/ubuntu xenial/main Sources [1103 kB]
Get:5 http://archive.ubuntu.com/ubuntu xenial/restricted Sources [5179 B]
...
...

Instalamos por ejemplo git.

root@635cacb8d77c:/# apt-get install git


© FUOC • PID_00241997 64 Infraestructura DevOps

Ahora vamos a guardar los cambios realizados en la imagen. Tenemos que salir
del contenedor y ejecutar el comando «commit». Cuando salimos de un con-
tenedor interactivo este se detiene. Lo vemos con docker ps –a. Ahora mismo
este contenedor está formado por la capa con la imagen base y la capa en la
que hemos instalado git.

Para poder utilizar esta imagen con los cambios, hemos de crear una nueva
imagen, con el comando:

docker commit -m "Conf realizada" -a "jguijarro" 635cacb8d77c


git/ubuntu:v1

• Con commit creamos una nueva imagen en nuestro repositorio local.


• -m: añadimos un comentario.
• -a: autor de la imagen.
• 635cacb8d77c: identificador del contenedor.
• git/ubuntu:v1: el nombre que le damos a la imagen.

Al crearla nos devuelve un identificador único de imagen. La podemos ver en


la lista de imágenes mediante el comando «docker images».

Figura 26. Consulta de las imágenes Docker disponibles en nuestro host

Fuente: Jordi Guijarro.

A partir de aquí podemos crear un contenedor con esta nueva imagen como
base y ya tendrá instalado git. Lo comprobamos:

Figura 27. Detalle del nuevo contenedor con git instalado

Fuente: Jordi Guijarro.

3.3.6. Detached o Background

Nos permite ejecutar un contenedor en segundo plano y poder correr coman-


dos sobre él en cualquier momento mientras esté en ejecución. Lo hacemos
con el flag -d. Se dice que es un contenedor demonizado y se ejecutará indefi-
nidamente. Vamos a ver un ejemplo. Primero creamos un contenedor basado
en la imagen ubuntu que hemos descargado en modo interactivo:
© FUOC • PID_00241997 65 Infraestructura DevOps

root@cloud-jguijarro:~# docker run -it --name 2plano ubuntu /bin/bash


root@fc6e05dedc96:/#

Y le instalamos un servidor web:

root@cloud-jguijarro:~# docker run -it --name apache ubuntu /bin/bash


root@2ca26b7f9d5c:/# apt-get install apache2

Ahora creamos una nueva imagen del contenedor con Apache instalado:

root@cloud-jguijarro:~# docker commit -m "Instalado Apache" -a "Jguijarro"


2ca26b7f9d5c apache/ubuntu:v1
sha256:defab75e4eb991475e943513f52002b76f5eaa65b5d69c998228c469e99093ab

Ahora podemos arrancar un contenedor en segundo plano:

root@cloud-jguijarro:~# docker run -d --name server apache/ubuntu:v1


/usr/sbin/apache2ctl -DFOREGROUND
9bb15ff58f5da24e2513e69f0c4301577eb10dd07c173729d472a94b8b20234d

Vamos a hacer que el servicio Apache no se detenga con -D y que el contenedor


se ejecute en segundo plano con -d.

Comprobamos nuestros contenedores:

root@cloud-jguijarro:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
9bb15ff58f5d apache/ubuntu:v1 "/usr/sbin/apache2ctl" 24
seconds ago Up 24 seconds server

Podemos ver los procesos que se están ejecutando en un contenedor con «top»:

root@cloud-jguijarro:~# docker top web_server


UID PID PPID C
STIME TTY TIME CMD
root 10543 10529 0
15:19 ? 00:00:00 /bin/sh
/usr/sbin/apache2ctl -DFOREGROUND
root 10564 10543 0
15:19 ? 00:00:00
/usr/sbin/apache2 -DFOREGROUND
www-data 10565 10564 0
15:19 ? 00:00:00
/usr/sbin/apache2 -DFOREGROUND
www-data 10566 10564 0
15:19 ? 00:00:00
© FUOC • PID_00241997 66 Infraestructura DevOps

/usr/sbin/apache2 -DFOREGROUND

Una vez que hemos creado el contenedor y lo tenemos corriendo en segundo


plano, podemos conectarnos a él mediante el comando exec, que ejecuta un
proceso en el contenedor:

root@cloud-jguijarro:~# docker exec -it server /bin/bash


root@5659f2d7e356:/#

Vemos que, al salirnos del contenedor, este no se detiene:

root@5659f2d7e356:/# exit
exit
root@docker:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
5659f2d7e356 apache/ubuntu:v1 "/usr/sbin/apache2ctl" 4
minutes ago Up 4 minutes server

3.3.7. Mapeo de puertos

Para que la aplicación que nos está sirviendo nuestro contenedor, por ejemplo
el servidor web instalado en el contenedor anterior, es necesario mapear los
puertos. Es decir, al crear el contenedor, este no está disponible al exterior. Para
que lo esté, tenemos que redireccionar el puerto 22 del contenedor a uno de
nuestra máquina. Usamos para ello el flag -p.

Vamos a ejecutar un contenedor basado en la imagen apache, en segundo


plano y con la redirección de puertos activa. Podemos hacer la redirección de
puertos con las opciones:

• -p: especificamos a qué puerto queremos la redirección.

• -P: le dice a Docker que si expone algún tipo de puerto haga el fordwarding
a un puerto aleatorio.

Este se una cuando usamos un Dockerfile.

Lanzamos el contenedor:

root@cloud-jguijarro:~# docker run -d -p 8000:80 --name apache_2


apache/ubuntu:v1 /usr/sbin/apache2ctl -D FOREGROUND

Comprobamos su estado:

root@cloud-jguijarro:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED
© FUOC • PID_00241997 67 Infraestructura DevOps

STATUS PORTS NAMES


c1fbe4ea1b9e apache/ubuntu:v1 "/usr/sbin/apache2ctl" 9
seconds ago Up 8 seconds apache_3
1d47feeb39ec apache/ubuntu:v1 "/usr/sbin/apache2ctl" 48
seconds ago Up 47 seconds 0.0.0.0:8000->80/tcp apache_2

Vemos que nos indica la redirección. Si accedemos desde nuestra máquina


local, veremos el servidor web en el puerto 8000 del anfitrión.

3.3.8. Docker Hub

Aquí vamos a hablar un poco de la plataforma Docker Hub, que sirve como
repositorio de imágenes oficiales y de terceros.

Las características de Docker Hub son:

• Repositorios de imágenes: encuentra, administra, sube y descarga imáge-


nes oficiales y de la comunidad.

• Imágenes automáticas: crea nuevas imágenes cuando haces un cambio en


la fuente de Github o BitBucket.

• Webhooks: crea automáticamente imágenes al hacer un push a un reposi-


torio.

En Docker Hub podemos tener nuestro propio repositorio de imágenes, públi-


co o privado.

Ya hemos visto cómo usar los repositorios desde la línea de comandos, ahora
lo vemos desde el sitio web.

Figura 28. Formulario de inscripción al Hub de Docker

Fuente: Jordi Guijarro.

Creamos una cuenta y al acceder vemos que podemos crear nuestro propio
repositorio, organización o buscar en los repositorios.
© FUOC • PID_00241997 68 Infraestructura DevOps

Al explorar vemos primero los repositorios oficiales. Si entramos en el reposi-


torio oficial de nginx por ejemplo, vemos las versiones disponibles para des-
cargar y el comando.

Figura 29. Detalle de las imágenes de nginx para Docker

Fuente: Jordi Guijarro.

3.3.9. Links

Para que dos contenedores colaboren entre ellos, podemos abrir puertos y que
se comuniquen por ahí, pero Docker nos ofrece la posibilidad de crear links
entre contenedores.

Primero creamos un contenedor:

root@cloud-jguijarro:~# docker run -d --name links01 apache/ubuntu:v1


/usr/sbin/apache2ctl -D FOREGROUND
bcaf034f661cfa05f4f520f42914620b06b8137a9c62a9117997cc69bd952a34

No hemos mapeado ningún puerto, el servidor no es accesible desde fuera.

Ahora creamos otro con la opción --link para que Docker cree un túnel entre
los dos contenedores:

root@cloud-jguijarro:~# docker run -d --name links02 --link links01


apache/ubuntu:v1 /usr/sbin/apache2ctl -D FOREGROUND
848a28b767733f7d791a4e3de0ae88423d1f71213c2dde4eeb6f9feec0fc8d4c

Comprobamos los contenedores activos con el comando «docker ps». Este tú-
nel es unidireccional y solo podremos acceder a él desde el que se ha ejecutado
con --link al otro:

root@cloud-jguijarro:~# docker exec links02 env


PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=848a28b76773
LINKS01_NAME=/links02/links01
© FUOC • PID_00241997 69 Infraestructura DevOps

HOME=/root

Vemos que aparecen variables del contenedor links01. Podemos modificar des-
de links02 las variables de entorno del otro contenedor. Docker internamente
gestiona las Ips de los contenedores, añadiéndolas al fichero /etc/hosts de los
contenedores.

root@cloud-jguijarro:~# docker exec links02 cat /etc/hosts


127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.6 links01 bcaf034f661c
172.17.0.7 848a28b76773

3.3.10. Volúmenes

Podemos montar volúmenes de datos en nuestros contenedores. Con el flag -


v podemos montar un directorio dentro de nuestro contenedor. Así, podemos
incorporar datos que estarían disponibles para nuestro contenedor. Además,
seguirá apareciendo después de un reinicio del contenedor, serán persistentes.
También podemos compartir volúmenes de datos entre contenedores. Si di-
chos volúmenes están anclados al sistema operativo anfitrión, no serán elimi-
nados por Docker cuando desaparezca el contenedor.

Vamos a crear un contenedor al que le pasemos un volumen.

Figura 30

Fuente: Jordi Guijarro.

Cuando listamos vemos en la carpeta que encontramos montado en nuestro


contenedor el directorio «scratch». Esto es muy útil para pasarle ficheros a los
contenedores y que los datos que nos interesen en ellos sean persistentes.

También podemos crear un contenedor que monte un volumen de otro con


la opción –volume-from:

root@cloud-jguijarro:/volumen01# docker run -d -p 8085:80 --name scratch


--volumes-from ejemplo_volumen git/ubuntu:v1 /sbin/apache2 -D
FOREGROUND
cf51f79ccb03f9042362d9ff962aba3ebd4c5a35ace3514600d42a37a5976036
© FUOC • PID_00241997 70 Infraestructura DevOps

3.3.11. Variables de entorno

Podemos modificar las variables de entorno de un contenedor con el flag -e


(--env).

También podemos pasarlas desde un fichero externo con ---env-file.

Y podemos ver las variables con:

root@cloud-jguijarro:/volumen01# docker exec a60 env


PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=a6066a7a2383
HOME=/root

3.3.12. Configuración de red

Por defecto, los contenedores tienen las conexiones de redes habilitadas. Po-
demos deshabilitarlas pasando la opción --net none.

Con el comando docker run podemos especificar tres configuraciones referen-


tes a la red:

a) -dns: para configurar un servidor dns en el contenedor:

# docker run -i -t -dns="8.8.8.8" ubuntu /bin/bash

b) -net: crear una red y conectar el servidor a ella:

# docker network create -d overlay mi-red


# docker run -net=mi-red -i -t -d ubuntu

c) -add-host: agregando una entrada en el fichero /etc/hosts del contenedor:

# docker run -i -t -add-host apache:10.0.0.10 ubuntu /bin/bash

3.3.13. Eliminar contenedores

Para eliminar un contenedor podemos hacerlo por el nombre o por el ID. Real-
mente solo necesitamos los tres primeros dígitos del ID. Para poder eliminarlo
debe estar parado. Si no lo estuviera, tendríamos que pararlo con «stop».

Utilizamos el comando rm. Si queremos ahorrarnos el paso de pararlo, usamos


-f.
© FUOC • PID_00241997 71 Infraestructura DevOps

3.3.14. Dockerfile

Un Dockerfile es un archivo legible por el demonio Docker, que contiene una


serie de instrucciones para automatizar el proceso de creación de un contene-
dor.

Construir el contenedor

El comando docker build irá siguiendo las instrucciones del Dockerfile y ar-
mando la imagen. El Dockerfile puede encontrarse en el directorio en el que
estemos o en un repositorio.

El demonio de Docker es el que se encarga de construir la imagen siguiendo


las instrucciones línea por línea y va lanzando los resultados por pantalla. Ca-
da vez que ejecuta una nueva instrucción se hace en una nueva imagen, son
imágenes intermedias, hasta que muestra el ID de la imagen resultante de eje-
cutar todas las instrucciones. El daemon irá haciendo una limpieza automática
de las imágenes intermedias.

Estas imágenes intermedias se guardan en la caché de Docker. Y ¿para qué


sirve que Docker cree una caché de imágenes intermedias? Pues para que, si
por alguna razón la creación de la imagen falla (por un comando erróneo por
ejemplo), cuando lo corregimos y volvemos a construir la imagen a partir del
dockerfile, el demonio no tiene que iniciar todo el proceso, sino que usará las
imágenes intermedias y continuará en el punto donde falló.

Dockerfile comandos

1)�FROM

Indicamos una imagen base para construir el contenedor y opcionalmente un


tag (si no la indicamos, docker asumirá «latest» por defecto, es decir, buscará
la última versión).

Lo que hace docker al leer esto es buscar en la máquina local una imagen que
se llama; si no la encuentra, la descargará de los repositorios.

Sintaxis:

FROM <imagen>
FROM <imagen>:<tag>

2)�MAINTAINER

Es información del creador y mantenedor de la imagen, usuario, correo, etc.


© FUOC • PID_00241997 72 Infraestructura DevOps

Sintaxis:

MAINTAINER <nombre> <correo> <cualquier_info>

3)�RUN

Ejecuta directamente comandos dentro del contenedor y luego aplica/persiste


los cambios creando una nueva capa encima de la anterior con los cambios
producidos de la ejecución del comando, y se hace un commit de los resulta-
dos. Posteriormente, sigue con la siguiente instrucción.

Sintaxis:

RUN <comando> -> modo shell, /bin/sh -c RUN ["ejecutable","parámetro1","parámetro2"] -> modo
ejecución, que permite correr comandos en imágenes base que no tengan /bin/sh o hacer uso
de otra shell.

4)�ENV

Establece variables de entorno del contenedor. Dichas variables se pasarán a


todas las instrucciones RUN que se ejecuten posteriores a la declaración de las
variables. Podemos especificar varias variables de entorno en una sola instruc-
ción ENV.

Sintaxis:

ENV <key> <value> <key> <value>


ENV <key>=<value> <key>=<value>

Si queremos sustituir una variable aunque esté definida en el Dockerfile, al


ejecutar un contenedor podemos especificarla y tomará dicho valor, tenga el
que tenga en el Dockerfile.

docker run -env <key>=<valor>

También podemos pasar variables de entorno con el comando «docker run»


utilizando el parámetro -e para especificar que dichas variables solo se utiliza-
rán en tiempo de ejecución.

Podemos usar estas variables en otras instrucciones llamándolas con


$nombre_var o $ {nombre_var}. Por ejemplo:

ENV DESTINO_DIR /opt/app


WORKDIR $DESTINO_DIR

5)�ADD
© FUOC • PID_00241997 73 Infraestructura DevOps

Esta instrucción copia los archivos o directorios de una ubicación especifica-


da en <fuente> y los agrega al sistema de archivos del contenedor en la ruta
especificada en <destino>.

En fuente podemos poner una URL, Docker se encargará de descargar el archi-


vo y copiarlo en el destino. Si el archivo origen está comprimido, lo descom-
prime en el destino como si usáramos «tar –x».

Sintaxis:

ADD <fuente>..<destino>
ADD ["fuente",..."destino"]

El parámetro <fuente> acepta caracteres comodín tipo ?,*, etc. Una de las co-
sas que debemos tener en cuenta (entre otras → https://docs.docker.com/engi-
ne/reference/builder/#add) es que el <origen> debe estar donde esté el Docker-
file, no se pueden añadir archivos desde fuera del directorio de construcción.

Si el destino no existe, Docker creará la ruta completa incluyendo cualquier


subdirectorio. Los nuevos archivos y directorios se crearán con los permisos
0755 y un UID y GID de 0.

También hemos de tener en cuenta que si los archivos o directorios agregados


por una instrucción ADD cambian, entonces se invalida la caché para las si-
guientes instrucciones del Dockerfile.

6)�COPY

Es igual que ADD, solo que NO admite URL remotas y archivos comprimidos
como lo hace ADD.

7)�WORKDIR

Permite especificar en qué directorio se va a ejecutar una instrucción RUN,


CMD o ENTRYPOINT.

Puede ser usada varias veces dentro de un Dockerfile. Si se da una ruta relativa,
esta será la ruta relativa de la instrucción WORKDIR anterior.

Podemos usar variables de entorno previamente configuradas, por ejemplo:

ENV rutadir /ruta


WORKDIR $rutadir

8)�USER
© FUOC • PID_00241997 74 Infraestructura DevOps

Sirve para configurar el nombre de usuario que utilizar cuando se lanza un


contenedor y para la ejecución de cualquier instrucción RUN, CMD o ENTRY-
POINT posteriores.

9)�VOLUME

Crea un punto de montaje con un nombre especificado que permite compartir


dicho punto de montaje con otros contenedores o con la máquina anfitriona.
Es un directorio dentro de uno o más contenedores que no utiliza el sistema
de archivos del contenedor, aunque se integra en él para proporcionar varias
funcionalidades útiles con el fin de que los datos sean persistentes y se puedan
compartir con facilidad.

Esto se hace para que cuando usemos el contenedor podamos tener acceso
externo a un determinado directorio del contenedor.

Las características de estos volúmenes son:

• Los volúmenes pueden ser compartidos y reutilizados entre los contene-


dores.

• Un contenedor no tiene que estar en ejecución para compartir sus volú-


menes.

• Los cambios en un volumen se hacen directamente.

• Los cambios en un volumen no se incluirán al actualizar una imagen.

• Los volúmenes persisten incluso cuando dejan de usarlos los contenedo-


res. Esto permite añadir datos, BBDD o cualquier otro contenido sin com-
prometer la imagen. El valor puede ser pasado en formato JSON o como
un argumento, y se pueden especificar varios volúmenes.

VOLUME ["/var/tmp"]
VOLUME /var/tmp

10)�LABEL

LABEL añade metadatos a una imagen Docker. Se escribe en el formato


etiqueta=“valor”. Se pueden añadir varios metadatos separados por un espacio
en blanco.

LABEL version="1.0"
LABEL localizacion="Barbate" tipo="BBDD"
© FUOC • PID_00241997 75 Infraestructura DevOps

Podemos inspeccionar las etiquetas en una imagen usando el comando docker


inspect. $ docker inspect <nombre_imagen>/<tag>.

11)�STOPSIGNAL

Le indica al sistema una señal que será enviada al contenedor para salir. Puede
ser un número válido permitido por el kernel (por ejemplo, 9) o un nombre de
señal en el formato SIGNAME (por ejemplo, SIGKILL).

12)�ARG

Define una variable que podemos pasar cuando estemos construyen-


do la imagen con el comando docker build, usando el flag --build-arg
<varname>=<value>. Si especificamos un argumento en la construcción que
no está definido en el Dockerfile, nos dará un error.

El autor del Dockerfile puede definir una o más variables. Y también puede
definir un valor por defecto para una variable, que se usará si en la construc-
ción no se especifica otro.

ARG user1
ARG user1=someuser ARG user2

Se deben usar estas variables de la siguiente manera:

docker build -build-arg <variable>=<valor> ....

Docker tiene un conjunto de variables predefinidas que pueden usarse en la


construcción de la imagen sin que estén declaradas en el Dockerfile:

HTTP_PROXY http_proxy
HTTPS_PROXY https_proxy
FTP_PROXY ftp_proxy
NO_PROXY no_proxy

13)�ONBUILD

Añade triggers a las imágenes. Un disparador se utiliza cuando se usa una ima-
gen como base de otra imagen. El disparador inserta una nueva instrucción
en el proceso de construcción como si se especificara inmediatamente después
de la instrucción FROM.

Por ejemplo, tenemos un Dockerfile con la instrucción ONBUILD, y creamos


una imagen a partir de este Dockerfile, por ejemplo, IMAGEN_padre. Si escri-
bimos un nuevo Dockerfile, y la sentencia FROM apunta a IMAGEN_PADRE,
© FUOC • PID_00241997 76 Infraestructura DevOps

cuando construyamos una imagen a partir de este Dockerfile, IMAGEN_HIJO,


veremos en la creación que se ejecuta el ONBUILD que teníamos en el primer
Dockerfile.

Los disparadores ONBUILD se ejecutan en el orden especificado en la imagen


padre y solo se heredan una vez; si construimos otra imagen a partir de la
IMAGEN_HIJO, los disparadores no serán ejecutados en la construcción de la
IMAGEN_NIETO.

Hay algunas instrucciones que no se pueden utilizar en ONBUILD, como son


FROM, MAINTAINER y ONBUILD, para evitar recursividad.

Un ejemplo de uso:

FROM Ubuntu:14.04
MAINTAINER mcgomez
RUN apt-get update && apt-get install -y apache2
ONBUILD ADD ./var/www/
EXPOSE 80
CMD ["D","FOREGROUND"]

14)�EXPOSE

Se utiliza para asociar puertos, permitiéndonos exponer un contenedor al ex-


terior (internet, host, etc.). Esta instrucción le especifica a Docker que el con-
tenedor escucha en los puertos especificados. Pero EXPOSE no hace que los
puertos puedan ser accedidos desde el host, para ello debemos mapear los puer-
tos usando la opción -p en docker run.

Por ejemplo:

EXPOSE 80 443
docker run centos:centos7 -p 8080:80

15)�CMD

Esta instrucción es similar al comando RUN pero con la diferencia de que se


ejecuta cuando instanciamos o arrancamos el contenedor, no en la construc-
ción de la imagen.

Solo puede existir una única instrucción CMD por cada Dockerfile y puede
ser útil para ejecutar servicios que ya estén instalados o para correr archivos
ejecutables especificando su ubicación.

16)�ENTRYPOINT
© FUOC • PID_00241997 77 Infraestructura DevOps

Cualquier argumento que pasemos en la línea de comandos mediante doc-


ker run será anexado después de todos los elementos especificados mediante
la instrucción ENTRYPOINT, y anulará cualquier elemento especificado con
CMD. Esto permite pasar cualquier argumento al punto de entrada.

Sintaxis:

ENTRYPOINT ["ejecutable","parámetro1","parámetro2"] -> forma de ejecución ENTRYPOINT comando


parámetro1 parámetro 2 -> forma shell

ENTRYPOINT nos permite indicar qué comando se va a ejecutar al iniciar el


contenedor, pero en este caso el usuario no puede indicar otro comando al
iniciar el contenedor. Si usamos esta opción, es porque no esperamos que el
usuario ejecute otro comando que el especificado.

17)�ARCHIVO�DOCKERIGNORE

Es recomendable colocar cada Dockerfile en un directorio limpio, en el que


solo agreguemos los ficheros que sean necesarios. Pero es posible que tengamos
algún archivo en dicho directorio que cumpla alguna función pero que no
queremos que sea agregado a la imagen. Para esto usamos .dockerignore, para
que docker build excluya esos archivos durante la creación de la imagen.

Un ejemplo de .dockerignore:

*/prueba*
*/*/prueba
prueba?

Ejemplo de Dockerfile

Vamos a lanzar un contenedor haciendo uso del siguiente Dockerfile, que he-
mos colocado en una carpeta llamada /wordpress.

FROM debian #FROM nos indica la imagen base a partir de la cual crearemos la imagen con
"wordpress" que construirá el Dockerfile.
MAINTAINER UOC <[email protected]>
ENV HOME /root #ENV HOME: Establecerá nuestro directorio "HOME" donde relizaremos los comandos "RUN".
RUN apt-get update
RUN apt-get install -y nano wget curl unzip lynx apache2 php5 libapache2- mod-php5 php5-mysql
RUN echo "mysql-server mysql-server/root_password password root" | debconf-set-selections
RUN echo "mysql-server mysql-server/root_password_again password root" | debconf-set-selections
RUN apt-get install -y mysql-server
ADD https://es.wordpress.org/wordpress-4.2.2-es_ES.zip /var/www/wordpress.zip #ADD nos permite
añadir un archivo al contenedor, en este caso nos estamos bajando Wordpress
ENV HOME /var/www/html/
RUN rm /var/www/html/index.html
© FUOC • PID_00241997 78 Infraestructura DevOps

RUN unzip /var/www/wordpress.zip -d /var/www/


RUN cp -r /var/www/wordpress/* /var/www/html/
RUN chown -R www-data:www-data /var/www/html/
RUN rm /var/www/wordpress.zip
ADD /script.sh /script.sh
RUN ./script.sh
#ADD nos añadirá en este caso la configuración de la base de datos que una vez realizada el
despliegue tendremos que poner para su utilización.
EXPOSE 80 #EXPOSE indica los puertos TCP/IP por los que se pueden acceder a los servicios del
contenedor 80 "HTTP".
CMD ["/bin/bash"] #CMD nos establece el comando del proceso de inicio que se usará.
ENTRYPOINT ["./script.sh"]

También colocamos en la misma carpeta el script donde vamos a establecer


una comunicación con la base de datos y nos va a crear una base de datos
"wordpress", usuario "wordpress" y contraseña "wordpress":

#!/bin/bash
#Iniciamos el servicio mysql
/etc/init.d/mysql start
#Guardamos en variables los datos de la base de datos
DB_ROOT="root" DB_ROOT_PASS="root" DB_NAME="wordpress" DB_USER="wordpress" DB_PASS="wordpress"
#Nos conectamos a la BBDD como root y creamos el usuario sql
mysql -u ${DB_ROOT} -p${DB_ROOT_PASS} -e "CREATE USER '${DB_USER}';"
#Creamos la base de datos
mysql -u ${DB_ROOT} -p${DB_ROOT_PASS} -e "CREATE DATABASE ${DB_NAME};"
#Le damos permisos al usuario sobre la base de datos y le ponemos contraseña
mysql -u ${DB_ROOT} -p${DB_ROOT_PASS} -e "GRANT ALL ON ${DB_NAME}.* TO $ {DB_USER} $

#Reiniciamos los servicios


/etc/init.d/apache2 start
/bin/bash

Nos situamos en la carpeta donde tenemos el Dockerfile y creamos la imagen


a partir de nuestro Dockerfile con el siguiente comando:

root@cloud-jguijarro:~# docker build -f dockerfile -t wordpress.

Ya tenemos creada nuestra imagen. Podemos listarla como una más:

root@cloud-jguijarro:~#docker images

El siguiente paso es correr la imagen en nuestro puerto 80, para lo que usamos
el siguiente comando:

root@cloud-jguijarro:~#docker run -d -p80:80 -i myblog


© FUOC • PID_00241997 79 Infraestructura DevOps

Limitación de recursos

Podemos limitar los recursos usados por los contenedores.

Algunos ejemplos de creación de contenedores con limitación de recursos se-


rían estos:

root@cloud-jguijarro:/# docker run -i -t -m 500m ubuntu /bin/bash root@fbc27c5774aa:/#

Hemos creado un contenedor con un límite de memoria de 500 megas.

Inicio automático

Para iniciar un contenedor y hacerlo disponible desde el inicio del sistema


anfitrión, usamos --restart, que admite tres valores:

• -no: valor predeterminado, no estará disponible al reiniciar el sistema an-


fitrión.

• -on-failure[max-retries]: reinicia si ha ocurrido un fallo y podemos indi-


carle los intentos.

• -always: reinicia el contenedor siempre.

Ejemplo:

root@cloud-jguijarro:/# docker run -i -t --restart=always ubuntu /bin/bash


© FUOC • PID_00241997 80 Infraestructura DevOps

4. Infraestructura PaaS pública: Cloud9, Heroku

Hasta el momento hemos visto entornos de aplicaciones completamente ad- Nota


ministrados en nuestros servidores, pero vivimos en una época en la que cada
En este apartado hablaremos
vez aparecen más herramientas de desarrollo en la nube y dotan a los desarro- de dos de las soluciones PaaS
lladores de la capacidad de utilizar infraestructuras PaaS (platform-as-a-service), más populares para desarro-
lladores basados en el cloud:
donde el entorno viene dado y solo tendremos que centrarnos en el desarrollo Cloud9 y Heroku.

de la aplicación.

La filosofía del desarrollo basado en infraestructuras PaaS reduce la compleji-


dad del modelo, ya que la gestión y el mantenimiento, así como la escalabili-
dad de la infraestructura serán delegadas a terceros. En ningún caso esto querrá
decir que como desarrolladores no hayamos de tener en cuenta la infraestruc-
tura, pero permitirá que centremos nuestros esfuerzos en optimizar nuestras
aplicaciones olvidándonos de la administración a más bajo nivel.

En este momento ya seríamos capaces de nombrar las singularidades y ventajas


que un sistema PaaS basado en VPS puede ofrecer:

• Configuraciones�asistidas�del�servidor: en pocos pasos podemos dispo-


ner de servidores totalmente configurados para ejecutar los lenguajes de
programación más comunes.

• Proyectos�en�la�nube: podemos acceder al desarrollo de nuestros códigos


por internet mediante una URL real, superando las limitaciones del desa-
rrollo en local.

• Trabajos�colaborativos: los entornos de trabajo son accesibles desde in-


ternet, lo que permite a grupos de trabajo poder acceder al servidor para
realizar múltiples tareas de forma simultánea.

• Posibilidad�de�deslocalización�de�los�equipos�de�trabajo: cualquier or-


denador con acceso a internet se convierte en una estación de trabajo;
algunas de las herramientas más famosas ya incorporan IDE completos,
con lo que no hace falta instalar ningún otro software para trabajar en el
código del servidor.

4.1. Cloud9

Cloud9 se presenta como una aplicación en nuestro navegador en la que dis-


pondremos de un IDE completo donde además de poder desarrollar nuestras
aplicaciones online podremos administrar nuestros entornos de trabajo.
© FUOC • PID_00241997 81 Infraestructura DevOps

Dentro de los planes de precios encontraremos una opción gratuita en la que


dispondremos de un entorno de trabajo con los recursos suficientes donde
probar nuestras aplicaciones.

Figura 31. Detalle de la interfaz web de Cloud9

Fuente: Joan Caparrós.

La interfaz web nos permitirá crear y editar en tiempo real nuestras aplicacio-
nes, al tiempo que nos dará acceso a un terminal que nos permitirá instalar
dependencias y servicios (servidor web, framework, base de datos, etc.) como
si de una VPS se tratara.

El uso de Cloud9 es muy sencillo, la configuración de nuestro entorno de tra-


bajo (workspace) es muy visual y dispondremos de configuraciones ya estable-
cidas para disponer de entornos HTML5, NodeJS, Meteor, LAMP, Django, Rails,
C++, entre otros. Después del paso inicial de configuración del entorno, ya
solo se deberá incluir un repositorio de nuestro sistema de control de versio-
nes favorito y, tras ejecutar los servicios necesarios, ya podremos acceder a la
aplicación desde el navegador.

Figura 32. Detalle de las aplicaciones disponibles en Cloud9

Fuente: Joan Caparrós.


© FUOC • PID_00241997 82 Infraestructura DevOps

4.2. Heroku

Heroku es otra solución PaaS en donde albergar nuestras aplicaciones en la nu-


be. Para ello, la plataforma dispone de una opción gratuita con la que dispon-
dremos de los recursos mínimos para poder ejecutar el código desarrollado.

La plataforma dispone de configuraciones básicas para dar soporte al desplie-


gue de aplicaciones desarrolladas en NodeJS, Rails, Java, PHP, Python, Go, Sca-
la y Clojure. Una vez definido el lenguaje e introducido sus dependencias, el
sistema asignará un servidor ligero llamado dynos, donde ejecutará el código
indicado por el usuario.

Para configuraciones avanzadas se deberá instalar Heroku Toobelt, la aplica-


ción para poder manejar Heroku desde consola, disponible para Windows,
Mac OS y Debian/Ubuntu.

Los despliegues en Heroku están directamente ligados al código almacenado


en el sistema de control de versiones, Heroku Git, Github o Dropbox. Una vez
configurada la plataforma, las actualizaciones irán ligadas a las modificaciones
del código subido al repositorio remoto vinculado al proyecto; en cada push el
sistema reiniciará nuestra aplicación incorporando los últimos cambios apli-
cados.

La escalabilidad del proyecto dependerá de los dynos implicados en el proyec-


to, pero es posible ampliar los recursos destinados mediante la contratación
de horas de uso de dynos extras.

En el caso de necesitar mejorar los servicios que acompañan a nuestra aplica-


ción –como gestión de logs, testing, tareas programadas, entre otros–, Heroku
dispone de addons (podéis consultar la lista completa de addons disponibles
desde la web https://addons.heroku.com/).

A continuación mostraremos los pasos necesarios para el despliegue de una


aplicación dentro de la plataforma Heroku:

• Creamos una cuenta en Heroku: https://signup.heroku.com/.

• Instalamos Heroku Toobelt: https://toolbelt.heroku.com/.

• Iniciamos sesión en Heroku mediante el terminal: heroku login.

• Creamos una aplicación, mediante la herramienta web o ejecutando las


siguientes instrucciones:
– heroku create.

– heroku apps:rename nombreApp.


© FUOC • PID_00241997 83 Infraestructura DevOps

– heroku open.

• Procedemos a la sincronización del repositorio git vinculado con los últi-


mos cambios que aplicar mediante el comando push: git push origin mas-
ter.

• La aplicación quedará desplegada en la dirección https://


nombreApp.herokuapp.com.
© FUOC • PID_00241997 85 Infraestructura DevOps

Bibliografía
1. Bibliografía utilizada (libros, revistas, capítulos de libros u otras fuentes de
interés)

Además de los enlaces proveídos dentro de los propios materiales como recursos adicionales,
añadimos las siguientes publicaciones:

Effective DevOps: <http://shop.oreilly.com/product/0636920039846.do>.

The DevOps 2.0 Toolkit: <https://leanpub.com/the-devops-2-toolkit>.

The Phoenix Project: <https://www.amazon.com/Phoenix-Project-DevOps-Helping-Busi-


ness/dp/0988262592>.

The DevOps Handbook: <https://www.amazon.com/gp/pro-


duct/1942788002/ref=pd_sim_14_2?
ie=UTF8&psc=1&refRID=YW60HZBXV9XNQAJC9CPR>.

The Official (ISC)2 Guide to the CCSP CBK2nd Edition: <https://www.amazon.com/gp/pro-


duct/1119276721/ref=pd_sbs_14_3/157-2087627-3975059?
ie=UTF8&psc=1&refRID=5MR8CP23FF8YSNSFWZZR>.

2. Referencias

[1] James P. Womack; Daniel T. Jones; Daniel Roos (1990). «The Machine That Chan-
ged the World».

[2] Ward Cunningham (1992). «The WyCash Portfolio Management System» [en línea].
<http://c2.com/doc/oopsla92.html>.

[3] Kent Beck y otros (2001; febrero). Manifesto for Agile Software Development [en línea].
<http://agilemanifesto.org>.

[4] Brian Marick (2003, 22 de agosto). Agile testing directions: tests and examples [en línea].
<http://www.exampler.com/old-blog/2003/08/22/>.
Casos de uso PaaS
y de
automatización
completa
PID_00241998

Joan Caparrós Ramírez


Lorenzo Cubero Luque
Jordi Guijarro Olivares

Tiempo mínimo de dedicación recomendado: 5 horas


© FUOC • PID_00241998 Casos de uso PaaS y de automatización completa

Ninguna parte de esta publicación, incluido el diseño general y la cubierta, puede ser copiada,
reproducida, almacenada o transmitida de ninguna forma, ni por ningún medio, sea éste eléctrico,
químico, mecánico, óptico, grabación, fotocopia, o cualquier otro, sin la previa autorización escrita
de los titulares del copyright.
© FUOC • PID_00241998 Casos de uso PaaS y de automatización completa

Índice

Objetivos....................................................................................................... 5

1. Caso de uso 1: Docker Machine y OpenNebula........................... 7


1.1. Introducción a la Docker Machine ............................................. 7
1.2. Instalar docker-machine ............................................................. 7
1.3. Instalar el driver para OpenNebula de docker-machine .............. 8
1.3.1. Preparación del sistema ................................................. 8
1.3.2. Instalación del driver....................................................... 8
1.4. Instalar docker-engine ................................................................. 9
1.5. Cómo utilizar el driver de OpenNebula con docker-machine ..... 9
1.5.1. Crear nuestro Docker Engine ........................................ 9
1.5.2. Enlazar la shell local con la de la máquina virtual ......... 10
1.6. Ejemplo de uso ........................................................................... 10

2. Caso de uso 2: Docker Swarm Cluster con Consul sobre


OpenNebula.......................................................................................... 12
2.1. Consul ......................................................................................... 13
2.2. Docker Swarm ............................................................................. 14
2.2.1. Swarm-master ................................................................. 14
2.2.2. Swarm-nodo ................................................................... 14
2.3. Conexión con el Swarm-master .................................................. 14
2.4. Red ............................................................................................... 14
2.5. Ejemplo de uso ........................................................................... 15

3. Caso de uso 3: Balanceo transparente con Docker Swarm,


Compose y Consul.............................................................................. 16
3.1. Consul ......................................................................................... 17
3.2. Docker Swarm ............................................................................. 18
3.2.1. Swarm-master ................................................................. 18
3.2.2. Swarm-nodo ................................................................... 18
3.2.3. Desplegar contenedores Registrator ............................... 18
3.3. Load Balancer .............................................................................. 19
3.4. Dockerfile .................................................................................... 20
3.5. Docker Compose ......................................................................... 21
3.5.1. Gestionar Docker Compose ........................................... 22
3.6. Ejemplo de uso ........................................................................... 22

4. Herramientas de automatización completa y testing:


Jenkins................................................................................................... 28
4.1. Servlet Demo ............................................................................... 29
4.2. Ejecución de test del proyecto .................................................... 30
© FUOC • PID_00241998 Casos de uso PaaS y de automatización completa

4.3. Construcción del proyecto .......................................................... 32


4.3.1. Despliegue del proyecto ................................................ 32
4.3.2. Página inicial ................................................................. 32
4.3.3. Página resultado ............................................................. 32
4.4. Dockerización del proyecto ........................................................ 33
4.4.1. Construcción de la imagen docker ................................ 33
4.4.2. Fichero Dockerfile .......................................................... 36
4.4.3. Ejecución de la aplicación mediante contenedor
Docker ............................................................................ 37
4.4.4. Detención de la aplicación mediante contenedor
Docker ............................................................................ 38
4.5. Jenkins ......................................................................................... 38
4.5.1. Instalación mediante imagen dockerizada .................... 38
4.5.2. Instalación mediante fichero WAR oficial ..................... 39
4.5.3. Configuración de Jenkins .............................................. 39
4.6. Registry Docker Hub ................................................................... 43
4.6.1. Registro mediante imagen dockerizada ......................... 44
4.6.2. Contribuir con nuestra imagen a la comunidad ........... 46
4.7. Proceso de automatización completo (pipeline) .......................... 47
4.7.1. Compilar el código cada vez que este sufra un
cambio ............................................................................ 49
4.7.2. Construcción y publicación de la imagen ..................... 51
4.7.3. Notificación de errores durante el proceso de
automatización .............................................................. 53
© FUOC • PID_00241998 5 Casos de uso PaaS y de automatización completa

Objetivos

Introducir al estudiante varios casos de uso 100 % prácticos sobre escenarios


reales con aplicación directa de los conocimientos cubiertos en el módulo di-
dáctico «Infraestructura DevOps».
© FUOC • PID_00241998 7 Casos de uso PaaS y de automatización completa

1. Caso de uso 1: Docker Machine y OpenNebula

Para poder crear máquinas Docker Engine en la OpenNebula podemos usar el


driver docker-machine; una vez instalado, podremos crear e instanciar nuestros
contenedores de Docker.

Requerimientos:

• Docker� Engine: Nos permite crear los contenedores, gestionarlos e ins-


tanciarlos.

• Docker�Machine: Nos permite crear y gestionar las máquinas virtuales.

• Driver�Docker�Machine�OpenNebula: Nos permite utilizar el docker-ma-


chine en el cloud del OpenNebula.

1.1. Introducción a la Docker Machine

Con docker-machine podemos aprovisionar y administrar múltiples Dockers


remotos, además de aprovisionar clústeres Swarm en entornos Windows, Mac
y Linux.

Es una herramienta que nos permite instalar el demonio Docker en hosts vir-
tuales y administrar dichos hosts con el comando docker-machine. Además,
podemos hacerlo en distintos proveedores (VirtualBox, OpenStack, OpenNe-
bula, VmWare, etc.).

Usando el comando docker-machine podemos iniciar, inspeccionar, parar y


reiniciar los hosts administrados, actualizar el cliente y demonio Docker, y
configurar un cliente Docker para que interactúe con el host. Con el cliente
podemos correr dicho comando directamente en el host.

1.2. Instalar docker-machine

Como usuario privilegiado, nos descargamos el binario y ejecutamos:

curl -L https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-`uname -s`-


`uname -m` > /usr/local/bin/docker-machine && \
chmod +x /usr/local/bin/docker-machine

Una vez instalado, para comprobar que podéis ejecutar docker-machine, eje-
cutad desde vuestro usuario:
© FUOC • PID_00241998 8 Casos de uso PaaS y de automatización completa

docker-machine version

Si os dijera que no encuentra el binario, ejecutad:

export PATH=$PATH:/usr/local/bin

Enlace de interés

Podéis encontrar más información en: <https://docs.docker.com/machine/install-machi-


ne/>.

1.3. Instalar el driver para OpenNebula de docker-machine

Antes de instalar el driver, tenemos que preparar el equipo para la instalación.

1.3.1. Preparación del sistema

1)�Paquete�GO

wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz
tar -C /usr/local -xvzf go1.6.linux-amd64.tar.gz
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin

Creamos el directorio work en nuestro espacio de trabajo, por ejemplo, en el


$HOME:

mkdir $HOME/work

Indicamos las variables de entorno necesarias:

export GOPATH=$HOME/work
export PATH=$PATH:$GOPATH/bin

2)�Paquete�GIT,�BZR

sudo apt-get install git bzr

3)�Paquete�GODEP

go get github.com/tools/godep

1.3.2. Instalación del driver

Le damos la siguiente orden:

go get github.com/opennebula/docker-machine-opennebula
cd $GOPATH/src/github.com/opennebula/docker-machine-opennebula
© FUOC • PID_00241998 9 Casos de uso PaaS y de automatización completa

make build
make install

1)�ONE_AUTH�y�ONE_XMLRPC

Nos creamos un fichero donde indicaremos nuestro usuario y contraseña del


OpenNebula:

mkdir -p $HOME/.one
echo usuario:password > $HOME/.one/one_auth

Creamos las variables de entorno necesarias:

export ONE_AUTH=$HOME/.one/one_auth
export ONE_XMLRPC=http://iaas.csuc.cat:2633/RPC2

Enlace de interés

Podéis encontrar más información en: <https://github.com/opennebula/docker-machi-


ne-opennebula>.

1.4. Instalar docker-engine

Tal como se ha podido ver en el módulo «Infraestructura DevOps» es necesario


disponer del componente docker-engine para disponer de los comandos de
control de contenedores de manera local.

Para instalar el docker-engine, se recomienda visitar la página siguiente:


<https://docs.docker.com/engine/installation/linux/>.

1.5. Cómo utilizar el driver de OpenNebula con docker-machine

1.5.1. Crear nuestro Docker Engine

Existe una imagen en la OpenNebula de un sistema operativo donde ya


está instalado el docker y donde podemos lanzar contenedores; se llama
boot2docker. También existe una versión de Ubuntu.

Si no está disponible, desde el marketplace del OpenNebula la descargamos.


Una vez tenemos descargada la imagen, creamos la máquina virtual:

docker-machine create --driver opennebula --opennebula-image-id [num_imagen_boot2docker]


--opennebula-network-id [num_red] --opennebula-b2d-size [medida_en_MB] [nombre_máquina_virtual]

Más opciones:

• --opennebula-cpu: CPU value for the VM.


© FUOC • PID_00241998 10 Casos de uso PaaS y de automatización completa

• --opennebula-vcpu: VCPUs for the VM.


• --opennebula-memory: Size of memory for VM in MB.
• --opennebula-template-id: Template ID to use.
• --opennebula-template-name: Template to use.
• --opennebula-network-id: Network ID to connect the machine to.
• --opennebula-network-name: Network to connect the machine to.
• --opennebula-network-owner: User ID of the Network to connect the ma-
chine to.
• --opennebula-image-id: Image ID to use as the OS.
• --opennebula-image-name: Image to use as the OS.
• --opennebula-image-owner: Owner of the image to use as the OS.
• --opennebula-dev-prefixe: Dev prefixe to use for the images: 'vd', 'sd', 'hd',
etc.
• --opennebula-disk-resize: Size of disk for VM in MB.
• --opennebula-b2d-size: Size of the Volatile disk in MB (only for b2d).
• --opennebula-ssh-user: Set the name of the SSH user.
• --opennebula-disable-vnc: VNC is enabled by default. Disable it with this
flag.

1.5.2. Enlazar la shell local con la de la máquina virtual

Ahora conectaremos nuestra shell local a la de la máquina virtual para que


cada vez que ejecutemos docker, este pueda dar órdenes al docker instalado
en la máquina virtual.

Obtenemos las variables de entorno en la máquina virtual:

docker-machine env [nombre_máquina_virtual]

Enlazamos la shell:

eval "$(docker-machine env [nombre_máquina_virtual])"

Ahora ya podemos utilizar docker normalmente.

Variables de entorno

Para mantener las nuevas variables de entorno de manera persistente, añadidlas a vues-
tro .profile ($HOME/.profile).

1.6. Ejemplo de uso

Actualmente disponéis de dos imágenes, ya precreadas con el Docker Engine


instalado, que podéis usar: Boot2docker y Docker-Machine-Ubuntu-14.04.

Crear�un�contenedor�con�nginx�en�una�máquina�Docker�con�el�driver�de
Docker�Machine�en�el�OpenNebula
© FUOC • PID_00241998 11 Casos de uso PaaS y de automatización completa

Crear una máquina en el OpenNebula con el Docker Engine y un disco volátil


de 10 GB con el comando:

docker-machine create --driver opennebula --opennebula-network-id $NETWORK_ID --opennebula-image


-name boot2docker --opennebula-image-owner oneadmin --opennebula-b2d-size 10240 mydockerengine

Donde $NETWORK_ID será el ID de la red donde crearemos la máquina con


Docker Engine.

Figura 1. Detalle del dashboard de OpenNebula

Fuente: Jordi Guijarro.

Podemos comprobar que todo ha funcionado bien con el comando:

docker-machine ls

Los siguientes comandos nos muestran las variables de entorno necesarias para
acceder a la shell:

docker-machine env mydockerengine


eval $(docker-machine env mydockerengine)

Ahora podemos comenzar a usar docker sobre la máquina Docker Engine que
acabamos de crear:

docker pull nginx


docker run --name mynginx -d -p 80:80 nginx

Finalmente, comprobamos que podemos acceder al servidor web que acaba-


mos de crear.
© FUOC • PID_00241998 12 Casos de uso PaaS y de automatización completa

2. Caso de uso 2: Docker Swarm Cluster con Consul


sobre OpenNebula

En este apartado se tratará de la instalación de los siguientes requerimientos:

• Consul.
• Docker Swarm.
• Swarm-master.
• Swarm-nodo.
• Conexión con el Swarm-master.

Figura 2. Diagrama relacional de Git, los diferentes componentes de Docker y OpenNebula

La idea es disponer de un clúster con Docker Engine y poder instanciar en él


nuestros contenedores Docker.

• Docker�Swarm: Nos permite crear un clúster Docker. El nodo máster re-


cibirá y distribuirá los contenedores a los nodos secundarios donde se eje-
cutarán.

• Consul: Nos proporcionará el servicio de discovery de los nuevos nodos


que añadimos al clúster swarm.

1)�Requerimientos�previos

Los requerimientos previos son los siguientes:


© FUOC • PID_00241998 13 Casos de uso PaaS y de automatización completa

• Docker� Engine: Nos permite crear los contenedores, gestionarlos e ins-


tanciarlos.

• Docker�Machine: Nos permite crear y gestionar las máquinas virtuales.

• Driver�Docker�Machine�OpenNebula: Nos permite utilizar el docker-ma-


chine en el cloud del OpenNebula.

2)�Instalar�los�requerimientos

Para poder implementar el Docker�Swarm�Cluster con el OpenNebula tene- Ved también


mos que instalar: Docker� Engine, Docker� Machine y el driver� de� Docker
En los subapartados siguientes
Machine�por�el�OpenNebula. disponéis de un tutorial de có-
mo hacerlo.

2.1. Consul

Dispondremos de una máquina virtual con Docker Engine que nos proporcio-
nará el servicio de discovery con Consul.

Usaremos el driver de Docker Machine por el OpenNebula, y crearemos una


máquina virtual llamada Consul, donde después ejecutaremos un contenedor
con el propio servicio de Consul dentro de esta:

docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id


[boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] consul
docker $(docker-machine config consul) run -d -p "8500:8500" -h "consul" progrium/consul -server
-bootstrap
CONSUL_IP=$(docker-machine ip consul)

Podemos verificar que se ha instalado correctamente el servicio de Consul ac-


cediendo a la IP de la máquina, que acabamos de crear, por el puerto 8500.

Figura 3. Confirmación de la correcta instalación de Consul

Fuente: Jordi Guijarro.


© FUOC • PID_00241998 14 Casos de uso PaaS y de automatización completa

2.2. Docker Swarm

Dispondremos de dos tipos de máquinas virtuales con Swarm:

• Swarm�Master: Esta máquina será la encargada de distribuir las instancias


de los contenedores a los diferentes nodos que tengamos en el clúster.

• Swarm�Nodo: Esta o estas máquinas serán las que ejecutarán los contene-
dores Docker.

2.2.1. Swarm-master

Creamos la máquina virtual, con el driver de Docker Machine, por el nodo


máster de los clústeres:

docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id


[boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] --swarm --swarm-master
--swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500
--engine-opt cluster-advertise="eth0:2376" swarm-master

2.2.2. Swarm-nodo

Creamos la máquina virtual con el driver de Docker Machine, por los diferentes
nodos de los clústeres:

docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id


[boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] --swarm
--swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500
--engine-opt cluster-advertise="eth0:2376" swarm-nodo-01

Podemos crear tantos nodos como queramos. Solo tenemos que ir modifican-
do el nombre de la máquina virtual.

2.3. Conexión con el Swarm-master

Una vez hemos creado las diferentes máquinas virtuales que componen el clús-
ter, podemos conectarnos al nodo máster con el siguiente comando:

eval $(docker-machine env --swarm swarm-master)

2.4. Red

Una vez tenemos creado nuestro clúster con Swarm, también tenemos la op-
ción de poder crear redes privadas dentro del clúster:

docker network create --driver overlay --subnet=10.0.1.0/24 overlay_limpio


© FUOC • PID_00241998 15 Casos de uso PaaS y de automatización completa

docker network ls

Figura 4. Detalles de las redes disponibles en Docker


Enlace de interés

Para más información, po-


déis consultar el siguiente en-
lace: <http://opennebula.org/
docker-swarm-with-openne-
bula/>.

Fuente: Jordi Guijarro.

2.5. Ejemplo de uso

Ejecutar�contenedores�Docker�en�el�clúster�creado

Ahora podemos empezar a usar Docker sobre el clúster que acabamos de crear.
Utilizaremos un contenedor con nginx, por ejemplo:

docker pull nginx


docker run --name mynginx -d -p 80:80 nginx

Podemos comprobar cómo el contenedor se está ejecutando en un nodo del


clúster. Para ello, podemos observar que el contenedor con nuestro nginx está
corriendo en la máquina swarm-nodo-01:

docker ps

Figura 5. Detalle del contenedor corriendo en Swarm

Fuente: Jordi Guijarro.

Para acceder al servicio del contenedor, tenemos que poner la dirección IP del
nodo del clúster en el navegador.
© FUOC • PID_00241998 16 Casos de uso PaaS y de automatización completa

3. Caso de uso 3: Balanceo transparente con Docker


Swarm, Compose y Consul

En este apartado se tratará la instalación de los siguientes requerimientos pre-


vios:

• Consul.
• Docker Swarm.
• Load Balancer.
• Docker Compose.

Figura 6. Diagrama relacional de Git, los diferentes componentes de Docker y OpenNebula

A partir de la ilustración y para ir cubriendo todo el pipeline en este caso de uso,


crearemos un clúster de docker-engine e instanciaremos allá nuestros conte-
nedores docker. Además, configuraremos un servicio balanceado de alta dis-
ponibilidad escalable.

• Docker�Swarm: Nos permite crear un clúster docker. El nodo máster reci-


birá y distribuirá los contenedores a los nodos secundarios donde se eje-
cutarán.

• Consul: Nos proporcionará el servicio de discovery de los nuevos nodos y


servicios que añadimos al clúster swarm.
© FUOC • PID_00241998 17 Casos de uso PaaS y de automatización completa

• Registrator: Este servicio monitorizará la información como por ejemplo


IP y PUERTO de cada servicio activado en los hosts y la guardará en el
consul.

• Docker�Compose: Nos permite configurar y crear grupos de contenedores.


Podemos escalar el servicio ofrecido por un contenedor aumentando o
disminuyendo el número de contenedores.

1)�Requerimientos�previos

Los requerimientos previos son los siguientes:

• Docker� Engine: Nos permite crear los contenedores, gestionarlos e ins-


tanciarlos.

• Docker�Machine: Nos permite crear y gestionar las máquinas virtuales.

• Driver�Docker�Machine�OpenNebula: Nos permite utilizar el docker-ma-


chine en el cloud del OpenNebula.

• Docker�Compose.

2)�Instalar�los�requerimientos

Para poder implementar el docker�swarm�cluster con el OpenNebula tenemos Ved también


que instalar el Docker�Engine, Docker�Machine y el driver�Docker�Machine
En el apartado 1 de este mó-
OpenNebula. dulo disponéis de un tutorial
de cómo hacerlo.

Para instalar Docker Compose:

sudo -y curl
-L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m`
> /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
exit

3.1. Consul

Dispondremos de una máquina virtual que nos proporcionará el servicio de


discovery con consul.

Creamos una máquina virtual en la OpenNebula llamada consul y después


ejecutamos un contenedor docker de consul dentro de ella.

docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id


[boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] consul
© FUOC • PID_00241998 18 Casos de uso PaaS y de automatización completa

docker $(docker-machine config consul) run -d -p "8500:8500" -h "consul" progrium/consul


-server -bootstrap

3.2. Docker Swarm

Dispondremos de dos tipos de máquinas virtuales con swarm:

• Swarm-master: Esta máquina será la encargada de distribuir las instancias


de los contenedores a los diferentes nodos que tengamos en el clúster.

• Swarm-nodo: Esta o estas máquinas serán las que ejecutarán los contene-
dores docker.

3.2.1. Swarm-master

Creamos la máquina virtual del swarm-master:

export CONSUL_IP=$(docker-machine ip consul)


docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id
[boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] --swarm --swarm-master
--swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500
--engine-opt cluster-advertise="eth0:2376" swarm-master

3.2.2. Swarm-nodo

Creamos la máquina virtual del swarm-nodo:

docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id


[boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] --swarm
--swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500
--engine-opt cluster-advertise="eth0:2376" swarm-nodo-1

Podemos crear los nodos que queramos. Solo tenemos que cambiar el nombre
de la máquina virtual.

3.2.3. Desplegar contenedores Registrator

Una vez hemos creado el máster y los diferentes nodos, instanciaremos los
contenedores con el registrator a todos ellos. Utilizaremos la imagen de gli-
derlabs/registrator.

Necesitamos tener un servicio Registrator corriendo en cada host para moni-


torizar todos los servicios que corre cada host.

export MASTER_IP=$(docker-machine ip swarm-master)


© FUOC • PID_00241998 19 Casos de uso PaaS y de automatización completa

export NODO_IP=$(docker-machine ip swarm-nodo-1)

eval $(docker-machine env --swarm swarm-master)


docker run -d --name=registrator -h ${MASTER_IP} --volume=/var/run/docker.sock:/tmp/docker.sock
gliderlabs/registrator:latest consul://${CONSUL_IP}:8500

eval $(docker-machine env swarm-nodo-1)


docker run -d --name=registrator -h ${NODO_IP} --volume=/var/run/docker.sock:/tmp/docker.sock
gliderlabs/registrator:latest consul://${CONSUL_IP}:8500

3.3. Load Balancer

Ahora tenemos que implementar un balanceador de carga que pueda distribuir


las peticiones por las diferentes instancias del servicio. Como aumentamos y
disminuimos las instancias del servicio, necesitamos que el balanceador de
carga se actualice automáticamente.

Utilizaremos nginx para el Load Balancer y consul-template para la configu-


ración del nginx.

1)�default.ctmpl

Antes de nada, necesitamos crear un template para la configuración del nginx.


Consul-template automáticamente llenará este fichero con la información en
lo referente al servicio instanciado y creará la configuración para el nginx.

El fichero default.ctmpl tiene que ser así:

{{$app := env "APP_NAME"}}

upstream {{printf $app}} {


least_conn;
{{range service $app}}
server {{.Address}}:{{.Puerto}} max_fails=3 fail_timeout=60 weight=1;{{end}}
}

server {
listen 80 default;

location / {
proxy_pass http://{{printf $app}};
}
}
© FUOC • PID_00241998 20 Casos de uso PaaS y de automatización completa

Crearemos la variable app con el valor de la variable de entorno APP_NAME


(definida más adelante en el fichero docker-compose.yml). También creare-
mos un upstream con el nombre de la variable app. La línea least_conn hace
que nginx encamine el tráfico hacia la instancia con menos conexiones.

Por cada instancia del servicio corriendo crearemos una línea con la dirección
del nodo donde se ejecuta ({{.Address}}) y el puerto por donde está escuchando
({{.Puerto}}).

Finalmente está la zona de configuración del servidor. Aquí definimos el puer-


to de escucha del load balancer y creamos una reverse proxy en la upstream
que hemos creado.

2)�start.sh

Necesitamos un script que actúe como entry point para esta imagen de docker.

El fichero start.sh tiene que ser así:

#!/bin/bash
service nginx start
consul-template -consul=$CONSUL_URL -template="/templates/default.ctmpl:/etc/nginx/conf.d/
default.conf:service nginx reload"

Este script pone en marcha primero el servicio nginx. Después pone en marcha
consul-template pasándole dos parámetros:

• -consul: Le pasamos la variable de entorno $CONSURL_URL definida en


el docker-compose.yml.

• -template: Le pasamos tres parámetros: el path donde está el template que


hemos creado anteriormente (dentro del contenedor), el path donde se
guardará el fichero de configuración generado y el comando que se ejecu-
tará una vez que se genere una nueva configuración.

El consul-template creará un nuevo fichero de configuración cada vez que un


servicio se ponga en marcha o se pare. La información sobre estos servicios
es recogida por el servicio registrator de cada nodo swarm y es almacenada
en el consul.

Los ficheros start.sh y default.ctmpl los guardaremos en un directorio deno-


minado «files». En el directorio guardaremos los ficheros Dockerfile y doc-
ker-compose.yml.

3.4. Dockerfile

FROM nginx:latest
© FUOC • PID_00241998 21 Casos de uso PaaS y de automatización completa

RUN apt-get update \


&& apt-get install -y unzip

ADD filas/start.sh /bin/start.sh


RUN chmod +x /bin/start.sh
ADD filas/default.ctmpl /templates/default.ctmpl

ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip
/usr/bin/
RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin

EXPONGO 80
ENTRYPOINT ["/bin/start.sh"]

Este fichero utiliza nginx como imagen base e instala consul-template encima.
Después copia el script start.sh y el template default.ctmpl (que antes hemos
creado) dentro del contenedor. Finalmente, expone el puerto 80 y define el
script start.sh como entry point de la imagen.

3.5. Docker Compose

Docker Compose nos permite escribir la configuración que queremos que ten- Enlace de interés
gan los contenedores que desplegar. Utilizaremos Docker Compose File ver-
Para saber más sobre
sion 2, que nos permite definir la configuración en lo referente a la red, volú- la versión 2 del fiche-
menes, puertos, variables de entorno. ro de docker-compose,
podéis consultar el si-
guiente enlace: <https://
docs.docker.com/compo-
1)�docker-compose.yml
se/compose-file/compose-fi-
le-v2/>.
Ejemplo de docker-compose.yml:

version: '2'
services:
lb:
build: .
container_name: lb
puertos:
- "80:80"
environment:
- APP_NAME=[Nombre_de el_servicio]
- CONSUL_URL=${CONSUL_IP}:8500
depends_on:
- web
networks:
- frente-tier
web:
image: [imagen_docker]
© FUOC • PID_00241998 22 Casos de uso PaaS y de automatización completa

puertos:
- "[Puerto_de el_servicio]"
environment:
- SERVICE_NAME=[Nombre_de el_servicio]
networks:
- frente-tier
networks:
frente-tier:
driver: overlay

3.5.1. Gestionar Docker Compose

Para arrancar todos los servicios, ejecutamos lo siguiente:

eval $(docker-machine env -swarm swarm-master)


docker-compose up -d

Para ver los detalles de los servicios corriendo podemos utilizar el comando:

docker-compose ps

Para parar y eliminar los servicios que están corriendo actualmente:

docker-compose stop; docker-compose rm -f

Ahora mismo solo tenemos una instancia del servicio. Si queremos aumentar
o disminuir:

docker-compose scale [nombre servicio]=[número de instancias]

Enlace de interés

Si queréis obtener más información, visitad el siguiente enlace: <https://botleg.com/sto-


ries/load-balancing-with-docker-swarm/>.

3.6. Ejemplo de uso

Queremos crear un clúster de docker y crear un servicio web balanceado con


nginx y escalable con Docker Compose.

Actualmente disponéis de dos imágenes, ya precreadas con el Docker Engine


instalado, que podéis usar: Boot2docker o Docker-Machine-Ubuntu-14.04.

Creamos las máquinas virtuales de consul, swarm-master y un swarm-nodo:

docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name


boot2docker --opennebula-b2d-size 10240 consul
docker $(docker-machine config consul) run -d -p "8500:8500" -h "consul" progrium/consul -server
© FUOC • PID_00241998 23 Casos de uso PaaS y de automatización completa

-bootstrap
export CONSUL_IP=$(docker-machine ip consul)

docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name


boot2docker --opennebula-b2d-size 10240 --swarm --swarm-master --swarm-discovery="consul:
//$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt
cluster-advertise="eth0:2376" swarm-master

docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name


boot2docker --opennebula-b2d-size 10240 --swarm --swarm-discovery="consul://$CONSUL_IP:8500"
--engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376"
swarm-nodo-1

Nota

Con --opennebula-b2d-size 10240 creamos discos volátiles de 10 GB.

Donde $NETWORK_ID será el ID de la red donde crearemos el clúster.

Figura 7. Detalle del dashboard de OpenNebula

Fuente: Jordi Guijarro.

Desplegamos Registrator en todos los nodos:

export MASTER_IP=$(docker-machine ip swarm-master)


export NODO_IP=$(docker-machine ip swarm-nodo-1)

eval $(docker-machine env --swarm swarm-master)


docker run -d --name=registrator -h ${MASTER_IP} --volume=/var/run/docker.sock:/tmp/docker.sock
gliderlabs/registrator:latest consul://${CONSUL_IP}:8500

eval $(docker-machine env swarm-nodo-1)


docker run -d --name=registrator -h ${NODO_IP} --volume=/var/run/docker.sock:/tmp/docker.sock
gliderlabs/registrator:latest consul://${CONSUL_IP}:8500

Creamos los ficheros de configuración necesarios:

1)�files/default.ctmpl

{{$app := env "APP_NAME"}}


© FUOC • PID_00241998 24 Casos de uso PaaS y de automatización completa

upstream {{printf $app}} {


least_conn;
{{range service $app}}
server {{.Address}}:{{.Puerto}} max_fails=3 fail_timeout=60 weight=1;{{end}}
}

server {
listen 80 default;

location / {
proxy_pass http://{{printf $app}};
}
}

2)�files/start.sh

#!/bin/bash
service nginx start
consul-template -consul=$CONSUL_URL -template="/templates/default.ctmpl:/etc/nginx/conf.d/
default.conf:service nginx reload"

3)�Dockerfile

FROM nginx:latest

RUN apt-get update \


&& apt-get install -y unzip

ADD files/start.sh /bin/start.sh


RUN chmod +x /bin/start.sh
ADD filas/default.ctmpl /templates/default.ctmpl

ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip
/usr/bin/
RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin

EXPOXE 80
ENTRYPOINT ["/bin/start.sh"]

4)�docker-compose.yml

version: '2'
services:
lb:
build: .
container_name: lb
© FUOC • PID_00241998 25 Casos de uso PaaS y de automatización completa

puertos:
- "80:80"
environment:
- APP_NAME=web_nginx
- CONSUL_URL=${CONSUL_IP}:8500
depends_on:
- web
web:
image: nginx
puertos:
- "80"
environment:
- SERVICE_NAME=web_nginx
networks:
default:
driver: overlay

Activamos el servicio. Desde el directorio donde tenemos el doc-


ker-compose.yml, ejecutamos:

eval $(docker-machine env -swarm swarm-master)


docker-compose up -d
docker-compose ps
© FUOC • PID_00241998 26 Casos de uso PaaS y de automatización completa

Figura 8. Detalle de la activación del servicio

Fuente: Jordi Guijarro.

Para aumentar o disminuir las instancias del servicio, utilizamos el siguiente


comando:

docker-compose scale web=4

Con este comando aumentaremos en 4 las instancias desplegadas del servicio


web.

El nombre que indicamos tiene que ser el nombre que hemos indicado en
el fichero docker-compose.yml. Nosotros en el fichero docker-compose.yml
hemos indicado que el nombre del servicio era web.

Ejecutamos docker-compose�ps para saber el estado de las instancias. Hemos


borrado las direcciones IP. Aquí se vería cómo las instancias están repartidas
por los diferentes nodos del clúster swarm.

Figura 9. Detalle de las múltiples instancias del servicio

Fuente: Jordi Guijarro.


© FUOC • PID_00241998 27 Casos de uso PaaS y de automatización completa

Para acceder al servicio, tenemos que acceder con la IP del load�balancer�(lb).

Para finalizar, podemos optar por parar y/o borrar los servicios:

docker-compose stop; docker-compose rm -f


© FUOC • PID_00241998 28 Casos de uso PaaS y de automatización completa

4. Herramientas de automatización completa y


testing: Jenkins

Requerimientos previos:

• Java: Lenguaje de programación multiplataforma.

• Maven: Herramienta de gestión y construcción de software, encargada de


proveer vía online de las dependencias necesarias.

• Git: Software de control de versiones

• Tomcat: Funciona como un contenedor de servlets que implementa las


especificaciones de Java Servlet y JavaServer Pages (JSP).

• Docker� Engine: Nos permite crear los contenedores, gestionarlos e ins-


tanciar-los.

• Jenkins: Software dedicado a la integración continua que nos permitirá


automatizar los procesos de test, construcción y despliegue entre otros.

• Registry�Docker�Hub: Nos permite crear, compartir y utilizar imágenes


creadas por nosotros o por terceros.

Figura 10. Diagrama relacional de Git, los diferentes componentes de Docker y OpenNebula

En este caso de uso partiremos de un proyecto web desarrollado en Java cum-


pliendo con las especificaciones de JavaServlet Pages. Por ello, se deberá ins-
talar Java�Development�Kit (JDK) y descargar la librería JUnit�4 para ejecutar
los test; por último, solo quedará instalar el contenedor de servlets Apache
Tomcat.
© FUOC • PID_00241998 29 Casos de uso PaaS y de automatización completa

4.1. Servlet Demo

El servlet utilizado durante la fase de automatización es un ejemplo sencillo de


una aplicación web Java ubicada en un sistema de versionado público como
GitHub.

Para trabajar con el proyecto de forma individual se deberá hacer un «fork» del
repositorio, lo que permitirá a cada alumno poder tener una copia remota con
permisos para hacer cualquier cambio requerido.

Una vez disponemos del fork del repositorio en nuestra cuenta de GitHub,
procederemos al clonado en local mediante el comando:

git clone https://github.com/<usuario>/HelloDevOps.git

El proyecto demo está basado en un servlet JSP con una clase principal User
junto con su controlador y los test JUnit, que verificarán el correcto funcio-
namiento de este.

La estructura completa del proyecto será la siguiente:

Figura 11. Detalle de las estructura del proyecto

Fuente: Joan Caparrós.


© FUOC • PID_00241998 30 Casos de uso PaaS y de automatización completa

El proyecto HelloDevOps contiene los siguientes subdirectorios:

• .git: Esta carpeta se crea automáticamente en proyectos versionados bajo


Git.

• src/main: Contendrá los modelos y los controladores junto con los jsp
que construirán las páginas web de la aplicación.

• src/test: Contendrá los diferentes test desarrollados bajo la librería JUnit.

4.2. Ejecución de test del proyecto

Para ejecutar las pruebas unitarias, no es necesario configurar nada. La confi-


guración predeterminada de Maven escaneará el directorio ${basedir}/src/test/
java en busca de ficheros con el patrón *Test.java.

Para efectuar las pruebas unitarias desarrolladas, ejecutaremos:

$ mvn test

En el caso de superar los test, verificaremos que todos los test se han superado
y que el resultado completo de la ejecución de las pruebas unitarias ha sido
satisfactorio.

Figura 12. Detalle de una ejecución satisfactoria de los test

Fuente: Joan Caparrós.

Existen otros tipos de test, llamados test� de� integración� continua, que se
diferencian de los unitarios en que no necesitan disponer de todo el entorno
de la aplicación para ejecutarse, sino que analizan las aplicaciones a partir de
sus contextos (partes independientes en las que se divide una aplicación).
© FUOC • PID_00241998 31 Casos de uso PaaS y de automatización completa

Maven incorpora la posibilidad de poder realizar estos test independientes sin


que afecten a la continuidad de la construcción del proyecto. Imaginad que
uno de los contextos de nuestra aplicación formase parte de un sistema ex-
terno susceptible a sufrir inestabilidades, los test pararían el proceso de cons-
trucción cada vez que este no respondiera de forma adecuada. Para estos casos,
Maven –mediante el uso de su plugin Failsafe– introduce la posibilidad de in-
corporar en el ciclo de vida de construcción las fases de «pre-integration-test»,
«integration-test» y «post-integration-test».

Para el uso del plugin Failsafe se deberá añadir al fichero pom.xml el siguiente
código:

<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>

Según convención, los test que queramos integrar en los test de integración
continua deberán incorporar «IT» o «IntegrationTest» como sufijo en el nom-
bre del fichero.

Definir si el proceso de build debe o no pararse al fallar un test de integración


continua vendrá indicado por la variable testFailureIgnore de nuestro fichero
pom.xml, «false» (valor por defecto) para detener el proceso ante fallos de test
de integración continua y «true» para continuar pese el fallo.
© FUOC • PID_00241998 32 Casos de uso PaaS y de automatización completa

4.3. Construcción del proyecto

Para compilar el proyecto de forma manual tendremos que ejecutar el siguien-


te comando:

$ mvn package

Mediante el uso de Maven y dado el contenido del fichero principal pom.xml,


el comando resolverá todas las dependencias, procederá a la ejecución de los
test desarrollados para finalmente empaquetar el proyecto dentro de un fiche-
ro WAR en el directorio target.

Los archivos WAR (Web Application Archive) son ficheros utilizados para la
distribución de JavaServer Pages, servlets, clases Java, archivos XML, librerías
y otros ficheros necesarios para el despliegue de aplicaciones en contenedores
web como el proporcionado por Tomcat.

4.3.1. Despliegue del proyecto

Una vez realizada la construcción del proyecto y para hacer el servlet accesible,
deberemos:

• Copiar el archivo WAR generado en la carpeta webapps de nuestro tomcat.


• Reiniciar el servicio de tomcat.

A partir de este momento la aplicación estará disponible bajo el subdirectorio


con nombre igual al fichero WAR desplegado.

4.3.2. Página inicial

La página inicial se compone de un formulario simple que requiere un nombre


en forma de cadena de caracteres.

Figura 13. Detalle de la página inicial

Fuente: Joan Caparrós.

4.3.3. Página resultado

La página resultado utiliza la cadena anteriormente introducida para saludar


al programador en cuestión.
© FUOC • PID_00241998 33 Casos de uso PaaS y de automatización completa

Figura 14. Detalle de la página resultado

Fuente: Joan Caparrós.

4.4. Dockerización del proyecto

En este momento disponemos de una aplicación web funcional, que requiere


un contenedor de aplicaciones Apache Tomcat para hacerla accesible.

¿Cómo hacerla portable y que pueda ser ejecutada en cualquier máquina con
docker? La respuesta es la dockerización de la aplicación.

Docker nos permitirá introducir en una «caja» todas aquellas cosas que la apli-
cación necesita para ser ejecutada, sin tener que preocuparse por la versión de
software que la máquina host tiene instalada, por si tiene instalados todos los
módulos necesarios o por si son compatibles o no con nuestra aplicación.

El despliegue de la imagen dockerizada resultante ofrecerá a los desarrollado-


res, testers y administradores de sistemas confianza y seguridad en el producto
resultante, ya que asegurará el entorno de ejecución, permitiendo a los desa-
rrolladores centrarse en el código sin preocuparse de posibles fallos dados por
las máquinas donde se ejecutarán.

4.4.1. Construcción de la imagen docker

Para construir una imagen docker podemos partir de cualquier contenedor Nota
disponible en el registro de imágenes de Docker (Docker Hub Registry), don-
Docker Hub dispone de más
de se encuentran disponibles aplicaciones funcionales, tales como bases de de cien mil imágenes disponi-
datos, servidores de aplicaciones, servidores web, etc.; lo único necesario se- bles de forma pública y listas
para ser usadas.
rá construir un archivo Dockerfile que contenga la composición de nuestro
contenedor.

Nuestra imagen partirá de la imagen oficial dockerizada del contenedor de


aplicaciones web tomcat en su versión 8.5. El funcionamiento del contenedor
de aplicaciones es sencillo y solo requerirá copiar en su carpeta webapps el
fichero WAR resultante de la construcción del proyecto para que de esta forma
al ejecutar la aplicación se realice el despliegue de la aplicación de manera
automática.

El fichero Dockerfile pondrá por escrito todo aquello necesario para el desplie-
gue de nuestra aplicación, ejecutando todas aquellas instrucciones para pre-
parar el entorno encapsulado. Este fichero puede construirse en cualquier di-
rectorio de nuestra máquina.
© FUOC • PID_00241998 34 Casos de uso PaaS y de automatización completa

Las instrucciones más importantes disponibles para la construcción de un fi-


chero Dockerfile son:

1)�FROM: establece la imagen base a partir de la cual crearemos la imagen que


construirá el Dockerfile. Un Dockerfile válido debe situar la instrucción FROM
como primera línea (excluyendo comentarios).

#Inclusión de la última versión de la imagen (por defecto tag:latest).


FROM <imagen>

#Definición de la versión específica de la imagen a utilizar mediante tag.


FROM <imagen>:<tag>

#Definición de la versión específica de la imagen a utilizar mediante el uso del código sha256
generado durante la construcción de la imagen.
FROM <imagen>@<digest>

2)�MAINTAINER: permite establecer el campo autor de la imagen generada.

MAINTAINER <autor>

3)�ENV: establece variables de entorno que podrán ser interpretadas por las
instrucciones mediante el formato $variable o ${variable}.

ENV <variable> <valor>


ENV <variable>=<valor>

4)� RUN: permite ejecutar una instrucción en el contenedor, para instalar o


persistir cambios en el contenedor. Resulta útil para la instalación de paquete-
ría mediante gestores de paquetes o ejecución de scripts que afecten a la cons-
trucción de la imagen.

#Ejecución del comando en una shell, por defecto /bin/sh -c en Linux y cmd /S /C em Windows
RUN <command>

#Ejecución del comando en una shell en formato parametrizado (formato exec)


RUN ["ejecutable", "param1", "param2"]

5)�ADD: permite añadir ficheros, directorios o ficheros remotos al sistema de


ficheros del contenedor.

#Copia ficheros con origen local o remoto en un destino dentro del contenedor
ADD <origen>... <destino>

#Versión parametrizada de la instrucción


ADD ["<origen>",... "<destino>"]
© FUOC • PID_00241998 35 Casos de uso PaaS y de automatización completa

6)�COPY: similar a la instrucción ADD, permite añadir ficheros y directorios


pero no permite la inclusión de ficheros remotos.

COPY <origen>... <destino>


COPY ["<origen>",... "<destino>"]

7)�VOLUME: crea un punto de montaje en el sistema de ficheros del conte-


nedor. Los volúmenes permiten externalizar un determinado directorio y así
proporcionar persistencia a los datos depositados (las imágenes de docker no
almacenan datos en el contenedor entre diferentes ejecuciones), lo que per-
mite a su vez que estos directorios sean compartidos por otros contenedores
o por la máquina anfitrión.

VOLUME ["/data"]

8)�EXPOSE: permite exponer los puertos TCP/IP por los que se pueden acceder
a los servicios del contenedor. Por ejemplo: puerto 22 para SSH, 80 para HTTP
o 3306 para MySQL. Esta instrucción expone los puertos para ser usados por
el propio contenedor. En el caso de querer hacerlos accesibles desde fuera del
contenedor, se deberá utilizar el flag -p (publish) durante la ejecución.

EXPOSE <puerto> [<puerto>...]

9)� CMD: similar al RUN, permite la ejecución de instrucciones pero con la


diferencia de que este no se ejecuta al construir la imagen, sino que lo hace
en el momento de ejecución. Para que el fichero Dockerfile sea válido, solo
puede contener una única instrucción CMD.

#Formato exec parametrizado


CMD ["ejecutable","param1","param2"]

#Definición de los parámetros utilizados por ENTRYPOINT


CMD ["param1","param2"]

#Formato shell
CMD comando param1 param2

10)�ENTRYPOINT: permite sobreescribir el binario por defecto (/bin/sh -c) que


ejecutará CMD.

#Formato exec parametrizado


ENTRYPOINT ["ejecutable", "param1", "param2"]

#Formato shell
ENTRYPOINT comando param1 param2
© FUOC • PID_00241998 36 Casos de uso PaaS y de automatización completa

4.4.2. Fichero Dockerfile

Volviendo al ejemplo, la definición del fichero Dockerfile se ha establecido


dentro de la carpeta principal HelloDevOps del proyecto, por tanto, las refe-
rencias a ficheros partirán de esta carpeta, y quedarán de la siguiente forma:

#Imagen de partida tomcat en su versión 8.5


FROM tomcat:8.5-jre8

#Copiamos el contenedor WAR generado de nuestra aplicación dentro la carpeta webapps.


COPY target/hellodevops.war /usr/local/tomcat/webapps/

En este momento tenemos todo lo necesario para la creación de una imagen


docker.

Para crear una imagen a partir del fichero Dockerfile, nos situaremos en el
directorio donde se encuentra el dichero y ejecutaremos:

#Instrucción de creación de imágenes:


#docker build -t <nombre_de_la_imagen> <ruta_al_fichero_Dockerfile>

$ docker build -t hellodevops:v1.

• docker� build: Es el comando utilizado para la creación de una imagen


docker.

• -t�hellodevops:v1: Indicamos mediante el flag -t el nombre de la imagen


y opcionalmente un tag en formato «nombre:tag».

• .: Indica que el fichero Dockerfile se encuentra en el directorio donde nos


encontramos.

Al finalizar la construcción de nuestra imagen docker se mostrará el resultado


del proceso, y en el caso de ser exitoso acompañará con el identificador de
nuestra nueva imagen.

Successfully built 94af2f7c9151

Para verificar que la imagen se ha creado correctamente, usaremos la instruc-


ción docker�images:

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hellodevops v1 94af2f7c9151 4 minutes ago 332.8 MB
tomcat 8.5-jre8 fd9c13f14ae6 11 hours ago 332.6 MB
© FUOC • PID_00241998 37 Casos de uso PaaS y de automatización completa

Dentro del resultado deberíamos encontrar la imagen creada junto con la de-
pendencia de la imagen del Apache Tomcat 8.5, que podremos incluir en fu-
turos proyectos sin la necesidad de volver a descargarlo.

4.4.3. Ejecución de la aplicación mediante contenedor Docker

Para iniciar un contenedor es tan sencillo como usar el comando docker�run.


Si la imagen no existe en el equipo local, Docker intentará buscarla en el re-
gistro público de Docker. Es importante tener en cuenta que los contenedores
están diseñados para detenerse cuando el comando ejecutado en su interior
termina.

Instrucción para la ejecución de contenedores Docker:


#docker run [OPCIONES] IMAGEN[:TAG|@DIGEST] [COMANDO] [ARG...]

$ docker run -p 8080:8080 -d hellodevops:v1

• docker�run: Comando utilizado para la ejecución de contenedores a partir


de una imagen.

• -p� 8080:8080: Indicamos mediante el flag -p


<puerto_local>:<puerto_en_el_contenedor> la relación de puertos que se
establecerá para que nuestra aplicación sea accesible desde la máquina an-
fitrión. En este caso, la relación será directa y el puerto 8080 local referen-
ciará al puerto 8080 dentro del Apache Tomcat del contenedor docker.

• -d: Indicamos mediante el flag -d que el contenedor se ejecutará en segun-


do plano; de no ser así, la duración de la aplicación estaría unida a la se-
sión de nuestro terminal.

• hellodevops:v1: Es el nombre de la imagen con la cual queremos crear el


contenedor. También podemos usar el id pero el nombre es más fácil de
recordar.

En este momento, mediante el comando docker ps verificaremos que nuestro


contenedor está activo, con la asignación de puertos establecida.

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
f37315e8cf14 hellodevops:v1 "catalina.sh run" 9 minutes ago Up 9 minutes

PORTS NAMES
0.0.0.0:8080->8080/tcp pensive_jennings

Comprobamos el correcto funcionamiento de la aplicación web dockerizada


mediante la URL local: http://<my.servlet.host>:8080/hellodevops/.
© FUOC • PID_00241998 38 Casos de uso PaaS y de automatización completa

4.4.4. Detención de la aplicación mediante contenedor Docker

Para detener un contenedor docker disponemos de dos maneras distintas:

1)�docker�stop: detiene un contenedor en ejecución enviando primero una


señal SIGTERM a la aplicación principal dentro del contenedor para luego,
después de un tiempo de gracia, enviar una señal SIGKILL:

$ docker stop f37315e8cf14


f37315e8cf14

2)�docker�kill: detiene un contenedor en ejecución enviando directamente la


señal SIGKILL o la señal indicada mediante --signal a la aplicación principal
dentro del contenedor.

$ docker kill f37315e8cf14


f11f5cc90e84

La ejecución de docker stop intenta acabar con la aplicación de manera amis-


tosa mediante una señal estándar POSIX, mientras que docker kill mata el pro-
ceso. La recomendación de uso será siempre dentro de lo posible la utilización
del comando docker stop.

4.5. Jenkins

Esta herramienta nos ofrece un componente fiable para ejercer de servidor


de integración continua. El propósito principal para su uso no es solo por
su capacidad de automatización de procesos, sino que ofrece una plataforma
orientada al seguimiento del proceso de ejecución de todas estas tareas.

4.5.1. Instalación mediante imagen dockerizada

Conociendo el funcionamiento de los contenedores, podemos optar por la


utilización de la imagen oficial dockerizada de Jenkins suministrada por Doc-
ker Hub; este contenedor nos proporcionará el servicio de automatización de
una manera sencilla y rápida.

#docker run [OPCIONES] IMAGEN [COMANDO] [ARGUMENTOS...]


$ docker run -p 8090:8080 -p 50000:50000 \
-v <ubicación_fichero_docker.sock>:/var/run/docker.sock -v $(which docker):/usr/bin/docker jenkins

• docker�run: Comando utilizado para la ejecución de contenedores a partir


de una imagen.
© FUOC • PID_00241998 39 Casos de uso PaaS y de automatización completa

• -p�8090:8080�-p�50000:50000: Esta aplicación será accesible a través de


los puertos 8090 ofreciendo la interfaz gráfica web y 50000 exponiendo la
API, para ejecución de operaciones remotas.

• -v�<ubicación_fichero_docker.sock>:/var/run/docker.sock�-v�$(which
docker):/usr/bin/docker: Dado que este contenedor requiere el uso de los
comandos docker, mapearemos el socket y el propio binario docker para
que este pueda ser usado por el contenedor.

• jenkins: Nombre de la imagen del contenedor en Docker Hub.

En el caso de precisar persistencia de nuestras configuraciones, mapearemos


mediante la opción «-v» el path del home de Jenkins dentro del contenedor
con una ubicación conocida de nuestro ordenador.

$ docker run -p 8090:8080 -p 50000:50000 -v <ubicación_local>:/var/jenkins_home \


-v <ubicación_fichero_docker.sock>:/var/run/docker.sock -v $(which docker):/usr/bin/docker jenkins

Nota

La ubicación del fichero docker.sock en la mayoría de las distribuciones Linux es /var/


run/docker.sock.

4.5.2. Instalación mediante fichero WAR oficial

La instalación de Jenkins puede realizarse mediante el despliegue del fichero


WAR que encontraremos disponible para su descarga en la página oficial de
Jenkins. Para ello, disponemos de dos formas:

• Ubicando el fichero WAR en el directorio webapps de nuestro tomcat.

• Ejecutando java�-jar�jenkins.war--httpPort=8090�start donde hayamos


guardado nuestro fichero oficial.

En ambos casos la aplicación será accesible mediante la URL http:/


<my.jenkins.host>:8090.

4.5.3. Configuración de Jenkins

A la hora de montar un entorno de integración continua se requerirá dotar


a la plataforma de las herramientas necesarias para la ejecución de todos los
procesos automatizados. Jenkins ya incorpora muchos mecanismos que tan
solo deberán ser configurados, como el servidor de correo, pero otros deberán
instalarse (Maven y plugins).
© FUOC • PID_00241998 40 Casos de uso PaaS y de automatización completa

Configuración servidor de correo saliente

Jenkins notificará a los desarrolladores los sucesos importantes producidos du-


rante cada una de sus operaciones.

Para configurar el servidor de correo saliente a través de la interfaz gráfica de


Jenkins, nos dirigiremos utilizando los diferentes menús a Administrar Jenkins
-> Configurar el Sistema y al apartado dedicado a la Notificación por correo
electrónico.

Figura 15. Detalle de menú de configuración de Jenkins

Fuente: Joan Caparrós.

El servidor utilizado puede ser local o hacer referencia a un servidor smtp ofre-
cido por terceros. A continuación mostramos un ejemplo de configuración de
la plataforma Jenkins para la utilización de Gmail como plataforma de envío
de correos.

Figura 16. Detalle de la configuración del servidor de correo saliente de Jenkins

Fuente: Joan Caparrós.

Una vez configurado, podremos enviar un correo de prueba para asegurar la


correcta configuración del servidor.
© FUOC • PID_00241998 41 Casos de uso PaaS y de automatización completa

Instalación Maven en Jenkins

Debido a que Jenkins utilizará los comandos mvn para la compilación y cons-
trucción de nuevas imágenes, será un requisito que Maven esté instalado den-
tro de nuestro contenedor Jenkins.

Para instalar Maven a través de la interfaz gráfica de Jenkins, nos dirigiremos


utilizando los diferentes menús a Administrar Jenkins -> Administrar Plugins y
en el apartado dedicado a la configuración de Maven pondremos un nombre
para la versión elegida (por ejemplo: «Maven 3.3.9») y clicaremos en Instalar
automáticamente.

Figura 17. Detalle de la configuración de Maven en Jenkins

Fuente: Joan Caparrós.

A partir de este momento, Maven ya estará disponible para ser incorporado


en la pipeline del proceso de construcción de nuestros proyectos.

Instalación de plugins necesarios

Para poder realizar las acciones propuestas en este caso de uso, se requerirá la
instalación de distintos plugins de Jenkins.

Jenkins pone a disposición la capacidad de instalar los plugins más usados por
la comunidad durante la fase de configuración de la aplicación.

Así pues, podremos adquirir la mayoría de los plugins necesarios clicando sobre
«Install suggested plugins» dentro de la página de bienvenida de Jenkins.
© FUOC • PID_00241998 42 Casos de uso PaaS y de automatización completa

Figura 18. Página de bienvenida de Jenkins

Fuente: Joan Caparrós.

En el caso de poseer una instalación previa de Jenkins o de no querer instalar


la totalidad de los plugins sugeridos, se deberán instalar como mínimo los si-
guientes:

• Maven�Plugin: Necesario para dotar a nuestro servidor de integración con-


tinua de las herramientas para construir y testar nuestro proyecto.

• Git� Plugin: Permite la interacción con Git, por tanto, con plataformas
como GitHub.

• Mailer�Plugin: Permite configurar las notificaciones de correo electrónico


que la plataforma enviará con los resultados de la compilación y testeo.

• Workspace� Cleanup� Plugin: Elimina el espacio de trabajo antes de la


construcción asegurando que no haya ninguna interferencia de archivos
entre construcciones.

Instalación del plugin CloudBees Docker Build and Publish en


Jenkins

Construir una imagen docker en Jenkins requiere el uso de los binarios de doc-
ker. Hemos aprendido cómo construir la imagen durante la dockerización de
la aplicación, y estos podrían ser perfectamente incluidos en una de las dife-
rentes etapas que podríamos definir en un pipeline de nuestro proceso comple-
to de automatización, pero Jenkins ofrece herramientas para facilitar la cons-
trucción y publicación de imágenes docker en un Registry Docker Hub, sin
tener que escribir ninguna línea de código. En este caso de uso utilizaremos el
plugin CloudBees Docker Build and Publish.

Para instalar el plugin nos dirigiremos utilizando los diferentes menús a Admi-
nistrar Jenkins -> Administrar Plugins.
© FUOC • PID_00241998 43 Casos de uso PaaS y de automatización completa

Figura 19. Detalle del menú de administración de Jenkins

Fuente: Joan Caparrós.

Dentro de la administración de plugins nos situaremos en la pestaña Todos los


plugins, utilizaremos el filtro para indicar el plugin en cuestión, CloudBees Doc-
ker Build and Publish, marcaremos el checkbox de instalación y procederemos
clicando sobre Descargar ahora e instalar después de reiniciar.

Figura 20. Detalle de la instalación y configuración del plugin CloudBees Docker Build and
Publish

Fuente: Joan Caparrós.

4.6. Registry Docker Hub

Para completar el ciclo de nuestras imágenes docker, construiremos nuestro


propio registro de imágenes de Docker. Así, seremos capaces de enviar nuestras
aplicaciones que se encuentran en contenedores a la nube, teniendo un punto
donde almacenar y compartir estas aplicaciones con otros usuarios.

Docker ofrece dentro de sus productos un punto centralizado de almacena-


miento seguro de imágenes, que hasta el momento lo hemos usado para cons-
truir nuestras imágenes, Docker Hub.

Aunque Docker Hub nos permite disponer de solo un repositorio privado y


debe ser considerado un servicio de pago para el almacenamiento de aplica-
ciones privadas, como sucede con GitHub, Docker cubre las necesidades de
los desarrolladores entregando las herramientas necesarias para que cualquie-
ra pueda construirse su propio repositorio privado en la nube.
© FUOC • PID_00241998 44 Casos de uso PaaS y de automatización completa

4.6.1. Registro mediante imagen dockerizada

Podemos optar por la utilización de la imagen oficial dockerizada de Registry


Docker Hub suministrada por Docker Hub. Este contenedor nos proporcionará
el registro de nuestras propias imágenes generadas mediante docker.

Iniciaremos nuestro registry:

$ docker run -p 5000:5000 -v <ubicación_local>:/tmp/registry-dev registry

• docker�run: Comando utilizado para la ejecución de contenedores a partir


de una imagen.

• -p�5000:5000: Esta aplicación será accesible a través del puerto 5000, no


dispone de interfaz gráfica web.

• -v� <ubicación_local>:/tmp/registry-dev: Con el uso del flag «-v» dota-


mos de persistencia al contenedor ubicando de forma local las imágenes
subidas a nuestra aplicación.

• registry: Nombre de la imagen del contenedor en Docker Hub.

Para probar y entender el funcionamiento del registro de imágenes de Doc-


ker, realizaremos una pequeña prueba donde descargaremos una imagen des-
de Docker Hub a nuestra máquina local para luego enviarla a nuestro propio
Registry Docker Hub.

Descargamos la imagen hello-world https://hub.docker.com/_/hello-world/ a


nuestra máquina:

#docker pull [OPCIONES] NOMBRE[:ETIQUETA|@DIGEST]


$ docker pull hello-world

• docker�pull: Comando utilizado para la descarga de imágenes desde un


registro de imágenes de Docker.

• hello-world: Nombre de la imagen del contenedor en Docker Hub.

Para que nuestra imagen local pueda ser subida a otro registro de imágenes,
deberemos etiquetarla.

#docker tag IMAGEN[:TAG] IMAGEN[:ETIQUETA]


$ docker tag hello-world <my.registry.host>:5000/myhello-world
© FUOC • PID_00241998 45 Casos de uso PaaS y de automatización completa

• docker�tag: Comando utilizado para etiquetar aplicaciones en contenedo-


res indicando el nuevo registro de imágenes, nombre y etiqueta del propio
contenedor.

• hello-world: Nombre de la imagen del contenedor en Docker Hub.

• <my.registry.host>:5000/myhello-world: Asignación del nombre y regis-


tro de contenedores para nuestra imagen local hello-world.

Comprobamos que la imagen con su nueva etiqueta aparece dentro de nues-


tras imágenes locales.

Si la imagen aparece, procederemos a subirla hacia nuestro propio registro de


imágenes Docker.

#docker push [OPCIONES] NOMBRE[:ETIQUETA]


$ docker push <my.registry.host>:5000/myhello-world
The push refers to a repository [<my.registry.host>:5000/myhello-world]
a02596fdd012: Pushed
latest: digest: sha256:a18ed77532f6d6781500db650194e0f9396ba5f05f8b50d4046b294ae5f83aa4 size: 524

• docker� push: Comando utilizado para la subida de imágenes hacia un


registro de imágenes de Docker.

• <my.registry.host>:5000/myhello-world: Nombre y ubicación de la ima-


gen del contenedor en Docker Hub.

Para asegurar que la imagen se encuentra dentro del registro de imágenes crea-
do, verificaremos que esta se encuentre en el registro y procederemos a des-
cargarla.

#Existen distintos comandos para hacer llamadas a la API del registro de imágenes Docker,
dependiendo de la versión de este estarán o no disponibles, es por eso que mostraremos dos
métodos para recuperar las imágenes remotas:
#Mediante instrucciones docker
$ docker search <my.registry.host>:[PUERTO]/library

#Mediante llamadas a la API


$ curl <my.registry.host>:5000/v2/_catalog
{"repositories":["myhello-world"]}
© FUOC • PID_00241998 46 Casos de uso PaaS y de automatización completa

$ docker pull <my.registry.host>:5000/myhello-world


Using default tag: latest
latest: Pulling from myhello-world
Digest: sha256:a18ed77532f6d6781500db650194e0f9396ba5f05f8b50d4046b294ae5f83aa4
Status: Image is up to date for <my.registry.host>:5000/myhello-world:latest

4.6.2. Contribuir con nuestra imagen a la comunidad

Hemos hablado anteriormente de la plataforma Docker Hub Registry como un


punto de almacenamiento de imágenes públicas de Docker listas para su uso.
Detrás de todas estas imágenes hay un trabajo duro por parte de los desarro-
lladores para que nosotros podamos disfrutar de todos estos contenedores con
tan solo invocar su ejecución.

Para compartir nuestro trabajo con la comunidad, podemos hacer accesible


nuestras imágenes dentro de dicha plataforma mediante los siguientes pasos:

1) Visitar la página de Docker Hub.

2) Registrarnos dentro de la plataforma mediante el formulario de Sign�Up y


verificar la cuenta.

3) Entrar en la plataforma (Log�In).

4) Crear nuestro repositorio, indicando nombre, descripción y visibilidad (pú-


blica o privada).

5) A partir de este momento tendremos disponible nuestro primer repositorio


en la nube.

6) Para subir nuestro contenedor al repositorio creado en Docker Hub, debe-


remos autenticar nuestra máquina local mediante la instrucción:

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID,
head over to https://hub.docker.com to create one.
Username: <usuario>
Password: <contraseña>
Login Succeeded

7) Etiquetamos nuestra imagen local <imagen.local>, para ser albergada dentro


del repositorio con nombre <usuario>/<nombre.repositorio>.
© FUOC • PID_00241998 47 Casos de uso PaaS y de automatización completa

8) Subimos la imagen al repositorio de Docker Hub:

En este momento nuestra imagen ya estará disponible para todos los usuarios
de la comunidad Docker simplemente con ejecutar la respectiva instrucción
docker pull.

Vale la pena pararse e investigar todas las opciones que la plataforma Docker
Hub nos ofrece, ya que no se limita solo a albergar sino que permite la creación
de organizaciones con sus respectivos equipos de trabajo y derivar la automa-
tización de construcción de imágenes mediante cuentas GitHub o Bitbucket
relacionadas.

4.7. Proceso de automatización completo (pipeline)

El proceso de generación de contenedores funcionales con nuestra aplicación


será el objetivo principal de nuestro pipeline. Hasta el momento hemos reali-
zado cada uno de los pasos de forma manual y faltaría dotar a nuestro proceso
de creación de imágenes de una cierta automatización para realizar cada una
de las acciones.

Jenkins aparece en nuestro esquema como plataforma encargada de la auto-


matización y del monitoreo, pasando a ser nuestro sistema�de�integración
continua, que se encargará de todas las tareas definidas en nuestro proceso
de automatización.

Para nuestro pipeline definido detectaremos las siguientes tareas:

• Compilar el código cada vez que este sufra un cambio.

• Realizar las pruebas unitarias definidas.

• Construir mediante Maven nuestra aplicación.

• Realizar la imagen del contenedor con nuestra aplicación.


© FUOC • PID_00241998 48 Casos de uso PaaS y de automatización completa

• Registrar la imagen generada en nuestro registro de imágenes de Docker.

• Avisar a los desarrolladores, en el caso de que alguno de los pasos estable-


cidos no finalice correctamente, para efectuar los cambios en el código que
sean necesarios.

Figura 21. Tareas definidas en la Jenkins pipeline

Fuente: Joan Caparrós.

Para iniciar nuestro proyecto en Jenkins, se deberá crear una Nueva� Tarea,
disponible en el menú lateral derecho de la plataforma. En el caso de no dis-
poner de ninguna tarea anterior, Jenkins indicará en su parte central un enlace
directo para empezar con la creación de la primera tarea.

Definiremos un nombre de proyecto interno para la plataforma (“HelloDe-


vOps”) y elegiremos el método de Crear un proyecto de estilo libre, ideal para la
ejecución de proyectos provinientes de cualquier tipo de repositorio de soft-
ware, con cualquier método de construcción o ejecución (make, ant, mvn,
scripts...).

Figura 22. Creación de la tarea HelloDevOps

Fuente: Joan Caparrós.


© FUOC • PID_00241998 49 Casos de uso PaaS y de automatización completa

Una vez dentro de la pantalla de configuración del proceso de automatización


definiremos las propiedades Generales, que definirán aquellas propiedades
transversales a todas las operaciones realizadas. Para nuestro ejemplo dejare-
mos todos estos campos en blanco.

A continuación definiremos la configuración para cada una de las acciones


descritas durante la definición del pipeline.

4.7.1. Compilar el código cada vez que este sufra un cambio

Dado que nuestro proyecto debe generar una nueva imagen cada vez que se
incorporen cambios a la rama principal (master) de nuestro proyecto, debere-
mos establecer nuestro repositorio Git como fuente de origen.

Configurar el origen del código fuente

• Seleccionar Git.

• Introducir en Repository� URL https://github.com/<usua-


rio>/HelloDevOps.git manteniendo las credenciales en none (si vuestro
repositorio es público).

Figura 23. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Existen diferentes acciones que pueden hacer que nuestro proyecto Jenkins se
ejecute de manera automática. Estos representan los Disparadores�de�ejecu-
ciones, y son los siguientes:

• Lanzar� ejecuciones� remotas: Permite la ejecución del pipeline ac-


cediendo a una URL especial (JENKINS_URL/job/HelloDevOps/build?
token=TOKEN_NAME o /buildWithParameters?token=TOKEN_NAME),
útil para integrar dentro de scripts. Un uso habitual es la llamada de esta
URL desde los scripts (hooks) ejecutados cuando se realizan cambios dentro
de un repositorio de versiones.

• Construir�después�de�la�construcción�de�otros�proyectos: Permite de-


finir como disparadores de ejecución la finalización de construcción de
otros proyectos.
© FUOC • PID_00241998 50 Casos de uso PaaS y de automatización completa

• Ejecutar�periódicamente: Permite la definición de tiempos de ejecución


del proyecto definidos en formato cron con algunas pequeñas adaptacio-
nes (ejemplo: H/15 * * * * - dispara la ejecución del pipeline cada 15 minu-
tos).

• Construir�cuando�un�cambio�es�subido�(pushed)�al�GitHub: Permite re-


lacionar la ejecución del proyecto Jenkins a cada comando PUSH recibido
por el repositorio de versiones GitHub definido en la sección «Configurar
el origen del código fuente».

• Consultar�repositorio�(SCM): Esta opción complementa a la anterior y


permite la ejecución de comprobaciones del repositorio de versiones en el
caso de que no se disponga de scripts capaces de disparar ejecuciones. Se
definen en el formato cron adaptado de Jenkins.

Para nuestro proyecto estableceremos la opción Construir�cuando�un�cambio


es�subido�(pushed)�al�GitHub.

Figura 24. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Realizar las pruebas unitarias definidas

El lanzamiento de las pruebas unitarias define un proceso de ejecución, que


lanzará un comando maven con parámetro «test» (mvn test). Los resultados
de la ejecución definirán si el proceso continúa y esto indicará que nuestro
proyecto funciona adecuadamente.

Ejecutar:

• En el seleccionable elegir Ejecutar�tareas�'maven'�de�nivel�superior.

• Versión�de�Maven: Elegiremos mediante el listado desplegable la versión


de Maven definida en el apartado Instalación Maven en Jenkins de este
caso de uso.

• Goals: test.
© FUOC • PID_00241998 51 Casos de uso PaaS y de automatización completa

Figura 25. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Construir mediante Maven nuestra aplicación

El proceso de construcción de nuestro proyecto es indispensable para la gene-


ración del contenedor WAR en la carpeta target, que alimentará las siguientes
fases de nuestro pipeline. De modo similar a la ejecución de las pruebas unita-
rias, lanzarán un proceso maven con parámetro «package».

Ejecutar:

• En el seleccionable elegir Ejecutar�tareas�'maven'�de�nivel�superior.

• Versión�de�Maven: Elegiremos mediante el listado desplegable la versión


de Maven definida en el apartado Instalación Maven en Jenkins de este
caso de uso.

• Goals: package

Figura 26. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

4.7.2. Construcción y publicación de la imagen

Realizar la imagen del contenedor y posterior registro en cualquier registro de


imágenes de Docker será una tarea fácil mediante el plugin instalado Docker
Build�and�Publish. Este ejecutará todos los comandos docker indicados en
el apartado de Dockerización y Registry Docker Hub simplemente indicando el
repositorio destino y la URL del repositorio de imágenes docker.

Para la subida en nuestro repositorio de imágenes Docker, hemos de ejecutar:

• En el seleccionable elegir Docker�Build�and�Publish.

• Repository�Name: «test/hellodevops», definiendo un registro «test» don-


de se ubicará nuestra imagen con nombre «hellodevops».
© FUOC • PID_00241998 52 Casos de uso PaaS y de automatización completa

• Tag: La etiqueta de nuestra imagen definirá la versión del contenedor; para


ello concatenamos «v» con una variable interna con la versión actual de
construcción de Jenkins (${BUILD_NUMBER}).

• Docker� Host� URI: Puede dejarse en blanco para utilizar los valores de
entorno docker por defecto (normalmente unix:///var/run/docker.sock o
tcp://127.0.0.1:2375).

• Docker�registry�URL: http://<my.registry.host>:5000/.

Figura 27. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Para la subida en la nube (Docker Hub), hemos de ejecutar:

• En el seleccionable elegir DockerBuild�and�Publish.

• Repository�Name: «<usuario.docker.hub>/hellodevops», definiendo el re-


positorio remoto que previamente habremos creado.

• Tag: La etiqueta de nuestra imagen definirá la versión del contenedor; para


ello concatenamos «v» con una variable interna con la versión actual de
construcción de Jenkins (${BUILD_NUMBER}).

• Docker�Host�URI: Dejaremos los valores en blanco para el uso de las va-


riables por defecto de la plataforma.

• Docker�registry�URL: Podemos dejar el campo en blanco, ya que por de-


fecto este contendrá el valor que nos interesa https://index.docker.io/v1/.

• Registry�credentials: Indicaremos un nuevo registro con las credenciales


de nuestro usuario dentro de la plataforma Docker Hub.
© FUOC • PID_00241998 53 Casos de uso PaaS y de automatización completa

Figura 28. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Una vez compilado el proyecto y publicada la imagen en el registro de imá-


genes, liberaremos el espacio mediante la definición de un último proceso de
ejecución.

Acciones para ejecutar después: en el seleccionable hemos de elegir Delete


workspace�when�build�is�done.

Figura 29. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Esto eliminará la carpeta con el proyecto al terminar el proceso.

4.7.3. Notificación de errores durante el proceso de


automatización

Si se ha configurado, Jenkins enviará un correo electrónico a los destinatarios


especificados cuando se produzca un determinado evento importante.

Es importante denotar que cada construcción fallida enviará un nuevo correo


electrónico y que también se enviarán en casos de superación de problemas
tras una construcción fallida y construcciones inestables.

Acciones para ejecutar después:

• En el seleccionable, elegir Notificación�por�correo.

• Destinatarios: Permite especificar múltiples destinatarios a los cuales se


les enviará la copia completa de la salida por consola de procesos fallidos.
Las direcciones de correo serán separadas por un espacio en blanco.

• Se deberá especificar qué usuarios deberán recibir los errores, o todos los
desarrolladores o aquellos que hayan realizado el último commit.
© FUOC • PID_00241998 54 Casos de uso PaaS y de automatización completa

Figura 30. Configuración de la tarea HelloDevOps

Fuente: Joan Caparrós.

Para ejecutar por primera vez nuestro proceso de integración continua, podre-
mos o bien introducir algún cambio en nuestro código y hacer push en el repo-
sitorio de versiones, o bien clicar en la opción del menú lateral Construir ahora.

Figura 31. Ejecución de la tarea HelloDevOps

Fuente: Joan Caparrós.

¡Ya tenemos nuestro servidor de integración continua preparado y funcionan-


do!
Introducción a
la seguridad en
cloud computing
PID_00241999

Joan Caparrós Ramírez


Lorenzo Cubero Luque
Jordi Guijarro Olivares

Tiempo mínimo de dedicación recomendado: 5 horas


© FUOC • PID_00241999 Introducción a la seguridad en cloud computing

Ninguna parte de esta publicación, incluido el diseño general y la cubierta, puede ser copiada,
reproducida, almacenada o transmitida de ninguna forma, ni por ningún medio, sea éste eléctrico,
químico, mecánico, óptico, grabación, fotocopia, o cualquier otro, sin la previa autorización escrita
de los titulares del copyright.
© FUOC • PID_00241999 Introducción a la seguridad en cloud computing

Índice

Introducción............................................................................................... 5

1. Principales riesgos, patrones y mitigación proactiva de


amenazas.............................................................................................. 9
1.1. Control de proveedores. Procedimientos operativos de
seguridad ..................................................................................... 15
1.1.1. Seguimiento del servicio ................................................ 16
1.1.2. Gestión de cambios ....................................................... 17
1.1.3. Gestión de incidentes .................................................... 18
1.1.4. Respaldo y recuperación de datos ................................. 18
1.1.5. Continuidad del servicio ............................................... 19
1.1.6. Finalización .................................................................... 20
1.1.7. Supervisión y auditoría .................................................. 20

2. Gestión de riesgos e incidentes de seguridad en cloud............. 22


2.1. Gestión de riesgos: Cuestionario de evaluación ......................... 22
2.2. Respuesta a incidentes en entornos cloud.................................... 25
2.2.1. Eventos y ciberincidentes .............................................. 26
2.2.2. La respuesta a los ciberincidentes ................................. 26
2.2.3. Política de seguridad de la información y gestión de
ciberincidentes ............................................................... 27
2.2.4. La gestión de los ciberincidentes .................................. 27

3. Caso de Uso I: Seguridad en entornos IaaS públicos................. 29


3.1. Caso Amazon Web Services ........................................................ 29
3.1.1. Seguridad de la infraestructura ...................................... 29
3.1.2. Cifrado de datos ............................................................ 29
3.1.3. Trazabilidad de cambios ................................................ 30
3.1.4. Escaneo de vulnerabilidades .......................................... 30
3.1.5. Cuentas de usuario y API .............................................. 30
3.1.6. Protección contra ataques DDoS ................................... 30
3.2. Caso Digital Ocean ..................................................................... 35
3.2.1. Claves SSH ..................................................................... 35
3.2.2. Cortafuegos .................................................................... 36
3.2.3. VPN y redes privadas ..................................................... 37
3.2.4. Infraestructura de clave pública y SSL/TLS
encriptación ................................................................... 38
3.2.5. Auditoría de archivo y archivo de sistemas de
detección ........................................................................ 39
3.2.6. Entornos de ejecución aislada ....................................... 39
© FUOC • PID_00241999 Introducción a la seguridad en cloud computing

4. Caso de uso II: Seguridad en entornos PaaS privados


basados en Docker............................................................................. 41
4.1. Seguridad en el host..................................................................... 41
4.2. Buenas prácticas de seguridad .................................................... 48

5. Herramientas de seguridad............................................................. 51
5.1. Herramientas de control de acceso ............................................. 51
5.2. Herramientas contra la fuga de información ............................. 51
5.2.1. MyDLP Community ...................................................... 51
5.2.2. Ossec .............................................................................. 52
5.3. Herramientas de gestión de vulnerabilidades ............................. 52
5.3.1. BDD-Security .................................................................. 52
5.3.2. OWASP ZAP ................................................................... 52
5.3.3. Nessus ............................................................................. 52
5.4. Beneficios del uso de los estándares abiertos .............................. 53
© FUOC • PID_00241999 5 Introducción a la seguridad en cloud computing

Introducción

El modelo de servicio TI basado en cloud y el constante aumento de las amena-


zas informáticas implican un cambio en el concepto de seguridad informática
en las organizaciones, especialmente en la importancia estratégica que tiene la
seguridad en cloud computing. Estamos involucrados en una transformación de
paradigmas en las tecnologías de la información y la comunicación (TIC) en la
que la transformación digital basada en modelos cloud es la tónica general. El
crecimiento del cloud incorpora de manera nativa a la web, y este crecimiento
deriva en grandes retos para la seguridad informática.

El cibercrimen es desarrollado por organizaciones internacionales que tienen


como objetivo perjudicar a empresas y entidades gubernamentales. Por este
motivo, las organizaciones necesitan tratar la seguridad en el cloud de una ma-
nera estructurada. En el momento en el que una organización decide confiar
sus datos sensibles, como por ejemplo la información de sus clientes, ha de
controlar en todo momento:

• La localización de la información.
• El proveedor y modelo del servicio cloud.
• Las niveles de servicio respecto a la integridad y la disponibilidad de los
datos.

Además, hay que tener en cuenta el plan de continuidad de negocio, es decir, si


este proveedor presenta vulnerabilidades en sus sistemas de seguridad, cuáles
serían los potenciales riesgos en el negocio.

La gran mayoría de los proveedores de cloud aseguran que la seguridad, en úl-


tima instancia, es responsabilidad del cliente. AWS, RackSpace, Google y otros
solo se responsabilizan de sus centros de datos e infraestructura, su seguridad
está certificada por las máximas autoridades en la materia. En particular, AWS
lo llama «entorno de responsabilidad compartida». Como usuarios de diferen-
tes servicios cloud somos responsables de los datos que alojamos en servidores
y bases de datos de los proveedores de cloud. Recordemos entonces que la se-
guridad no solo es importante, sino que debemos trabajar en ella.
© FUOC • PID_00241999 6 Introducción a la seguridad en cloud computing

Figura 1. Modelos de servicio del cloud computing

Los proveedores de plataforma como servicio (PaaS) se encargan de la seguri-


dad de la capa de infraestructura y plataforma, mientras que el cliente debe
encargarse de la seguridad en la capa de aplicación.

En el caso de los proveedores infraestructura como servicio (IaaS), estos se


encargan de la seguridad de la capa de infraestructura, mientras que el cliente
debe encargarse de las otras dos.

En la capa de plataforma debemos usar todas las medidas necesarias para man-
tener nuestros servidores, bases de datos y copias de seguridad accesibles solo
a personal autorizado; usando el principio de menor privilegio, otorgaremos
a cada uno el mínimo privilegio necesario para realizar su trabajo.

Los analistas y programadores deben ocuparse de la capa de aplicación. No


tiene mucho sentido blindar los datos y servidores si la aplicación permite
accesos no legítimos a los datos o a funciones críticas de los servidores.

El cloud computing es una revolución en el mundo de las TIC. Trae en su desa-


rrollo una atractiva perspectiva para las organizaciones, grandes o pequeñas,
respecto a un mejor aprovechamiento de los recursos internos y a un modelo
de gestión optimizado.

Este nuevo modelo ofrece a las organizaciones la posibilidad de tener un foco


más claro en sus negocios a partir del momento en el que las tecnologías de
información pasan a ser tratadas como un suministro más de sus cadenas pro-
ductivas, y como todo nuevo concepto, el aspecto de la seguridad informática
es siempre uno de los puntos más importantes que hemos de tener en cuenta,
especialmente en momentos de intensa transformación.
© FUOC • PID_00241999 7 Introducción a la seguridad en cloud computing

En este capítulo dotaremos al alumno de la visión de los principales riesgos,


como la fuga de información o las credenciales comprometidas y la suplanta-
ción en la autenticación; los principales patrones, y la mitigación proactiva de
amenazas mediante los procedimientos operativos de seguridad para el con-
trol de proveedores.

También veremos la gestión de incidentes de seguridad en cloud: desde la po-


lítica de seguridad de la información, hasta la respuesta a incidentes en entor-
nos cloud.

Veremos en detalle el caso de uso de seguridad sobre el modelo de infraestruc-


tura como servicio pública basado en Amazon Web Services y DigitalOcean.
En el apartado de Amazon Web Services veremos los servicios de seguridad que
ofrece el proveedor y explicaremos en detalle cómo evitar ataques distribuidos
de denegación de servicio. Mientras que en el caso de DigitalOcean haremos
un repaso sobre prácticas de seguridad básica.

Analizaremos también el caso de uso sobre el modelo de plataforma como


servicio privada basada en Docker: desde la seguridad del host, hasta módulos
de computación segura. Al final de este apartado se proporciona al alumno un
checklist de prácticas de seguridad en Docker.

Por último, haremos un repaso de las principales herramientas de seguridad:


desde herramientas de gestión de acceso, hasta herramientas de gestión de
vulnerabilidades de seguridad, pasando por los beneficios del uso de los están-
dares abiertos.
© FUOC • PID_00241999 9 Introducción a la seguridad en cloud computing

1. Principales riesgos, patrones y mitigación proactiva


de amenazas

La naturaleza compartida en los catálogos de servicios en el campo de la


computación en la nube introduce la aparición de nuevas brechas de seguridad
que pueden amenazar los beneficios obtenidos en el cambio hacia tecnologías
basadas en la nube. Organizaciones como la CSA (Cloud Security Alliance)
advierten que es importante considerar que los servicios en la nube, por su
naturaleza, permiten a los usuarios omitir las políticas de seguridad de toda
la organización utilizando servicios externos, fenómeno que se conoce como
«Shadow IT». De aquí la importancia de establecer nuevos controles para la
detección, el control y la concienciación sobre los riesgos de esta nueva situa-
ción.

Figura 2. Modelos y áreas en el cloud computing

En términos generales, en función del tipo de servicio contratado, conforme


va incrementándose el nivel de abstracción disminuye el control que el cliente
tiene sobre la infraestructura. Del mismo modo, cuanto mayor control tiene la
organización o el cliente sobre la infraestructura que proporciona el servicio,
mayor nivel de seguridad y control puede aplicar sobre esta y, por tanto, sobre
la información tratada.

1)�Amenaza�n.º�1:�Fuga�de�información

Los entornos en la nube se enfrentan a muchas de las amenazas que ya encon-


tramos en las redes corporativas tradicionales, pero estas se acentúan debido a
la gran cantidad de datos almacenados en servidores en la nube, y los provee-
dores se convierten en un objetivo más atractivo. Si hablamos de datos/infor-
mación, es muy importante tener en cuenta que la gravedad del daño depen-
de en gran medida de la sensibilidad de los datos expuestos. La información
© FUOC • PID_00241999 10 Introducción a la seguridad en cloud computing

financiera expuesta tiende a salir en los titulares de la prensa generalista, pero


las infracciones que involucran información de salud, secretos comerciales y
propiedad intelectual son las más devastadoras.

Cuando se produce una fuga de datos, las empresas pueden incurrir en multas
o pueden enfrentarse a demandas o incluso a cargos criminales. También se
han de considerar las investigaciones de la infracción y las propias notifica-
ciones hacia los clientes, que por daños de imagen pueden añadir costes muy
significativos. Efectos indirectos, como daños a la marca y la pérdida de nego-
cio, pueden afectar a las organizaciones durante varios años.

Al final, los proveedores de nube implementan controles de seguridad para


proteger sus entornos, pero cabe recordar que en última instancia las organi-
zaciones son responsables de proteger sus propios datos dentro de la organi-
zación y también en la nube. Es más que recomendable que las organizaciones
utilicen mecanismos como la autenticación multifactor y el cifrado de datos
para protegerse contra las fugas de información.

2)�Amenaza�n.º�2:�Credenciales�comprometidas�y�suplantación�en�la�au-
tenticación

Las brechas de datos y otros ataques frecuentemente resultan de un sistema de


autenticación «pobre», como permitir contraseñas débiles y una mala admi-
nistración de claves o certificados. A menudo, las organizaciones luchan con
la gestión de identidades en tanto que tratan de asignar permisos adecuados a
la función de trabajo del usuario. Pero en algunas ocasiones la falta de gestión
correcta de las bajas provoca que no estas no sean efectivas en el momento en
el que el puesto de trabajo cambia o el usuario abandona la organización.

Los sistemas de autenticación multifactor, como las contraseñas de un solo


uso, la autenticación mediante dispositivos móviles y las tarjetas inteligentes
protegen los servicios en la nube porque dificultan que los atacantes inicien
sesión con contraseñas robadas. Existen multitud de ejemplos de organizacio-
nes y servicios de internet muy conocidos que han expuesto millones de regis-
tros de clientes o usuarios como resultado de credenciales de usuario robadas.
En la mayoría de los casos, asociado a fallos en el despliegue de un proceso de
autenticación de tipo multifactor, así que una vez que los atacantes obtienen
las credenciales, solo cabe esperar que el proceso que se encarga de la respuesta
a incidentes sea efectivo.

Muchos desarrolladores cometen el error de incrustar credenciales y claves


criptográficas en el código fuente y dejarlas en repositorios orientados al pú-
blico, como GitHub. Las claves necesitan estar adecuadamente protegidas, y
una infraestructura de clave pública bien asegurada es necesaria. También ne-
cesitan ser rotadas periódicamente para que a los atacantes les sea más difícil
utilizar claves que han obtenido sin autorización.
© FUOC • PID_00241999 11 Introducción a la seguridad en cloud computing

Las organizaciones que planean federar la identidad con un proveedor de la


nube necesitan entender las medidas de seguridad que el proveedor utiliza
para proteger la plataforma de identidad. Centralizar la identidad en un solo
repositorio tiene sus riesgos, y en cada caso se ha de valorar muy bien la pro-
tección y las salvaguardas asociadas.

3)�Amenaza�n.º�3:�Interfaces�y�API�hackeadas

Prácticamente todos los servicios y las aplicaciones en la nube ahora ofrecen


API para facilitar tareas de automatización e interoperabilidad. Los equipos
de TI utilizan interfaces y API para gestionar e interactuar con servicios en
la nube, incluidos aquellos que ofrecen aprovisionamiento en autoservicio,
gestión remota, orquestación, monitorización y supervisión en la nube.

La seguridad y la disponibilidad de los servicios en la nube, desde la autentica-


ción y el control de acceso hasta el cifrado y la monitorización de actividades,
dependen de la seguridad de la API. El riesgo aumenta con terceros que depen-
den de las API y se basan en estas interfaces, ya que las organizaciones pueden
necesitar exponer más servicios y credenciales. Las interfaces débiles y las API
exponen a las organizaciones a cuestiones de seguridad relacionadas con la
confidencialidad, la integridad, la disponibilidad y la rendición de cuentas.

Las API y las interfaces tienden a ser la parte más expuesta de un sistema
porque normalmente son accesibles desde internet. Se recomiendan controles
adecuados como la primera línea de defensa y detección. Las aplicaciones y los
sistemas de modelado de amenazas, incluidos los flujos de datos y la arquitec-
tura/diseño, se convierten en partes importantes del ciclo de vida del desarro-
llo. También se recomiendan revisiones de código enfocadas en la seguridad
y rigurosas pruebas de penetración.

4)�Amenaza�n.º�4:�Vulnerabilidades

Las vulnerabilidades del sistema, o bugs explotables en los programas, no son


nuevos, pero se han convertido en un problema mayor con la acentuación de
los sistemas de información «multitenant» en el modelo de cloud computing.
Las organizaciones comparten memoria, bases de datos y otros recursos en
estrecha proximidad, lo que crea nuevas superficies de ataque.

Afortunadamente, los ataques a las vulnerabilidades del sistema pueden ser


mitigados con «procesos de TI básicos». Las mejores prácticas incluyen la ex-
ploración regular de vulnerabilidades, la administración rápida de parches y
un rápido seguimiento de las amenazas informadas.

Es importante considerar que los costes de mitigar las vulnerabilidades del sis-
tema «son relativamente pequeños en comparación con otros gastos de TI». El
coste de poner los procesos de TI en el lugar que les correspondes con el obje-
tivo de controlar, detectar y reparar vulnerabilidades es pequeño en compara-
© FUOC • PID_00241999 12 Introducción a la seguridad en cloud computing

ción con el daño potencial. Las organizaciones necesitan parchear lo más rá-
pido posible, preferiblemente como parte de un proceso automatizado y recu-
rrente. Los procesos de control de cambios que tratan los parches de emergen-
cia aseguran que las actividades relacionadas con el mantenimiento del soft-
ware estén debidamente documentadas y revisadas por los equipos técnicos.

5)�Amenaza�n.º�5:�Secuestro�de�cuentas

La pesca electrónica (phishing), el fraude y las explotaciones de código siguen


teniendo éxito, y los servicios en la nube agregan una nueva dimensión a la
amenaza debido a que los atacantes pueden interceptar actividad, manipular
transacciones y modificar datos. A esto se debe añadir que los atacantes tam-
bién pueden utilizar la aplicación en la nube para lanzar otros ataques de ma-
nera encadenada.

Las estrategias más comunes en la defensa en profundidad pueden contener


los daños ocasionados por una infracción. Las organizaciones deben prohi-
bir el intercambio de credenciales de cuenta entre usuarios y servicios, así co-
mo habilitar sistemas de autenticación multifactor cuando estén disponibles.
Las cuentas, incluso las de servicio, deben ser monitorizadas para que cada
transacción pueda ser rastreada e identificar un usuario unipersonal si fuere
necesario. Una parte de la estrategia es proteger las credenciales de las cuentas
de usuario para evitar que estas sean robadas.

6)�Amenaza�n.º�6:�Intrusos�maliciosos

Esta amenaza tiene muchas caras: un empleado o un antiguo empleado, un


administrador de sistemas, un cliente o incluso un partner. La actividad mali-
ciosa puede querer llevar a cabo el robo de datos o un acto de venganza. En
un escenario en la nube, un actor privilegiado puede destruir infraestructuras
enteras o manipular datos. Los sistemas que dependen únicamente de un pro-
veedor de servicios en la nube, como podrían ser los de cifrado, corren sin
duda un mayor riesgo.

Se recomienda que sean las propias organizaciones las que controlen el proceso
de cifrado y las claves, segregando las tareas y minimizando el acceso dado
a los usuarios. Las actividades de registro, monitorización y auditoría de los
propios administradores también son consideradas a día de hoy como críticas.

En entornos de cloud computing, es fácil interpretar erróneamente un intento


de ataque por parte de un proceso rutinario como actividad «malintenciona-
da» sobre información privilegiada. Un ejemplo de esto sería un administra-
dor que copia accidentalmente una base de datos confidencial de clientes a un
servidor accesible públicamente. La formación y la prevención para prevenir
tales errores se vuelven aspectos más críticos en la nube, debido a una mayor
exposición de los sistemas y servicios.
© FUOC • PID_00241999 13 Introducción a la seguridad en cloud computing

7)�Amenaza�n.º�7:�El�parásito�APT

La CSA llama acertadamente a las amenazas persistentes avanzadas (APT) for-


mas «parásitas» de ataque. Las APT se infiltran en los sistemas para establecerse
en un punto de apoyo, y luego exfolian furtivamente los datos y la propiedad
intelectual durante un periodo prolongado de tiempo.

Las APT normalmente se mueven lateralmente a través de la red y se mezclan


con el tráfico normal, por lo que son difíciles de detectar. Los principales pro-
veedores de nube aplican técnicas avanzadas para evitar que las APT se infil-
tren en su infraestructura, pero los clientes deben ser tan diligentes en la de-
tección de compromisos APT en las cuentas de la nube como lo harían en sus
sistemas locales.

Entre los puntos de entrada comunes se incluyen la pesca electrónica, los ata-
ques directos, unidades USB precargadas con malware y redes de terceros com-
prometidas. En particular, se recomienda entrenar a los usuarios para que re-
conozcan las técnicas de pesca electrónica o phishing.

Los programas de concienciación mantienen a los usuarios en alerta y lo ha-


cen menos propensos a ser engañados para que una APT ingrese en la red. Por
otra parte, los departamentos de TI deben mantenerse informados de los últi-
mos ataques avanzados. Los controles de seguridad avanzados, la gestión de
procesos, los planes de respuesta a incidentes y la capacitación del personal de
TI conducen a mayores presupuestos de seguridad. Las organizaciones deben
sopesar estos costes frente al posible daño económico infligido por los ataques
exitosos de APT.

8)�Amenaza�n.º�8:�Pérdida�permanente�de�datos

A medida que la nube se ha madurado, los informes de pérdida permanente de


datos debido al error del proveedor se han vuelto extremadamente raros. Sin
embargo, se sabe que los hackers maliciosos eliminan de forma permanente los
datos de la nube para dañar a las empresas, y los centros de datos en la nube
son tan vulnerables a desastres naturales como cualquier instalación.

Los proveedores de nube recomiendan distribuir datos y aplicaciones a través


de múltiples zonas para una mayor protección. Las medidas adecuadas de res-
paldo de datos son esenciales, así como la adhesión a las mejores prácticas en
la continuidad del negocio y la recuperación de desastres. La copia de segu-
ridad diaria de datos y el almacenamiento en otro lugar físico siguen siendo
importantes con los entornos en la nube.
© FUOC • PID_00241999 14 Introducción a la seguridad en cloud computing

La carga de evitar la pérdida de datos no recae toda en el proveedor de servicios


en la nube. Si un cliente cifra datos antes de subirlos a la nube, entonces ese
cliente debe tener cuidado de proteger la clave de cifrado. Una vez que se
pierde la clave, también se pierden los datos.

Las políticas de cumplimiento a menudo estipulan cuánto tiempo las organi-


zaciones deben conservar los registros de auditoría y otros documentos. La pér-
dida de estos datos puede tener graves consecuencias regulatorias. Las nuevas
normas de protección de datos de la UE también tratan la destrucción de datos
y la corrupción de datos personales como infracciones de datos que requieren
una notificación adecuada. Hay que conocer las reglas para evitar problemas.

9)�Amenaza�n.º�9:�Inadecuada�diligencia

Las organizaciones que abrazan la nube sin entender completamente el en-


torno y sus riesgos asociados pueden encontrarse con un «incremento de ries-
gos comerciales, financieros, técnicos, legales y de cumplimiento». El grado
del riesgo depende de si la organización está intentando migrar a la nube o
fusionarse (o trabajar) con otra compañía en la nube. Por ejemplo, las organi-
zaciones que no examinan un contrato de servicio pueden no ser conscientes
de la responsabilidad del proveedor en caso de pérdida de datos o algún tipo
de incumplimiento.

Los problemas operacionales y de arquitectura surgen si el equipo de desarrollo


de una empresa carece de familiaridad con las tecnologías en la nube, ya que
las aplicaciones se despliegan en una nube en particular y no son habituales
a día de hoy los modelos híbridos o de tipo multicloud.

10)�Amenaza�n.º�10:�Abusos�de�los�servicios�en�la�nube

Los servicios en la nube pueden ser utilizados para apoyar actividades ilegales,
como el uso de recursos de computación en la nube para romper una clave
de cifrado para lanzar un ataque. Otros ejemplos incluyen el lanzamiento de
ataques DDoS, el envío de correos electrónicos de spam y phishing, y el aloja-
miento de contenido malicioso.

Los proveedores deben reconocer estos tipos de abuso –como el análisis del
tráfico para reconocer los ataques DDoS– y ofrecer herramientas para que los
clientes puedan supervisar la salud de sus entornos cloud. Los clientes deben
asegurarse de que los proveedores ofrezcan un mecanismo para notificar el
abuso. Aunque los clientes no pueden ser víctimas directas de acciones mali-
ciosas, el abuso en el servicio en la nube puede resultar en problemas de dis-
ponibilidad de servicios y pérdida de datos.

11)�Amenaza�n.º�11:�Ataques�DoS
© FUOC • PID_00241999 15 Introducción a la seguridad en cloud computing

Los ataques DoS han existido durante años, pero han ganado prominencia
gracias a la computación en la nube, ya que a menudo afectan de manera des-
tacada sobre la disponibilidad. Los sistemas pueden ralentizarse o estar fuera
de juego. «Experimentar un ataque de denegación de servicio es como estar
atrapado en un atasco de tráfico de hora punta; hay una manera de llegar a su
destino y no hay nada que pueda hacer al respecto, excepto sentarse y esperar».

Los ataques de DoS consumen grandes cantidades de procesamiento, una fac-


tura que el cliente puede finalmente tener que pagar. Aunque los ataques DDoS
de gran volumen no son muy comunes, las organizaciones deben ser cons-
cientes de los ataques asimétricos a nivel de aplicación de DoS, que se dirigen
a vulnerabilidades de servidor web y otros componentes críticos como son las
bases de datos.

La norma habitual es que los proveedores de nube tienden a estar mejor pre-
parados para manejar ataques de DoS que sus clientes. La clave es tener un
plan para mitigar el ataque antes de que ocurra, por lo que los administradores
tienen acceso a esos recursos cuando los necesitan.

12)�Amenaza�n.º�12:�Tecnología�compartida,�peligros�compartidos

Las vulnerabilidades en la tecnología compartida suponen una amenaza sig-


nificativa para la computación en la nube. Los proveedores de servicios en
la nube comparten infraestructura, plataformas y aplicaciones, y si surge una
vulnerabilidad en cualquiera de estas capas, afecta a todos. «Una sola vulne-
rabilidad o mala configuración puede llevar a un compromiso a través de la
nube de un proveedor entero».

Si un componente se ve comprometido –digamos, un hipervisor, un compo-


nente de plataforma compartida o una aplicación–, expone todo el entorno a
un posible compromiso y violación.

En definitiva, es más que recomendable una estrategia�de�defensa�en�pro-


fundidad, incluyendo la autenticación�multifactor en todos los hosts, siste-
mas�de�detección�de�intrusos tanto a nivel de host como en red, aplicando el
concepto de privilegios�mínimos, segmentación�de�red y parche�de�recur-
sos�compartidos.

1.1. Control de proveedores. Procedimientos operativos de


seguridad

Algunas operaciones del servicio deben ser realizadas de manera conjunta por
ambas partes, contratada y contratante, debiendo establecerse los roles, las
responsabilidades (capacidad de autorizar y obligación de rendir cuentas) y los
protocolos adecuados para llevarlas a cabo.
© FUOC • PID_00241999 16 Introducción a la seguridad en cloud computing

Cabe destacar las siguientes actividades, sin que sean las únicas que procedi-
mentar:

• Mantenimiento y gestión de cambios.


• Gestión de incidentes.
• Continuidad - recuperación de desastres.
• Gestión del personal.
• Configuración de seguridad.
• Recuperación de datos de copias de seguridad.

1.1.1. Seguimiento del servicio

En los servicios prestados por terceros a la organización, tan importante es el


acuerdo contractual con el proveedor de servicios como el seguimiento que
se debe realizar sobre el servicio prestado. Para poder tener el control de los
servicios, y por tanto también poder exigirle al proveedor el cumplimiento de
cualesquiera medidas de seguridad aplicables, es necesaria una monitorización
de estos.

• La medición del cumplimiento del servicio y el procedimiento para res-


taurar las desviaciones estipuladas contractualmente.

• El proceso de coordinación para el mantenimiento de los sistemas impli-


cados.

• El proceso de coordinación ante incidentes o desastres.

En cuanto al primer aspecto y dadas las características de la prestación de ser-


vicios en la nube, en ocasiones con aspectos relevantes fuera del control de
la organización cliente y también dada su forma de pago, en función del uso,
es muy importante reflejar de un modo claro los términos del cumplimiento.
Es necesario identificar en el contrato los derechos de la organización cliente
para poder monitorizar el funcionamiento del servicio y de este modo poder
comprobar el cumplimiento de las medidas de seguridad, los controles y las
políticas que garantizan la integridad, confidencialidad y disponibilidad de los
datos, y del mismo modo poder realizar la comprobación de que el nivel de
prestación es el pactado. La definición y el control de los SLA son vitales para
poder garantizar el cumplimiento de lo estipulado en el contrato.

La organización debe monitorizar de manera independiente el cumplimiento


de los términos establecidos en el contrato, bien a través de controles técnicos
propios o bien a través de la revisión y aprobación periódica de los informes
de servicio proporcionados por el proveedor de servicios cloud (CSP).

Es necesario ejecutar esta monitorización sobre al menos los siguientes con-


troles de seguridad y servicio con independencia de la categoría del sistema:
© FUOC • PID_00241999 17 Introducción a la seguridad en cloud computing

• Niveles de calidad, disponibilidad y capacidad del servicio ofrecido, inclu-


yendo el cumplimiento de las obligaciones de servicio acordadas y la res-
puesta ofrecida por el proveedor ante desviaciones significativas.

• Gestión de incidentes de seguridad, incluyendo toda la información nece-


saria para determinar orígenes, objetivos, riesgos... asociados a cualquier
incidente relevante.

• Controles de acceso a los servicios, incluyendo listado actualizado de usua-


rios autorizados para utilizar los servicios disponibles, y los privilegios aso-
ciados en cada caso.

• Cumplimiento normativo y legislativo entre el prestador y el cliente de


los servicios, incluyendo los aspectos de cumplimiento de aplicación sobre
el prestador que correspondan en cada caso, como auditorías LOPD, ISO,
financieras...

• Situación actualizada de las medidas de protección de la información es-


tablecidas por el proveedor, incluyendo aspectos de seguridad física, pro-
tección contra software malicioso, seguridad del personal, copias de segu-
ridad...

• Mecanismos de comprobación regular de los controles de seguridad por


parte del proveedor y resultados de dichas comprobaciones.

Toda la información de los controles anteriores proporcionada periódicamen-


te por el proveedor de servicios debe incluir de obligatoriamente cualesquie-
ra anomalías o desviaciones significativas producidas durante el periodo, así
como las acciones ejecutadas en cada caso como respuesta a estas situaciones
susceptibles de introducir riesgos en la organización. Adicionalmente, debe-
mos solicitar al proveedor de servicios la información de auditoría y no con-
formidades de aplicación en cada caso para poder verificar que las medidas de
seguridad tomadas por este son las correctas y oportunas para solventar des-
viaciones halladas durante el proceso de auditoría.

1.1.2. Gestión de cambios

Otro aspecto que se debe tratar en la gestión diaria del servicio es el referente a
la gestión y coordinación del mantenimiento de los sistemas. En este sentido,
se deberá establecer contractualmente de acuerdo con los requisitos mínimos
de normativas como el Esquema Nacional de Seguridad (ENS) la obligación de
mantener actualizados los sistemas para garantizar su correcto funcionamien-
to, así como eliminar las posibles vulnerabilidades que pueden afectar a los
sistemas.
© FUOC • PID_00241999 18 Introducción a la seguridad en cloud computing

Deberá definirse un procedimiento de coordinación en el mantenimiento de


sistemas entre ambas partes para prevenir paradas o errores en la prestación
del servicio; este procedimiento estará en línea con el proceso de gestión de
cambio e incluirá la notificación con suficiente antelación de la realización
de mantenimientos por parte del proveedor, identificando los tiempos en los
que puede interrumpirse el servicio. La notificación se realizará previa y pos-
teriormente al mantenimiento, y tras este se pedirá al cliente conformidad del
correcto funcionamiento del servicio.

Por otra parte, siempre que el mantenimiento o la actualización implique un


cambio mayor o pueda suponer el funcionamiento incorrecto de los sistemas
de la organización cliente, el proveedor habilitará previamente un entorno ac-
tualizado para que el cliente puede verificar el correcto funcionamiento de sus
sistemas en preproducción. Además, el proveedor deberá informar periódica-
mente de los mantenimientos y las actualizaciones realizados en los sistemas
que albergan los sistemas del cliente.

1.1.3. Gestión de incidentes

De acuerdo con normativas vigentes y buenas prácticas, el proveedor deberá


disponer de un procedimiento de gestión de incidentes. Se deberá informar a
la organización cliente de:

• Procedimiento de notificación de incidentes.


• Tipología de incidentes incluidos en el servicio.
• Procedimientos específicos ante incidentes de seguridad.
• Tiempos de respuesta y resolución de incidentes.
• Mantenimiento y gestión del registro de incidentes.

Deberá definirse un procedimiento de coordinación ante incidentes que pue-


dan afectar a los sistemas del cliente, procedimiento que deberá contemplar
los flujos de información y las interacciones entre cliente y proveedor durante
la gestión del incidente. A su vez, el proveedor deberá informar periódicamen-
te de los incidentes que han afectado a los sistemas que soportan los sistemas
del cliente.

En los niveles de servicio, en el caso de incidentes que afecten a la información


o a los servicios del organismo contratante, el proveedor deberá facilitar toda
la información forense necesaria para analizar el incidente y su gestión.

1.1.4. Respaldo y recuperación de datos

El proveedor deberá disponer de un procedimiento de copias de respaldo que


garantice la restauración de la información como describe [mp.info.9]. El pro-
veedor deberá informar a la organización cliente de:

• Política de copias de seguridad.


© FUOC • PID_00241999 19 Introducción a la seguridad en cloud computing

• Medidas de cifrado de información en respaldo.


• Procedimiento de solicitud de restauraciones de respaldo.
• Realización de pruebas de restauración.
• Alcance de los respaldos.
• Traslado de copias de seguridad (si procede).

1.1.5. Continuidad del servicio

De acuerdo con normativas como el ENS o normas como la ISO27001, los sis-
temas afectados deberán disponer de medidas para la continuidad del servicio.
Si bien los niveles de disponibilidad, así como los tiempos de recuperación en
la prestación de servicios, se encuentran recogidos contractualmente a través
de los SLA, se deberá solicitar al proveedor evidencia de que existe un plan
de continuidad de negocio que garantice la restauración de los servicios. El
proveedor deberá informar a la organización cliente de:

• Existencia de plan de continuidad de negocio.


• Evidencia satisfactoria de la ejecución periódica de pruebas de continui-
dad.
• Análisis de impacto del servicio proporcionado.

Se considerarán los siguientes aspectos en función del nivel de disponibilidad


requerido:

1) Se deberá requerir al proveedor evidencia de que existe un plan de conti-


nuidad de negocio cuyo alcance incluya los servicios objeto de la prestación.

2) Se exigirá constancia de que los tiempos de recuperación identificados en


el análisis de impacto están alineados con los criterios definidos en los SLA en
cuanto a tiempo de recuperación del servicio.

3) Deberá definirse un procedimiento de coordinación ante incidentes y desas-


tres que puedan afectar a los sistemas del cliente, procedimiento que deberá
contemplar los flujos de información y las interacciones entre cliente y pro-
veedor durante la gestión tanto de incidentes como de desastres.

4) A su vez, el proveedor deberá informar periódicamente de los incidentes


que han afectado a los sistemas que soportan los sistemas del cliente.

5) Se realizarán pruebas periódicas que involucren al organismo y a los dife-


rentes proveedores y subproveedores para validar el correcto funcionamiento
de los planes y el cumplimiento de los plazos y servicios mínimos previstos
© FUOC • PID_00241999 20 Introducción a la seguridad en cloud computing

1.1.6. Finalización

Salvo cuando la parte contratante disponga de una copia actualizada de su in-


formación, se deberán establecer los procedimientos para que esta recupere la
información entregada al proveedor. En estos procedimientos se deben acotar
formatos de datos y tiempos.

Salvo cuando la parte contratante no haya transferido información en claro


al proveedor, se deberán establecer procedimientos para la eliminación de las
copias en los equipos del proveedor. Estos�procedimientos�deben�incluir�los
mecanismos�de�borrado�y�las�garantías�de�que�han�sido�aplicados�correcta-
mente. Los tiempos de destrucción de la información deberán tener en cuenta
los requisitos legales de retención, si los hubiera.

Los procedimientos anteriores deben tener en el proveedor la parte correspon-


diente para prolongarlos a posibles terceros proveedores subcontratados.

1.1.7. Supervisión y auditoría

La organización cliente, como responsable última de los posibles riesgos que


afecten tanto a la información como a los servicios prestados, deberá disponer
de un determinado nivel de control sobre tales servicios. En este sentido y
para garantizar el cumplimiento de las medidas de seguridad de aplicación
en cada caso, la organización deberá evaluar la conveniencia de disponer del
derecho de auditoría, con la profundidad correspondiente, sobre el proveedor
de servicios o de solicitarle la siguiente documentación:

• Una declaración de aplicabilidad de las medidas que hay que aplicar.

• Una auditoría que verifique mediante evidencias el cumplimiento de las


medidas de seguridad que sean de aplicación de acuerdo con el nivel del
sistema.

• Auditorías de cumplimiento de normativa necesaria para satisfacer los re-


quisitos de seguridad de la información del organismo contratante. Por
ejemplo, LOPD, SAS70, PCI-DSS, etc.

El proveedor puede disponer de certificaciones o acreditaciones en materia de


seguridad. Estas certificaciones pueden simplificar la auditoría completa del
servicio prestado, en su condición de evidencias de cumplimiento que valorar
por el equipo auditor. Por ejemplo:

• Auditorías recomendadas por ENISA para proveedores de servicios en la


nube [ENISA-CCSL].
© FUOC • PID_00241999 21 Introducción a la seguridad en cloud computing

• Sistema de Gestión de la Seguridad de la Información (SGSI) [ISO/IEC


27001:2013].

• Sistema de Gestión de la Continuidad [ISO 22301:2012].

• Cloud Controls Matrix [CCM].

Figura 3. Control de medidas de seguridad sobre la base de la norma ISO 27001 y Cloud
Control Matrix (CSA)
© FUOC • PID_00241999 22 Introducción a la seguridad en cloud computing

2. Gestión de riesgos e incidentes de seguridad en


cloud

La manera de empezar que hemos considerado para esta sección no es en nin-


gún caso la habitual, pero en el camino de la adopción del cloud computing y
todo lo que implica es importante situar el punto en el que nos encontramos
y el objetivo.

2.1. Gestión de riesgos: Cuestionario de evaluación

Las preguntas críticas que las organizaciones deben hacerse a sí mismas y a sus
proveedores de la nube durante cada paso son las siguientes:

1) Asegurar eficazmente la gobernanza, el riesgo y los procesos de cumplimien-


to:

• ¿Qué normas de seguridad y privacidad de la información o qué regula-


ciones se aplican a la nube de dominio por el cliente?

• ¿El cliente tiene procesos de gobierno y de cumplimiento para el uso del


servicio en la nube?

• De acuerdo con los requerimientos del cliente, ¿el proveedor tiene proce-
sos apropiados de gobernanza y notificación?

• ¿Está claro qué controles legales y regulatorios se aplican a los servicios


del proveedor?

• ¿Qué contemplan los acuerdos a nivel de servicio sobre la división de res-


ponsabilidades de seguridad entre proveedor y cliente?

• ¿Existe un riesgo relacionado con la ubicación de los datos?

2) Auditoría. Presentación de informes operacionales y procesos de negocio:

• ¿Existe alguna certificación demostrable por parte del proveedor? La in-


formación de auditoría se ajusta a una de las Normas para la auditoría de
seguridad, como ISO 27001/27002.

• ¿Tiene el proveedor mecanismos para informar a los clientes tanto de as-


pectos rutinarios como de comportamiento excepcional relacionado con
sus servicios?
© FUOC • PID_00241999 23 Introducción a la seguridad en cloud computing

• ¿Los controles de seguridad abarcan no solo los propios servicios en la


nube, sino también las interfaces de gestión ofrecidas a los clientes?

• ¿Existe un proceso de notificación de incidentes y gestión de incidentes


críticos?

3) Administrar a las personas, roles e identidades:

• ¿Ofrecen los servicios del proveedor un control de acceso de tipo granular?

• ¿Puede el proveedor proporcionar informes para supervisar el acceso de


los usuarios?

• ¿Es posible integrar o federar sistemas de gestión de identidad de clientes


con las instalaciones de gestión de identidad del proveedor?

4) Asegurar la correcta protección de datos e información:

• ¿Existe un catálogo de todos los activos de datos que se utilizarán o alma-


cenarán en la nube?

• ¿Hay una descripción de los roles responsables?

• ¿Se ha tenido en cuenta el tratamiento de todas las formas de datos, en


particular datos como vídeos e imágenes?

• ¿Existe una separación de entornos adecuada entre clientes?

• ¿Se han aplicado las medidas adecuadas de confidencialidad e integridad


de los datos almacenados?

5) Políticas de privacidad:

• ¿Los servicios del proveedor cuentan con controles apropiados para ma-
nejar datos personales?

• ¿Existen restricciones de localización geográfica de los datos en el acuerdo


de servicio?

• Si hay un incumplimiento sobre el tratamiento de los datos, el proveedor


es responsable de informar de ello y resolverlo. ¿Están claras las prioridades
y los plazos?

6) Evaluar la seguridad de las aplicaciones:


© FUOC • PID_00241999 24 Introducción a la seguridad en cloud computing

• Basado en el modelo que aplique (IaaS, PaaS, SaaS), ¿está claro quién tiene
la responsabilidad de la seguridad de las aplicaciones (cliente o proveedor)?

• Si es el cliente, ¿tiene políticas y metodologías establecidas para asegurar


los controles de seguridad apropiados para cada aplicación?

• Si es el proveedor, ¿el acuerdo de servicio en la nube hace que sus respon-


sabilidades sean claras y que existan controles de seguridad específicos pa-
ra ser aplicados a la aplicación?

• En cualquier caso, ¿la aplicación hace uso de técnicas de cifrado adecuadas


para proteger los datos y las transacciones de los usuarios?

7) Asegurar la red:

• ¿Es posible la detección o inspección del tráfico de la red?

• ¿Qué capacidad tiene el proveedor para hacer frente a los ataques de de-
negación de servicio?

• ¿Tiene la red del proveedor la capacidad de detección y prevención de


intrusiones?

• ¿Está el acceso a la red del cliente separado del acceso a la red del provee-
dor?

8) Controles de la infraestructura física:

• ¿Puede el proveedor de servicios en la nube demostrar los controles de


seguridad apropiados aplicados a su infraestructura física e instalaciones?

• ¿Dispone el proveedor de servicios de instalaciones para garantizar la con-


tinuidad frente a amenazas o fallos en el equipamiento?

9) Términos del acuerdo sobre el servicio:

• ¿El acuerdo de servicio especifica las responsabilidades de seguridad del


proveedor y del cliente?

• ¿El acuerdo de servicio requiere que todos los términos de seguridad tam-
bién deben aplicar a cualquier proveedor de servicios utilizado por el pro-
veedor?

• ¿El acuerdo de servicio tiene métricas para medir el desempeño y la eficacia


de seguridad?
© FUOC • PID_00241999 25 Introducción a la seguridad en cloud computing

• ¿El contrato de servicio documenta explícitamente los procedimientos de


notificación y manejo de incidentes de seguridad?

10) Requisitos de seguridad del proceso de salida o fin de contrato:

• ¿Existe un proceso documentado de salida como parte del servicio?

• ¿Está claro que todos los datos de los clientes del servicio en la nube se
borran en el momento de finalizar el proceso de migración o salida?

• ¿Los datos de los clientes de servicios en la nube están protegidos contra


pérdidas o incumplimientos durante la salida?

2.2. Respuesta a incidentes en entornos cloud

La labor del proveedor es básica en las actividades de respuesta ante la ocu-


rrencia de algún incidente de seguridad. Esto incluye la verificación, el análisis
del ataque, la contención, la recogida de evidencias, la aplicación de remedios
y la restauración del servicio.

La colaboración entre los proveedores y los suscriptores para la detección y el


reconocimiento de los incidentes es esencial para la seguridad y la privacidad
en cloud computing, ya que la complejidad de los servicios puede dificultar la
labor de la detección.

Se hace necesario entender y negociar los procedimientos de respuesta a inci-


dentes antes de firmar un contrato de servicio. La localización de los datos es
otro aspecto que puede impedir una investigación, por lo que es otro de los
puntos que se deben negociar en los contratos.

Figura 4. Ciclo de vida de la respuesta a ciberincidentes

La solución que se negocie ha de tener la finalidad de mitigar el incidente en


un tiempo que limite los daños y que mejore los tiempos de recuperación. Los
equipos para la resolución deberían ser mixtos (proveedor y suscriptor), ya que
la solución puede involucrar a alguna de las partes de forma individual o a
ambas conjuntamente, y el incidente puede incluso afectar a otros suscriptores
que comparten la infraestructura.
© FUOC • PID_00241999 26 Introducción a la seguridad en cloud computing

2.2.1. Eventos y ciberincidentes

Los ataques contra los sistemas de información son, cada día, no solo más nu-
merosos y diversos, sino también más peligrosos o potencialmente dañinos.
Aunque las acciones y medidas preventivas, adoptadas en función de los re-
sultados obtenidos de los preceptivos análisis de riesgos a los que deben so-
meterse todos los sistemas públicos, contribuyen sin lugar a dudas a reducir el
número de ciberincidentes, la realidad nos muestra que, desafortunadamente,
no todos pueden prevenirse.

Por tanto, se hace necesario disponer de la adecuada capacidad de respuesta


a ciberincidentes, que detectando rápidamente ataques y amenazas minimice
la pérdida o la destrucción de activos tecnológicos o de información, mitigue
la explotación dañina de los puntos débiles de las infraestructuras y alcance
la recuperación de los servicios a la mayor brevedad posible. Esta sección ofre-
ce pautas para el manejo de ciberincidentes y para la determinación de la res-
puesta más adecuada a cada tipo, independientemente de la plataforma tec-
nológica subyacente, el hardware, los sistemas operativos o las aplicaciones.

Puesto que gestionar adecuadamente los ciberincidentes constituye una acti-


vidad compleja que contempla la adopción de métodos para recopilar y ana-
lizar datos y eventos, metodologías de seguimiento, procedimientos de tipifi-
cación de su peligrosidad y priorización, así como la determinación de canales
de comunicación con otras unidades o entidades, propias o ajenas a la organi-
zación, la consecución de una capacidad de respuesta eficaz a ciberincidentes
exige una planificación escrupulosa y la correspondiente asignación de recur-
sos, adecuados y suficientes.

2.2.2. La respuesta a los ciberincidentes

Para las organizaciones, el beneficio más significativo de poseer una adecuada


capacidad de respuesta a ciberincidentes es abordar su gestión de manera sis-
temática (es decir, siguiendo una metodología consistente y consolidada), lo
que facilita la adopción de las medidas adecuadas.

Así, una correcta capacidad de respuesta a ciberincidentes ayuda a los equipos


de seguridad responsables a minimizar la pérdida o exfiltración de informa-
ción, o la interrupción de los servicios. Otro de sus beneficios es la posibilidad
de utilizar la información obtenida durante la gestión del ciberincidente para
preparar mejor la respuesta a incidentes de seguridad futuros y, en consecuen-
cia, proporcionar una mayor y mejor protección a los sistemas.
© FUOC • PID_00241999 27 Introducción a la seguridad en cloud computing

2.2.3. Política de seguridad de la información y gestión de


ciberincidentes

Las buenas prácticas en seguridad señalan la necesidad de una política de se-


guridad reconocida y conocida en la organización. Normativas�como�el�Es-
quema�Nacional�de�Seguridad�(ENS) establecen los requisitos mínimos que
debe contemplar toda política de seguridad, entre ellos, los incidentes de se-
guridad, para los que debe especificarse:

• La posición del Equipo�de�Respuesta�a�Ciberincidentes (ERI), sus com-


petencias y autoridad, dentro de la estructura de la organización y la defi-
nición de los roles y responsabilidades de cada unidad.

• Normativa de seguridad.

• Definición de los ciberincidentes considerados a tenor del análisis de ries-


gos y los términos de referencia usados.

• Criterios para la comunicación de ciberincidentes y, en su caso, el inter-


cambio de información, interna y externamente.

• Nivel de peligrosidad de los ciberincidentes.

• Procedimientos operativos de seguridad.

• Mecanismos para la notificación de informes de ciberincidentes.

• Formularios de notificación, comunicación e intercambio de información.

• Elementos del Plan de respuesta a ciberincidentes.

Los organismos del ámbito de aplicación del ENS deben poseer un Plan de
respuesta a ciberincidentes que dé adecuada respuesta a sus requisititos espe-
cíficos, atendiendo a la misión, el tamaño, la estructura y las funciones de la
organización. El Plan debe, asimismo, determinar y asegurar que se dispone
de los recursos humanos y materiales necesarios, y debe contar con el impres-
cindible apoyo por parte de la Dirección.

Una vez que la Dirección de la organización ha redactado y aprobado el Plan


de respuesta a ciberincidentes, se iniciará su implantación. El Plan debería ser
revisado, al menos, anualmente para asegurar que la organización está siguien-
do adecuadamente la hoja de ruta para una mejora continua.

2.2.4. La gestión de los ciberincidentes

La gestión de ciberincidentes consta de varias fases:


© FUOC • PID_00241999 28 Introducción a la seguridad en cloud computing

1) La fase�inicial contempla la creación y formación de un Equipo de Respues-


ta a Ciberincidentes (ERI) y la utilización de las herramientas y los recursos
necesarios.

Durante esta fase de preparación, la organización, atendiendo a un previo


análisis de riesgos, habrá identificado y desplegado un determinado conjunto
de medidas de seguridad. La adecuada implantación de las medidas ayudará a
detectar las posibles brechas de seguridad de los sistemas de información de la
organización y a su análisis, en la fase de detección,�análisis�y�notificación,
lo que desencadenará los procesos de notificación pertinentes.

2) La organización, en la fase de contención,�erradicación�y�recuperación


del ciberincidente y atendiendo a su peligrosidad, deberá intentar, en prime-
ra instancia, mitigar su impacto, procediendo después a la eliminación de los
sistemas afectados y tratando finalmente de recuperar el sistema al modo de
funcionamiento normal. Durante esta fase será necesario, cíclicamente, per-
sistir en el análisis de la amenaza, de cuyos resultados se desprenderán, paula-
tinamente, nuevos mecanismos de contención y erradicación.

3) Tras el incidente, en la fase de actividad�posciberincidente, los responsa-


bles de la organización emitirán un Informe del ciberincidente, que detallará
su causa originaria y su coste (especialmente, en términos de compromiso de
información o de impacto en los servicios prestados), así como las medidas
que la organización debe tomar para prevenir futuros ciberincidentes de na-
turaleza similar.
© FUOC • PID_00241999 29 Introducción a la seguridad en cloud computing

3. Caso de Uso I: Seguridad en entornos IaaS públicos

En este apartado veremos prácticas de seguridad aplicadas a entornos IaaS


públicos, en concreto veremos el caso de Amazon Web Services y de Digital
Ocean.

3.1. Caso Amazon Web Services

En el caso de Amazon�Web�Services, veremos brevemente los aspectos rela-


tivos a la seguridad más importantes que debemos tener en cuenta, para cen-
trarnos después en detalle en cómo mitigar los ataques de tipo DDoS combi-
nando diferentes servicios del proveedor de IaaS.

3.1.1. Seguridad de la infraestructura

Amazon Web Services, en adelante AWS, proporciona varias capacidades y ser-


vicios de seguridad para mejorar la privacidad y controlar el acceso de redes.
Entre ellos, se incluyen los firewalls de red integrados en Amazon VPC, y las
capacidades de firewall para aplicaciones web existentes en AWS WAF permi-
ten crear redes privadas y controlar el acceso a las instancias y aplicaciones.
También se incluye el cifrado en tránsito con TLS en todos los servicios. Y por
último, existen las opciones de conectividad que permiten conexiones priva-
das o dedicadas desde la oficina o entorno on-premise.

Como podemos ver, AWS en sí ya implementa diferentes medidas de seguridad


en cuanto a seguridad de la infraestructura, lo que permite a los usuarios de
AWS centrarse en otros aspectos de la seguridad.

3.1.2. Cifrado de datos

AWS ofrece la posibilidad de añadir una capa de seguridad adicional a los datos
en reposo en la nube, proporcionando características de cifrado en los servicios
de base de datos y almacenamiento, como EBS, S3, Glacier, Oracle RDS, SQL
Server RDS y Redshift.

También podemos utilizar servicios de administración de claves, como AWS


Key Management Service, que permiten elegir si AWS administra las claves de
cifrado o si mantenemos el control sobre las claves.

AWS también proporciona diversas API para que pueda integrar el cifrado y
la protección de los datos con cualquiera de los servicios desarrollados en un
entorno de AWS.
© FUOC • PID_00241999 30 Introducción a la seguridad en cloud computing

3.1.3. Trazabilidad de cambios

Utilizando herramientas de administración de inventario y configuración, co-


mo AWS Config, que identifican los diferentes recursos de AWS, se puede rea-
lizar el seguimiento de los cambios en esos recursos a lo largo del tiempo. Po-
demos así construir una trazabilidad sobre los cambios de configuración e in-
cluso volver atrás en el tiempo hacia un escenario más seguro.

3.1.4. Escaneo de vulnerabilidades

AWS ofrece un servicio de evaluación de la seguridad, Amazon Inspector, que


evalúa las aplicaciones automáticamente para detectar vulnerabilidades o des-
viaciones de las prácticas recomendadas. Dicho escaneo incluyes las redes, el
sistema operativo y el almacenamiento.

3.1.5. Cuentas de usuario y API

Amazon ofrece herramientas para cuidar la seguridad. La autenticación por


múltiples factores en las cuentas de AWS es muy recomendable mediante el
servicio AWS Multi-Factor Authentication.

Se recomienda crear cuentas separadas para los usuarios de Amazon con el fin
de no compartir contraseñas. Hay que asegurar también que no se utilicen
cuentas root y que las cuentas solo tengan los privilegios necesarios, por ejem-
plo las cuentas de desarrollador. AWS Identity and Access Management (IAM)
permite definir cuentas de usuarios individuales con permisos en los recursos
de AWS.

Es recomendable utilizar las herramientas de Amazon para administrar claves


privadas y almacenarlas posteriormente de forma segura. Por último, hay que
supervisar las actividades sospechosas, como las llamadas inesperadas a la API
e inicios de sesión inusuales.

3.1.6. Protección contra ataques DDoS

En el caso de un ataque DDoS (distributed denial of service), un atacante utiliza


múltiples fuentes que pueden haber sido comprometidas o controladas por
un colaborador para orquestar un ataque contra un objetivo. En un ataque
DDoS, cada uno de los colaboradores o hosts comprometidos participa en el
ataque, generando una inundación de paquetes o peticiones con el fin de que
un servicio o recurso sea inaccesible a los usuarios legítimos.

Defensa de la capa de infraestructura

En un entorno de centro de datos tradicional, se puede proteger la capa de


infraestructura frente a ataques DDoS utilizando técnicas como el sobreprovi-
sionamiento, desplegando sistemas de mitigación de DDoS, o por medio la
© FUOC • PID_00241999 31 Introducción a la seguridad en cloud computing

limpieza de tráfico con la ayuda de servicios de mitigación de DDoS. En AWS


existen opciones para diseñar una aplicación para poder escalar y absorber
mayores volúmenes de tráfico sin recurrir a una complejidad innecesaria.

1)�Tamaño�de�instancia

La capacidad de cómputos es un recurso escalable en Amazon EC2. Se puede


escalar horizontalmente añadiendo instancias a la aplicación, según sea nece-
sario. O también se puede escalar verticalmente usando instancias mayores.
Algunos tipos de instancia constan de interfaces de red de 10 Gigabits, que
mejoran la capacidad para manejar grandes volúmenes de tráfico. Esto ayuda
a evitar la congestión de la interfaz para cualquier tráfico que llegue a la ins-
tancia de Amazon EC2. Estas instancias tienen mayor rendimiento de E/S, lo
que implica una menor utilización de la CPU.

2)�Elección�de�región

Muchos servicios de AWS, como Amazon EC2, están disponibles en múltiples


ubicaciones en todo el mundo. Estas áreas geográficamente separadas se de-
nominan Regiones AWS. En el momento de diseñar la arquitectura de la apli-
cación, se pueden elegir una o más regiones dependiendo de los requisitos. En
cada región, AWS proporciona acceso a un conjunto único de conexiones a
internet y relaciones de peering que permiten una latencia adecuada a los usua-
rios finales que se sitúan cerca de la región. También es importante considerar
la elección de la región en términos de flexibilidad DDoS. Muchas regiones es-
tán más cerca de los grandes intercambios de internet. Muchos ataques DDoS
se orquestan internacionalmente, por lo que es útil estar cerca de los puntos de
intercambio, ya que esto ayuda a los usuarios finales a alcanzar la aplicación.

3)�Balanceo�de�carga

Los ataques DDoS más grandes pueden superar el tamaño de una única ins-
tancia de Amazon EC2. Al mitigar estos ataques, hay que considerar opciones
para balancear la carga. Con Elastic Load Balancing (ELB) se puede reducir el
riesgo de sobrecarga de la aplicación mediante la distribución de tráfico entre
muchas instancias de backend. ELB puede balancear automáticamente, lo que
le permite gestionar grandes volúmenes de tráfico, como los volúmenes resul-
tantes de los ataques DDoS.

ELB solo acepta conexiones TCP bien formadas. Esto significa que muchos de
los ataques DDoS, como inundaciones SYN o ataques de reflexión UDP, no
serán aceptados por ELB. Cuando ELB detecta estos tipos de ataques, escala
automáticamente para absorber el tráfico adicional.

4)�Entrega�a�escala�mediante�AWS�Edge�Locations
© FUOC • PID_00241999 32 Introducción a la seguridad en cloud computing

El acceso a conexiones de internet muy escaladas y diversas aumenta la capa-


cidad para optimizar la latencia y el rendimiento a los usuarios finales, para
absorber ataques de DDoS y para aislar las fallas mientras se minimiza el im-
pacto de la disponibilidad. AWS Edge constituye una capa adicional de infra-
estructura de red que proporciona beneficios a las aplicaciones web que utili-
zan también Amazon CloudFront y Amazon Route53.

Con estos servicios, el contenido se sirve y las consultas DNS se resuelven des-
de ubicaciones que a menudo están más cerca de sus usuarios finales. Ama-
zon CloudFront es un servicio de red de distribución de contenido (CDN) que
se puede utilizar para entregar todo el sitio web, incluido contenido estático,
dinámico, de transmisión e interactivo. Las conexiones TCP persistentes y el
tiempo de vida variable (TTL) se pueden utilizar para acelerar la entrega de
contenido, incluso si no se puede almacenar en caché. Esto permite usar Ama-
zon CloudFront para proteger una aplicación web, incluso si no se está sirvien-
do contenido estático. Amazon CloudFront solo acepta conexiones bien for-
madas para evitar que muchos ataques DDoS comunes –como inundaciones
SYN y ataques de reflexión UDP– lleguen a tu origen. Los ataques DDoS están
geográficamente aislados cerca de la fuente, lo que evita que el tráfico afecte
a otras ubicaciones. Estas capacidades pueden mejorar considerablemente la
capacidad para seguir sirviendo tráfico a los usuarios finales durante ataques
DDoS mayores. Se puede utilizar Amazon CloudFront para proteger un origen
en AWS o en cualquier otro lugar de internet.

5)�Resolución�de�nombres�de�dominio

Amazon Route 53 es un servicio de nombres de dominio (DNS) altamente dis-


ponible y escalable que se puede utilizar para dirigir tráfico a una aplicación
web. Incluye muchas características avanzadas, como flujo de tráfico, enruta-
miento basado en latencia, Geo DNS, comprobaciones de estado y supervisión.
Estas características permiten controlar cómo responde el servicio a las peti-
ciones DNS para optimizar la latencia. Amazon Route 53 usa Shuffle Sharding
y Anycast Striping para que los usuarios finales puedan acceder a la aplicación,
incluso si el servicio DNS es atacado por un ataque DDoS. Con Shuffle Shar-
ding, cada servidor de nombres en su conjunto de delegaciones corresponde
a un conjunto único de ubicaciones y rutas de internet. Esto proporciona una
mayor tolerancia a fallos y minimiza la superposición entre clientes. Si un
servidor de nombres en el conjunto de delegaciones no está disponible, los
usuarios finales pueden volver a intentarlo y recibir una respuesta de otro ser-
vidor de nombres en una ubicación diferente. Anycast Striping se utiliza para
que cada petición de DNS se sirva desde la ubicación más rápida. Esto tiene el
efecto de extender la carga y reducir la latencia del DNS, lo que permite a los
usuarios finales recibir una respuesta más rápida. Además, Amazon Route 53
puede detectar anomalías en la fuente y el volumen de las consultas DNS, y
priorizar las peticiones de los usuarios que se sabe que son fiables.
© FUOC • PID_00241999 33 Introducción a la seguridad en cloud computing

Defensa de capa de aplicación

1)�Detectar�y�filtrar�peticiones�web�malintencionadas

Los cortafuegos de aplicaciones web (WAF) se utilizan para proteger aplicacio-


nes web contra ataques que intentan explotar una vulnerabilidad en la apli-
cación. Los ejemplos más comunes incluyen la inyección SQL o el cross-site
scripting. También se puede utilizar un WAF para detectar y mitigar los ataques
DDoS de la capa de aplicación web.

En AWS, se puede utilizar Amazon CloudFront y AWS WAF para defender una
aplicación contra estos ataques. Amazon CloudFront permite almacenar en ca-
ché estática el contenido y servirlo desde AWS Edge Locations. Además, Ama-
zon CloudFront puede cerrar automáticamente conexiones de lectura lenta o
ataques de escritura lenta. Se puede utilizar la restricción geográfica Amazon
CloudFront para bloquear ataques que se originen desde ubicaciones geográ-
ficas donde no se espera servir a los usuarios finales.

Puede ser difícil identificar la firma de un ataque DDoS o identificar las di-
recciones IP que están participando en el ataque. Se puede utilizar la consola
AWS WAF para ver una muestra de las peticiones que Amazon CloudFront ha
enviado a AWS WAF. Algunos ataques consisten en tráfico web que se disfraza
para parecer tráfico procedente de un usuario final. Para mitigar este tipo de
ataque, se puede utilizar una función AWS Lambda para implementar listas
negras basadas en una tasa. Si un bot o crawler excede este límite, se puede
utilizar AWS WAF para bloquear automáticamente futuras peticiones.

2)�Escala�para�absorber

Otra forma de hacer frente a los ataques en la capa de aplicación es escalar. En


el caso de las aplicaciones web, se puede utilizar ELB para distribuir instancias
EC2 sobreprovisionadas o configuradas para escalar automática con el objeti-
vo de atender los aumentos de tráfico, que pueden ser resultado de un ataque
DDoS en la capa de aplicación. Las alarmas de Amazon CloudWatch se utilizan
para iniciar el Auto Scaling, que escalona automáticamente el tamaño de la
flota de Amazon EC2 en respuesta a eventos previamente definidos. Esto pro-
tege la disponibilidad de las aplicaciones incluso cuando se está tratando un
volumen inesperado de peticiones. Mediante el uso de Amazon CloudFront
o ELB, la negociación SSL es manejada por el balanceador de carga, lo que
puede impedir que sus instancias se vean afectadas por ataques que exploten
vulnerabilidades SSL.
© FUOC • PID_00241999 34 Introducción a la seguridad en cloud computing

Ofuscación de los recursos AWS

Otra consideración importante al diseñar en AWS es limitar las oportunidades


que un atacante pueda tener para aprender de la aplicación. Por ejemplo, si
no se espera que un usuario final interactúe directamente con ciertos recursos,
estos recursos no deben ser accesibles desde internet.

Del mismo modo, si no se espera que los usuarios finales o las aplicaciones
externas se comuniquen con la aplicación en ciertos puertos o protocolos,
ese tipo de tráfico debería no ser aceptado. Este concepto se conoce como
reducción de la superficie de ataque.

Para muchas aplicaciones, los recursos AWS no necesitan estar completamente


expuestos a internet. Por ejemplo, puede no ser necesario para las instancias
de Amazon EC2 detrás de un ELB ser accesibles al público. En este escenario,
se puede permitir a los usuarios finales acceder al ELB en ciertos puertos TCP
y permitir que solo el ELB pueda comunicarse con las instancias de Amazon
EC2. Esto puede lograrse configurando grupos de seguridad y listas de control
de acceso a la red (NACL) dentro de Amazon Virtual Private Cloud (VPC).
Amazon VPC le permite proveer una sección lógicamente aislada de la nube
de AWS donde lanzar recursos de AWS en una red virtual que defina.

Los grupos de seguridad y las ACL de red son similares, ya que permiten con-
trolar el acceso a los recursos de AWS dentro de una VPC. Los grupos de segu-
ridad permiten controlar tráfico entrante y saliente a nivel de instancia, y la
ACL de red ofrece capacidades similares, pero a nivel de subred VPC.

1)�Grupos�de�seguridad

Se pueden especificar grupos de seguridad al iniciar una instancia. Todo el trá-


fico desde internet en un grupo de seguridad se niega implícitamente a menos
que se cree una regla para permitir el tráfico. Por ejemplo, si consideramos
una aplicación web que consiste en un ELB y varias instancias Amazon EC2,
se podría crear un grupo de seguridad para el ELB (Grupo de seguridad ELB) y
uno para las instancias (Grupo de seguridad servidor de aplicaciones web). A
continuación, se pueden crear permisos para permitir el tráfico desde internet
para el grupo de seguridad ELB y para permitir el tráfico del Grupo de seguri-
dad ELB al servidor de aplicaciones web. Como resultado, el tráfico en internet
no puede comunicarse directamente con sus instancias de Amazon EC2, lo
que hace más difícil para un atacante aprender acerca de una aplicación.

2)�Listas�de�control�de�acceso�a�la�red

Esta herramienta es útil cuando se responde a ataques DDoS porque puede


permitir crear reglas para mitigar el ataque si conoce la dirección IP origen.
Con las ACL de red, se pueden especificar las reglas de permitir y denegar.
Esto resulta útil en caso de que se deseen negar explícitamente ciertos tipos de
© FUOC • PID_00241999 35 Introducción a la seguridad en cloud computing

tráfico a la aplicación. Por ejemplo, puede definir direcciones IP (como rangos


CIDR), protocolos y puertos de destino que se deben denegar para toda una
subred. Si una aplicación utiliza solo tráfico TCP, se puede crear una regla para
denegar todo el tráfico UDP o viceversa.

3)�Protección�basada�en�el�origen�de�las�peticiones

Si se está utilizando Amazon CloudFront con un origen que se encuentra den-


tro de una VPC, se puede utilizar una función AWS Lambda para actualizar
automáticamente las reglas del grupo de seguridad asociado con el fin de per-
mitir solo el tráfico de Amazon CloudFront. Esto obliga a las peticiones a ser
procesadas por Amazon CloudFront y AWS WAF.

4)�Protección�de�los�puntos�finales�de�API

Normalmente, cuando existe la necesidad de exponer una API al público, apa-


rece el riesgo de que el interfaz API pueda ser atacado por un ataque DDoS.
Amazon API Gateway es un servicio totalmente administrado que permite
crear una API que actúa como una «puerta de entrada» a aplicaciones que se
ejecutan en Amazon EC2, AWS Lambda o cualquier aplicación web.

Con Amazon API Gateway, no es necesario que ejecute sus propios servidores
para la API, y se pueden ocultar otros componentes de la aplicación al acceso
público. Esto ayuda a evitar que los recursos de AWS sean atacados mediante
un DDoS. Amazon API Gateway está integrado con Amazon CloudFront, lo
que permite beneficiarse de la capacidad adicional de DDoS que es inherente
a ese servicio. También se puede proteger el backend del exceso de tráfico con-
figurando límites de velocidad estándar o de ráfaga para cada método para las
API de tipo REST.

3.2. Caso Digital Ocean

Digital�Ocean es un proveedor estadounidense de servidores virtuales priva-


dos. La compañía alquila servidores de sus centros de datos, a los que llama
droplets. Aprovechando que se trata de un proveedor muy simple, en este caso
de uso se explicarán los conceptos de seguridad básica práctica aplicados al
entorno de Digital Ocean.

3.2.1. Claves SSH

Las claves SSH son un par de claves criptográficas con las que se puede au-
tenticar contra un servidor SSH como una alternativa a los logins basados en
contraseña. Con anterioridad a la autentificación se han creado un par de cla-
ves, una privada y una clave pública. La clave privada se mantiene secreta y
asegurada por el usuario, mientras que la clave pública puede ser compartida
con cualquiera.
© FUOC • PID_00241999 36 Introducción a la seguridad en cloud computing

Para configurar la autenticación SSH, hay que colocar la clave pública del usua-
rio en el servidor en un directorio específico. Cuando el usuario conecta al
servidor, el servidor comprobará que el cliente tiene la clave privada asociada.
El cliente SSH utilizará la clave privada para responder en una manera que
pruebe la propiedad de la clave privada. Entonces, el servidor permite al clien-
te conectar sin el uso de una contraseña.

Mediante el uso de SSH, cualquier clase de autenticación, incluyendo auten-


ticación bajo contraseña, es completamente encriptada. Aun así, cuando el
servidor permite el uso de contraseñas, un usuario malicioso podría intentar
acceder al servidor repetidamente. Con la capacidad actual de cómputo, es
posible obtener acceso a un servidor mediante la automatización de estos in-
tentos probando diferentes combinaciones de contraseñas hasta encontrar la
correcta.

La instalación de la autenticación de claves SSH permite deshabilitar la auten-


ticación basada en contraseñas. Generalmente, las claves SSH tienen muchos
más bits de datos que una contraseña, lo que significa que hay muchas más
combinaciones posibles que un atacante tendría que ejecutar para ganar acce-
so al sistema. Muchos algoritmos de clave SSH se consideran no hackeables por
el hardware de computación actual simplemente porque requerirían demasia-
do tiempo para computar las diferentes posibilidades.

Las claves SSH son muy fáciles de instalar y es la forma recomendable de re-
gistrarse en cualquier entorno de servidor Linux o Unix de modo remoto. Un
par de claves SSH se pueden generar en la máquina del usuario y puede trans-
ferirse la clave pública a sus servidores en unos minutos mediante un gestor
de configuración.

En el caso de tener que utilizar autenticación mediante contraseña, existe la


posibilidad de implementar una solución como fail2ban en los servidores para
limitar los intentos de acceso fraudulentos.

3.2.2. Cortafuegos

Un cortafuegos es un dispositivo software que controla qué servicios están


expuestos a la red. Esto significa bloquear o restringir el acceso a cada puerto,
excepto aquellos que tengan que estar públicamente disponibles.

En un servidor típico, los servicios pueden ser categorizados en los siguientes


grupos:

• Servicios públicos a los que puede acceder cualquier persona en internet, a


menudo de forma anónima. Un buen ejemplo de esto es un servidor web.
© FUOC • PID_00241999 37 Introducción a la seguridad en cloud computing

• Servicios privados que solo tendrían que ser accedidos por un grupo de
cuentas autorizadas o sitios seguros. Un ejemplo de esto puede ser un panel
de base de datos.

• Servicios internos que tendrían que ser accesibles solo desde dentro del
propio servidor, sin exponer el servicio al mundo exterior. Por ejemplo,
puede tratarse de una base de datos que solo acepta conexiones locales.

Un cortafuegos puede garantizar que el acceso a un determinado servicio esté


restringido según las categorías anteriores. Los servicios públicos pueden de-
jarse abiertos y estar disponibles para todos, y los servicios privados pueden
restringirse basándose en criterios diferentes. Los servicios internos pueden
ser completamente inaccesibles al mundo exterior. Para los puertos que no se
utilizan, el acceso se bloquea completamente.

La configuración del cortafuegos es una parte esencial de la configuración de


un servidor; incluso si los servicios instalados implementan características de
seguridad o están restringidos a las interfaces de red correspondientes, un cor-
tafuegos provee de una capa adicional de protección.

Un cortafuegos correctamente configurado restringirá el acceso a todo excepto


a los servicios específicos que se necesita que permanezcan abiertos. Exponer
solo unos pocos servicios reduce la superficie de ataque de un servidor, limi-
tando los componentes vulnerables a la explotación.

Hay muchos cortafuegos disponibles para sistemas Linux, algunos de los cua-
les tienen una curva de aprendizaje más pronunciada que otros. Por lo gene-
ral, la instalación del cortafuegos solo tardaría unos minutos y solo tendrá que
pasar por un servidor de configuración inicial o cuando realice cambios en los
servicios.

3.2.3. VPN y redes privadas

Las redes privadas son redes que solo son visibles dentro de la red que forman
nuestros servidores.

Para conectar equipos remotos a una red privada, se utiliza una VPN, o red
privada virtual, que es una forma de crear conexiones seguras entre equipos
remotos y presentar la conexión como una red privada local. Esto proporciona
una forma de configurar los servicios como en una red privada y de conectar
servidores remotos a través de conexiones seguras.

El uso de una VPN es efectivamente una forma de mapear una red privada
que solo los usuarios pueden ver. La comunicación será totalmente privada y
segura. Otras aplicaciones se pueden configurar para pasar el tráfico a través
© FUOC • PID_00241999 38 Introducción a la seguridad en cloud computing

de la interfaz virtual expuesta por el software VPN. De esta manera, los únicos
servicios se exponen públicamente son los servicios que están destinados a ser
accedidos por los usuarios a través de internet.

El uso de redes privadas en un centro de datos que tenga esta capacidad es


fácil: basta con habilitar la interfaz privada durante la creación de configura-
ciones de servidores y aplicaciones, y configurar el cortafuegos para usar la red
privada.

En cuanto a VPN, la configuración inicial resulta un poco más complicada,


pero la seguridad aumenta considerablemente, por lo que es la opción reco-
mendada para la mayoría de los casos de uso. Cada servidor en una VPN ne-
cesita instalar y configurar los datos comparativos de seguridad y configura-
ción necesarios para establecer la conexión segura. Después de que la VPN esté
funcionando, las aplicaciones deben configurarse para usar el túnel VPN.

3.2.4. Infraestructura de clave pública y SSL/TLS encriptación

La infraestructura de clave pública, o PKI, se refiere a un sistema diseñado para


crear, dirigir y validar certificados para identificar comunicaciones individua-
les y de cifrado. Los certificados SSL o TLS pueden ser auténticos y diferentes.
Después de la autenticación, la comunicación establecida también puede en-
criptarse usando los mismos certificados.

Establecer una autoridad de certificación y los certificados de los administra-


dores de los servidores de cada entidad dentro de la infraestructura sirve para
validar la otra identidad de los miembros y cifrar el tráfico. Asimismo, puede
evitar el ataque a las comunicaciones en el que un atacante imita ser un ser-
vidor de la infraestructura para interceptar tráfico.

Cada servidor puede configurarse para confiar en una autoridad de certifica-


ción centralizada. A continuación, se puede confiar implícitamente en cual-
quier certificado que señale la autoridad. Encriptación TLS / SSL es una mane-
ra de encriptar el sistema sin utilizar una VPN (que también SSL utiliza inter-
namente).

Hay que configurar la autoridad de certificación e instalar el resto de la infraes-


tructura. Además, dirigir los certificados crea una nueva necesidad de gestión
de los certificados que deben crearse, firmarse o revocarse.

Implementar una infraestructura de clave pública tiene sentido en infraestruc-


turas grandes. Asegurar las comunicaciones entre los componentes que usan
VPN puede ser una buena estrategia hasta que alcance el punto en el que la
PKI valga la pena los costes de administración adicionales.
© FUOC • PID_00241999 39 Introducción a la seguridad en cloud computing

3.2.5. Auditoría de archivo y archivo de sistemas de detección

La auditoría de intrusión es el proceso de comparar el sistema actual de un


registro de los archivos y los archivos del sistema cuando se encontraban en
buen estado. Por lo general, detecta cambios en el sistema que pueden no
haber sido autorizados.

Esta estrategia es una manera de asegurarse de que el sistema de archivos no


ha sido alterado por ningún usuario o proceso. A menudo, los intrusos quie-
ren permanecer ocultos para seguir explotando el servidor durante un periodo
prolongado de tiempo. Estos podrían reemplazar binarios con versiones com-
prometidas. Hacer una auditoría del sistema de archivos para saber si alguno
de los archivos ha sido alterado asegura la integridad del entorno del servidor.

La realización de auditorías de archivo puede ser un proceso muy intenso. La


configuración inicial implica la auditoría del sistema sobre cualquier cambio
no estándar realizado en el servidor y la definición de rutas que deberían ser
excluidas para crear una base de lectura.

También hace que las operaciones diarias sean más complicadas. Complica los
procedimientos de actualización cuando sea necesario para volver a compro-
bar el sistema antes de ejecutar actualizaciones y reconstruir la baseline des-
pués de ejecutar la actualización. También es necesario descargar los informes
a otra ubicación para que un atacante no pueda alterar la auditoría.

Si bien esto puede aumentar la carga de la administración, ser capaz de com-


probar el sistema asegura que los archivos no han sido alterados. Algunos sis-
temas populares de detección son Tripwire y Aide.

3.2.6. Entornos de ejecución aislada

Aislar entornos de ejecución se refiere a cualquier método en el que compo-


nentes individuales se están ejecutando dentro de un espacio dedicado.

Esto puede significar separar los componentes de aplicación en servidores pro-


pios o puede referirse a configurar los servicios para operar en entornos chroot
o contenedores. El nivel de aislamiento depende fuertemente de los requisitos
de cada aplicación.

Aislar los procesos en entornos de ejecución individual aumenta la capacidad


de aislar cualquier problema de seguridad que pueda surgir. Separar los com-
ponentes individuales puede limitar el acceso que un intruso tiene a otras pie-
zas de la infraestructura.
© FUOC • PID_00241999 40 Introducción a la seguridad en cloud computing

Dependiendo del tipo de aislamiento, aislar una aplicación puede ser una tarea
relativamente sencilla. Paquetizar los componentes individuales en contene-
dores es una manera, pero curiosamente Docker no considera su aislamiento
una medida de seguridad.

Instalar un chroot en el entorno para cada pieza software también puede pro-
porcionar un cierto nivel de aislamiento, pero cabe recordar que hay maneras
de romper el chroot incluso para aplicaciones que se encuentra dentro de este
tipo de aislamiento.
© FUOC • PID_00241999 41 Introducción a la seguridad en cloud computing

4. Caso de uso II: Seguridad en entornos PaaS privados


basados en Docker

Docker es una plataforma que nos permite construir y ejecutar aplicaciones


distribuidas basadas en contenedores. Esta nueva forma de trabajar está cam-
biando el paradigma del desarrollo de aplicaciones, ya que se pasa de aplica-
ciones monolíticas a aplicaciones basadas en microservicios. Muchas de las
grandes empresas, como Google o Spotify, e infinidad de start ups recurren a
esta arquitectura, afrontando nuevos retos en cuanto a seguridad se refiere.

Conceptualmente, cada aplicación bajo contenedores dockers debe aislarse de


cualquier otra aplicación, limitando y controlando los recursos a los que estos
pueden acceder mediante capacidades heredadas del host, como namespaces
y cgroups.

Docker ofrece seguridad basada en capas; por defecto estos ya incorporan mé-
todos de aislamiento, pero debemos recordar que Docker es una plataforma
que puede ejecutarse en máquinas virtuales y añadir una capa suplementaria
en el caso de requerir un aislamiento extra.

Para definir cómo securizar un entorno dockerizado, no existe un protocolo


infalible, sino que procederemos a seguir un conjunto de recomendaciones
para mitigar y dificultar cualquier ataque recibido.

Entre los ataques más comunes con los que deberemos tener especial atención
encontraremos:

• Ataques Conainer�scape, escalado de privilegios en el host.


• Ataque Root/Kernel�exploit, host comprometido.
• Ataque DOS (denial of service), pérdida de disponibilidad.
• Ataque Software�&�Crypto�exploit, pérdida de confidencialidad.

4.1. Seguridad en el host

Para definir la seguridad de nuestras aplicaciones dockerizadas, primero debe-


remos centrarnos en la raíz, donde estos se ejecutarán.

Seguiremos algunas recomendaciones que afectarán a distintos ámbitos del


sistema anfitrión:

1)�Uso�de�imágenes�validadas
© FUOC • PID_00241999 42 Introducción a la seguridad en cloud computing

Durante la construcción de nuestros contenedores es común el uso de conte-


nedores de terceros como punto de partida; la recomendación más clara es
la de usar repositorios validados, ya que cualquier fuente no confiable puede
exponer nuestro contenedor a numerosas vulnerabilidades.

2)�Securización�del�kernel�de�Linux

Es recomendable aplicar los parches de Grsecurity (grsecurity.net), que ofrecen


una mejora de seguridad para el kernel de Linux, incorporando entre otros me-
canismos ante amenazas de seguridad un control de acceso inteligente y con-
troles de prevención de vulnerabilidades basadas en corrupción de memorias.

3)�Recursos�del�sistema�con�ulimit

Linux incorpora el comando ulimit, encargado de obtener y modificar los lí-


mites de los recursos del usuario; con él podremos limitar el número máximo
de ficheros abiertos o el número máximo de procesos que los contenedores
podrán manejar por usuario. Por otro lado, Docker también incorpora meca-
nismos para definir estos valores mediante el uso de parámetros con la misma
nomenclatura (ulimit).

Con la limitación del número de recursos con ulimit estableceremos valores


máximos para los contenedores, pero recordad que otras aplicaciones como
Apache o Nginx disponen de parámetros extra para establecer distintos límites
dentro de ellos.

Podremos definir distintos tipos de limitaciones, de manera global o local para


contenedores. A continuación mostraremos distintos ejemplos de configura-
ción de máximo de ficheros abiertos y de procesos activos:

a) Estableciendo límites durante el arranque del demonio de Docker:

docker daemon --default-ulimit nofile=100:200

El parámetro nofile define los valores máximos de la siguiente forma <soft


limit>[:<hard limit>]. Diferenciaremos el soft limit y el soft limit: el soft limit
es lo que realmente se aplica para una sesión o proceso, permitiendo al admi-
nistrador (o usuario) establecer el límite máximo requerido; el hard limit es
un campo opcional y define el límite máximo para el parámetro definido de
soft limit.

b) Modificando el fichero /etc/security/limits.conf:

docker soft nofile <max_soft_limit>


docker hard nofile <max_hard_limit>
© FUOC • PID_00241999 43 Introducción a la seguridad en cloud computing

c) Mediante la sobreescritura de los valores de límites por defecto en el mo-


mento de la ejecución de un contenedor específico, limitando el número de fi-
cheros máximos abiertos mediante el parámetro --ulimit nofile o establecien-
do el número máximo de procesos abiertos por el contendor:

docker run --name <nombre container> --ulimit nofile=<soft limit>:<hard limit> ...

docker run --name <nombre container> --ulimit nproc=<soft limit>:<hard limit> ...

d) Estableciendo las opciones oportunas dentro del fichero de configuración


de Docker /etc/sysconfig/docker:

OPTIONS="--ulimit nofile=<soft limit>:<hard limit> --ulimit nproc=<soft limit>:<hard limit>"

O en el fichero /etc/systemd/system/docker.service.d:

[Service]
Environment="OPTIONS=$OPTIONS \"--default-ulimit nofile=<soft limit>:<hard limit>\""
Environment="OPTIONS=$OPTIONS \"--default-ulimit nproc=<soft limit>:<hard limit>\""

Después de agregar o modificar un archivo deberemos ejecutar el comando Nota


systemctl daemon-reload para indicar a systemd que vuelva a cargar la confi-
Los valores ulimit especificados
guración del servicio. para un contenedor sobrescri-
ben los valores predetermina-
dos que establecidos para el
4)�Namespaces daemon.

Los espacios de nombres son una característica del kernel de Linux que aísla y
virtualiza los recursos del sistema de una colección de procesos.

Los contenedores Docker son muy similares a los contenedores LXC y tie-
nen características de seguridad similares. Cuando se inicia un contenedor con
Docker se crean un conjunto de espacios de nombres y grupos de control para
el contenedor.

Los espacios de nombres proporcionan la primera y más sencilla forma de


aislamiento: los procesos que se ejecutan dentro de un contenedor no pueden
ver los procesos que se ejecutan en otro contenedor o en el sistema host.

Para remapear nuestro usuario con otro usuario con su propio identificador
dentro del contenedor, ejecutaremos:

docker daemon --userns-remap=<nombre_usuario>

Esta instrucción tomará el identificador del <usuario> dentro del host y lo re-
mapeará dentro del contenedor siguiendo la fórmula:
© FUOC • PID_00241999 44 Introducción a la seguridad en cloud computing

FIRST_SUB_UID = 100000 + (UID - 1000) * 65536

Por ejemplo, si nuestro usuario en el host está definido por usua-


rio::100000:65536, al ejecutar el remap podremos encontrar que dentro del
contenedor corresponderá con usuario:1000:1

5)�Capabilities

Las capabilities definen un sistema de seguridad que permite «fragmentar»


los privilegios de root en distintos componentes, y estos podrán ser asignados
de forma individual a procesos que requieran de privilegios especiales para
recursos específicos sin necesidad de poseer privilegios de superusuario.

Docker utiliza esta granulación de privilegios para restringir los accesos a re-
cursos, definiendo a qué capas podrá tener acceso el contenedor.

Para definir un acceso global a los recursos, aunque no recomendable, se uti-


lizará la instrucción:

A menudo es necesario exponer directamente los dispositivos a un contenedor.


La opción que utilizaremos será --device, que permitirá vincular el contenedor
con dispositivos de almacenamiento específicos o dispositivos de audio sin
poseer privilegios de root:

Por defecto, el contenedor podrá leer (read), escribir (write) y mknod sobre es-
tos dispositivos. Estos privilegios pueden ser sobreescritos mediante las opcio-
nes :rwm para cada etiqueta device:

#Permisos de lectura/escritura esplicito


docker run --device=/dev/sda:/dev/xvdc:rw --rm -it ubuntu fdisk /dev/xvdc

6)�Módulos�de�seguridad�(AppArmor)
© FUOC • PID_00241999 45 Introducción a la seguridad en cloud computing

Tanto AppArmor (Application Armor) como SeLinux son módulos de seguri-


dad de Linux que protegen un sistema operativo y sus aplicaciones contra
amenazas de seguridad.

Para utilizar AppArmor, un administrador del sistema asocia un perfil de segu-


ridad AppArmor para cada programa. Así pues, Docker espera encontrar una
política de AppArmor cargada y aplicada para limitar la aplicación dockeriza-
da. El binario Docker instala un perfil predeterminado de AppArmor en el ar-
chivo /etc/apparmor.d/docker, y este perfil se utilizará en los contenedores, no
en el Docker Daemon.

7)�Computación�segura�o�Seccomp

El modo de computación segura (Seccomp) es una característica del kernel de


Linux. Se utiliza para restringir las acciones disponibles dentro del contenedor.
La llamada al sistema seccomp () opera en el estado de la llamada seccomp, y
se puede usar esta función para restringir el acceso de la aplicación.

Esta función solo está disponible si Docker se ha creado con seccomp y el


núcleo está configurado con CONFIG_SECCOMP habilitado. Para comprobar
si el kernel es compatible con seccomp, ejecutaremos:

cat /boot/config-`uname -r` | grep CONFIG_SECCOMP=


CONFIG_SECCOMP=y

El perfil de seccomp predeterminado deshabilita en torno a 44 llamadas de sis-


tema de más de 300 disponibles. Es moderadamente protector mientras pro-
porciona una amplia compatibilidad de aplicaciones. El perfil predeterminado
de Docker tiene un diseño JSON y puede sobreescribirse mediante:

docker run --rm -it --security-opt seccomp=/path/to/seccomp/profile.json hello-world

Donde profile.json sería un fichero JSON siguiendo la siguiente estructura:

{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
"name": "accept",
"action": "SCMP_ACT_ALLOW",
"args": []
},
© FUOC • PID_00241999 46 Introducción a la seguridad en cloud computing

{
"name": "accept4",
"action": "SCMP_ACT_ALLOW",
"args": []
},
...
]
}

Os recomendamos la lectura de la documentación oficial para la especificación


de todas aquellas llamadas al sistema disponibles.

8)�Limitación�de�CPU

En algunos entornos nos interesará la limitación del uso de la CPU del host
para protegerlo frente a ataques que intenten vulnerar las capacidades del pro-
cesador anfitrión; para ello, Docker dispone de opciones de configuración es-
pecíficas:

a)�--cpu-shares <int>

Limitación relativa a la cantidad de procesadores disponibles, se especifica en


porcentaje.

b)�--cpu-quota <int>

Limitación del uso de la CPU en el contenedor. El valor 0 predeterminado


permite que el contenedor tome el 100 % de un recurso de CPU (1 CPU). Para
limitar el uso del procesador al 50 %, estableceremos un valor de cuota de
50000.

#Límite del uso de la CPU al 50%


docker run -ti --cpu-quota=50000 ubuntu:latest /bin/bash.

c)�--cpu-period <int>

Esta opción se utiliza para establecer el periodo de CPU y limitar el uso de la


CPU del contenedor. El periodo por defecto de CPU CFS es de 100 ms. Usual-
mente --cpu-period funciona junto con la opción --cpu-quota.

#Limitación del 50% de la CPU cada 50ms


docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:14.04 /bin/bash

d)�--cpuset-cpus <string>
© FUOC • PID_00241999 47 Introducción a la seguridad en cloud computing

Permite la restricción del uso de determinados CPU de nuestro host, que se


especificarán en formato «1,3» en el caso de querer utilizar solo 2 CPU (número
1 y 3) o con el formato «0-2» para indicar que usaremos un rango (uso de CPU
0, 1 y 2).

9)�Limitación�de�RAM

En Docker, o en cualquier otro sistema contenedor, la memoria es adminis-


trada por el kernel que ejecuta Docker y los contenedores. El proceso que se
ejecuta en el contenedor sigue funcionando como un proceso normal pero en
un cgroup diferente, donde cada cgroup posee sus propios límites, como la
cantidad de memoria que el kernel entregará al espacio del usuario o, como ya
hemos visto, qué dispositivos tendrá disponibles.

Para especificar las limitaciones oportunas, usaremos las opciones de ejecución


de la familia --memory de docker:

a)�--memory <int>[<unidad (b, k, m o g)>]

Para definir la cantidad de memoria máxima que el contenedor tendrá dispo-


nible se indicará en forma de número entero positivo la cantidad de memoria
seguido de la unidad correspondiente (b, k, m o g). El mínimo de memoria
es de 4 M.

#Limitación de la memoria a 1Gb


docker run --memory 1G ubuntu

b)�--memory-reservation <int>[<unidad (b, k, m o g)>]

Se utiliza normalmente en conjunción con la instrucción --memory. En el ca-


so de especificar ambos parámetros, la memoria (especificada con opción --
memory) debe ser mayor que la memoria reservada. Al especificar una canti-
dad de memoria reservada, el contenedor inicia con el valor reservado; de lo
contrario, utilizará el valor de la memoria asignada.

Por ejemplo, si un contenedor normalmente utiliza 256 Mb de memoria, pero


ocasionalmente requiere 512 Mb de memoria por periodos cortos de tiempo,
podemos establecer una reserva de memoria de 256 Mb y un límite de memo-
ria de 600 Mb, estableciendo así los dos ámbitos donde la memoria del conte-
nedor puede ubicarse.

El mínimo de memoria reservada es de 4 M.

#Reserva de memoria inicial de 256Mb con limite de 600Mb


docker run --memory 600M --memory-reservation 256M ubuntu
© FUOC • PID_00241999 48 Introducción a la seguridad en cloud computing

c)�--memory-swap <int>[<unidad (b, k, m o g)>]

Los contenedores pueden hacer uso de la memoria SWAP, que amplía los lími-
tes de la memoria RAM establecida por el parámetro –memory. Se establece así
el uso total de memoria como memoria + memoria SWAP asignada.

d)�--memory-swappiness <int>

Existe la posibilidad de ajustar la frecuencia con la que se utilizan los ficheros


de intercambio del contenedor con valores de 0 a 100. Los valores bajos indi-
carán que no se utilizará memoria SWAP a menos que sea totalmente necesa-
rio. Por otro lado, los valores altos indicarán un uso exhaustivo de este tipo
de memoria.

10)�Redes

Cada contenedor Docker tiene su propia pila de red, lo que significa que un
contenedor no obtiene acceso privilegiado a los sockets o interfaces de otro
contenedor, aunque esto es posible si el sistema host está configurado para
ello, e incluso interactuar con hosts externos.

Cuando se especifica un puerto público para el contenedor o se utilizan víncu-


los, se permite el tráfico IP entre contenedores, es decir, pueden hacer ping
unos a otros, enviar/recibir paquetes UDP y establecer conexiones TCP.

Desde el punto de vista de la arquitectura de red, todos los contenedores de un


host Docker determinado están situados en interfaces de puente (bridge). Esto
significa que son como máquinas físicas conectadas a través de un conmutador
ethernet común.

4.2. Buenas prácticas de seguridad

La seguridad de los sistemas es una cuestión bien tratada por los propios con-
tenedores, y es el propio Docker el que está centrando cada vez más esfuerzos
en mejorar los sistemas integrados de seguridad de estos. No obstante, para
comprobar que nada quede en el descuido, incluimos un listado de noventa
buenas prácticas desarrolladas por el Center for Internet Security (CIS) para
Docker, que se podrán seguir a modo de checklist.

1. Configuración del host


© FUOC • PID_00241999 49 Introducción a la seguridad en cloud computing

1.1. Crear una partición separada para los contenedores


1.2. Uso del kernel de Linux actualizado
1.3. No utilizar herramientas de desarrollo en producción
1.4. Securizar el host anfitrión del contenedor
1.5. Eliminar todos los servicios no esenciales del host
1.6. Mantener Docker actualizado
1.7. Solo permitir que los usuarios de confianza controlen el daemon de Docker
1.8. Aplicar técnicas de auditoría sobre el daemon Docker
1.9. Auditar archivos y directorios de Docker - /var/ lib/docker
1.10. Auditar archivos y directorios de Docker - /etc/docker
1.11. Auditar archivos y directorios de Docker - docker-registry.service
1.12. Auditar archivos y directorios de Docker - docker.service (marcado)
1.13. Auditar archivos y directorios de Docker - /var/run/docker.sock
1.14. Auditar archivos y directorios de Docker - /etc/sysconfig/docker
1.15. Auditar archivos y directorios de Docker - /etc/sysconfig/docker-network
1.16. Auditar archivos y directorios de Docker - /etc/sysconfig/docker-registry
1.17. Auditar archivos y directorios de Docker - /etc/sysconfig/docker-storage
1.18. Auditar archivos y directorios de Docker - /etc/default/docker

2. Configuración del daemon de Docker

2.1. No utilizar el controlador de ejecución lxc


2.2. Limitar el tráfico de red entre contenedores
2.3. Establecer el nivel adecuado de logging
2.4. Permitir que Docker realice cambios en iptables
2.5. No utilizar registros inseguros (sin TLS)
2.6. Configurar un espejo del registro local
2.7. No utilizar aufs como controlador de almacenamiento
2.8. No vincular Docker a otro puerto IP o un socket Unix
2.9. Configurar la autenticación TLS para el daemon Docker
2.10. Establecer el valor predeterminado ulimit según corresponda

3. Archivos de configuración del demonio Docker

3.1 Comprobar que la propiedad del archivo docker.service está establecida en root:root
3.2. Comprobar que los permisos de archivo docker.service están establecidos en 644 o más restrictivos
3.3. Comprobar que la propiedad del archivo docker-registry.service está establecida en root:root
3.4 Comprobar que los permisos de archivo docker-registry.service están establecidos en 644 o más restrictivos
3.5. Comprobar que la propiedad del archivo docker.socket está establecida en root:root
3.6. Comprobar que los permisos de archivo docker.socket se establecen en 644 o más restrictivos
3.7. Comprobar que la propiedad del archivo de entorno Docker está establecida en root:root
3.8. Comprobar que los permisos de archivo de entorno de Docker se establecen en 644 o más restrictivos
3.9. Comprobar que la propiedad del archivo del entorno docker-network está establecida en root:root
3.10. Comprobar que los permisos de archivos de entorno de red Docker están configurados en 644 o más restrictivos
3.11. Comprobar que la propiedad del archivo del entorno docker-registry está establecida en root:root
3.12. Comprobar que los permisos de archivo del entorno de registro de base de datos se establecen en 644 o más restrictivos
3.13. Comprobar que la propiedad del archivo del entorno de almacenamiento acoplador está establecida en root:root
3.14 Comprobar que los permisos de archivo del entorno de almacenamiento acoplador se establecen en 644 o más restrictivos
3.15. Verificar que la propiedad del directorio /etc/docker está establecida en root:root
3.16. Verificar que los permisos del directorio /etc/docker están configurados como 755 o más restrictivos
3.17. Comprobar que la propiedad del archivo del certificado del registry se establece en root:root
3.18. Comprobar que los permisos de los archivos del certificados del registry se establecen en 444 o más restrictivos
3.19. Comprobar que la propiedad del archivo del certificado de la CA de TLS está establecida en root:root
3.20. Comprobar que los permisos de archivo del certificados de CA de TLS se establecen en 444 o más restrictivos
3.21. Verificar que la propiedad del archivo del certificado del servidor Docker está establecida en root:root
3.22. Verificar que los permisos de los archivos de certificados del servidor Docker están establecidos en 444 o más restrictivos
3.23. Comprobar que la propiedad del archivo de clave de certificado del servidor Docker se establece en root:root
3.24. Verificar que los permisos de archivo de clave de certificado del servidor Docker están establecidos en 400
3.25. Verificar que la propiedad del archivo de socket Docker está establecida en root:docker
3.26. Comprobar que los permisos de archivo de zócalo de Docker están establecidos en 660 o más restrictivos

4. Imágenes de contenedor y archivo de generación

4.1. Crear un usuario para el contenedor


4.2. Utilizar imágenes de confianza para los contenedores
4.3. No instalar paquetes innecesarios en el contenedor
4.4. Regenerar las imágenes para incluir parches de seguridad

5. Tiempo de ejecución del contenedor


© FUOC • PID_00241999 50 Introducción a la seguridad en cloud computing

5.1. Verificar el perfil de AppArmor


5.2. Verificar las opciones de seguridad SELinux
5.3. Verificar que los contenedores solo ejecutan un único proceso principal
5.4. Restringir las capacidades del kernel de Linux dentro de los contenedores
5.5. No utilizar contenedores con privilegios
5.6. No montar directorios sensibles del host en los contenedores
5.7. No ejecutar ssh dentro de los contenedores
5.8. No asignar puertos privilegiados dentro de los contenedores
5.9. Abrir solo los puertos necesarios en el contenedor
5.10. No utilizar el modo «host network» en el contenedor
5.11. Limitar el uso de memoria para el contenedor
5.12. Establecer la prioridad de CPU del contenedor de manera adecuada
5.13. Montar el sistema de archivos raíz del contenedor como solo lectura
5.14. Vincular el tráfico de contenedores entrantes a una interfaz de host específica
5.15. Establecer la política de reinicio del contenedor en modo «on-failure»
5.16. No compartir el PID del procesos del host anfitrión con los contenedores
5.17. No compartir el espacio de nombres IPC del anfitrión
5.18. No exponer directamente los dispositivos del anfitrión con los contenedores
5.19. Sobreescribir el valor predeterminado ulimit en tiempo de ejecución solo si es necesario

6. Operaciones de seguridad de Docker

6.1. Realizar auditorías regulares de seguridad del sistema anfitrión y de los contenedores
6.2. Monitorizar el uso, el rendimiento y la métricas de los contenedores de Docker
6.3. Uso Endpoint protection platform (EPP) para contenedores
6.4. Hacer copias de respaldo de los contenedores
6.5. Utilizar un servicio de recolegida de registros centralizado y remoto
6.6. Evitar el almacenamiento de imágenes obsoletas o sin etiquetas correctas
6.7. Evitar el almacenamiento de contenedores obsoletos o sin etiquetas correctas
© FUOC • PID_00241999 51 Introducción a la seguridad en cloud computing

5. Herramientas de seguridad

En este apartado citaremos algunas de las herramientas esenciales para el con-


trol de acceso, el control de fuga de información y la gestión de vulnerabili-
dades. También veremos los beneficios del uso de los estándares abiertos.

5.1. Herramientas de control de acceso

Los denominados agentes de seguridad para el acceso a la nube (cloud access


security broker) es una categoría de herramientas de seguridad que surgen como
una necesidad para atender riesgos de seguridad considerados por los provee-
dores de software como servicio. Gartner los define como los «puntos que re-
fuerzan las políticas de seguridad utilizadas en la nube, y que se ubican entre
los usuarios y los proveedores de servicios cloud, para combinar e intercalar
las políticas de seguridad de la organización, relacionadas con la manera en
la que se accede a los recursos».

• Netskope.
• Paloalto Aperture.
• Cloudlock.

5.2. Herramientas contra la fuga de información

El software de prevención de pérdida de datos (DLP en sus siglas en inglés)


está diseñado para detectar potenciales brechas de datos / transmisiones de
datos exfiltración y prevenirlas mediante la monitorización, la detección y el
bloqueo de datos confidenciales durante el uso (acciones de punto final), en
movimiento (tráfico de red) y en reposo (almacenamiento de datos). En inci-
dentes de fuga de datos, los datos confidenciales son revelados a personal no
autorizado por intención malintencionada o por un error inadvertido. Tales
datos confidenciales pueden venir en forma de información privada o de em-
presa, propiedad intelectual (IP), información financiera o de pacientes, datos
de tarjetas de crédito y otra información dependiendo del negocio y la indus-
tria.

5.2.1. MyDLP Community

MyDLP es un software libre y de código abierto de prevención de pérdida de


datos. Se puede instalar tanto en servidores de red como en estaciones de tra-
bajo. Los canales de inspección de datos soportados incluyen web, correo, im,
transferencia de archivos a dispositivos de almacenamiento extraíble e impre-
soras. MyDLP proyecto de desarrollo ha hecho su código fuente disponible
bajo los términos de la GNU General Public License.
© FUOC • PID_00241999 52 Introducción a la seguridad en cloud computing

5.2.2. Ossec

OSSEC es un sistema de detección de intrusos basado en host de código abier-


to y libre (HIDS). Realiza análisis de registro, comprobación de integridad, su-
pervisión del registro de Windows, detección de rootkits, alertas basadas en el
tiempo y respuesta activa. Proporciona detección de intrusiones para la ma-
yoría de los sistemas operativos, incluyendo Linux, OpenBSD, FreeBSD, OS
X, Solaris y Windows. OSSEC tiene una arquitectura centralizada y multipla-
taforma que permite que múltiples sistemas sean fácilmente monitorizados y
administrados.

5.3. Herramientas de gestión de vulnerabilidades

5.3.1. BDD-Security

BDD-Security es un marco de pruebas de seguridad que utiliza lenguaje natu-


ral en una sintaxis Given, When y Then para describir requisitos de seguridad
como características. Esos mismos requisitos también son ejecutables como
pruebas estándar de unidad/integración, lo que significa que pueden ejecutar-
se como parte del proceso de compilación/prueba/implementación durante el
proceso de integración continua.

Prueba aplicaciones web y API desde un punto de vista externo y no requiere


acceso al código fuente de destino.

5.3.2. OWASP ZAP

El OWASP Zed Attack Proxy (ZAP) es una de las herramientas de seguridad


gratuitas más populares del mundo y es mantenida activamente por cientos
de voluntarios internacionales. Puede ayudar a encontrar automáticamente
vulnerabilidades de seguridad en sus aplicaciones web durante su desarrollo y
prueba. También es una gran herramienta para pentesters experimentados para
usar para pruebas de seguridad manuales.

El complemento oficial de OWASP ZAP Jenkins amplía la funcionalidad de la


herramienta de seguridad ZAP en un entorno de CI:

• Administrar sesiones (cargar o persistir).


• Definir contexto (nombre, incluir URL y excluir URL).
• Contextos de ataque (Spider Scan, AJAX Spider, Active Scan).

5.3.3. Nessus

Nessus es un escáner de vulnerabilidades desarrollado por Tenable Network


Security. Permite escanear los siguientes tipos de vulnerabilidades:
© FUOC • PID_00241999 53 Introducción a la seguridad en cloud computing

• Vulnerabilidades que permiten a un hacker remoto controlar o acceder a


datos confidenciales en un sistema.

• Misconfiguración (por ejemplo, relé de correo abierto, parches que faltan,


etc.).

• Contraseñas predeterminadas, algunas contraseñas comunes y contrase-


ñas en blanco/ausentes en algunas cuentas del sistema. Nessus también
puede llamar a Hydra (una herramienta externa) para lanzar un ataque de
diccionario.

• Denegaciones de servicio contra la pila TCP/IP mediante el uso de paquetes


malformados.

• Preparación para auditorías PCI DSS.

5.4. Beneficios del uso de los estándares abiertos

Cuando se trata de seguridad, los estándares abiertos aparecen para ofrecernos


todos sus beneficios:

• Agilizar las implementaciones en la nube: una capa API bien conocida y


estándar dará a los desarrolladores de la empresa la capacidad de aprove-
char las funciones básicas de la nube rápidamente, acelerando así el ritmo
de las implementaciones en la nube.

• Fomentar las innovaciones entre nubes: con las API de Cloud Security
Open, los desarrolladores ahora tienen una forma de escribir funciones de
nube cruzada sin tener que integrarse a la perfección con cada nube que
toque. Esto puede abrir innovaciones en nuevos escenarios económicos,
nuevas formas de hacer negocios tanto para los usuarios como para los
proveedores de la nube.

• Extender servicios cloud a nuevas funcionalidades: Desde la perspectiva de


un proveedor de servicios en la nube (CSP), las API Cloud Security Open
permitirán a un conjunto mucho mayor de desarrolladores (que aquellos
dentro de la propia compañía de CSP) aprovechar la base de datos y en-
tregar funcionalidad adyacente. A veces este modelo puede conducir a ex-
periencias de usuario totalmente nuevas e inesperadas y a avances tecno-
lógicos, lo que puede hacer que el servicio sea mucho más atractivo para
los usuarios finales.
© FUOC • PID_00241999 54 Introducción a la seguridad en cloud computing

Entre todas las iniciativas destaca la Open API de la Cloud Security Alliance. Enlace de interés

Podéis encontrar más infor-


mación sobre la Open API en
el siguiente enlace: Open API
Working Group.

También podría gustarte