Capítulo 1. Revolución en la nube

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Nunca hubo un momento en que el mundo comenzara, porque gira y gira como un círculo, y no hay ningún lugar en un círculo donde comience.

Alan Watts

Se está produciendo una revolución. En realidad, tres revoluciones.

La primera revolución es la creación de la nube, y te explicaremos qué es y por qué es importante. La segunda es el amanecer de DevOps, y descubrirás qué implica y cómo está cambiando las operaciones. La tercera revolución es la amplia adopción de contenedores. Juntas, estas tres olas de cambio están creando un nuevo mundo de software: el mundo nativo de la nube. El sistema operativo de este mundo se llama Kubernetes.

En este capítulo, haremos un breve recuento de la historia y la importancia de estas revoluciones, y exploraremos cómo los cambios están afectando a la forma en que todos implementamos y operamos el software. Esbozaremos qué significa nube nativa y qué cambios puedes esperar ver en este nuevo mundo si trabajas en desarrollo, operaciones, implementación, ingeniería, redes o seguridad de software.

Gracias a los efectos de estas revoluciones interrelacionadas, creemos que el futuro de la informática reside en los sistemas distribuidos, en contenedores y basados en la nube, gestionados dinámicamente por la automatización, en la plataforma Kubernetes (o algo muy parecido). El arte de desarrollar y ejecutar estas aplicaciones-DevOps nativo de la nube- eslo que exploraremos en el resto de este libro.

Si ya estás familiarizado con todo este material de base, y sólo quieres empezar a divertirte con Kubernetes, no dudes en saltar al Capítulo 2. Si no, acomódate cómodamente, con una taza de tu bebida favorita, y empezaremos.

La creación de la nube

Al principio (bueno, al menos en los años 60), los ordenadores llenaban un rack tras otro en enormes centros de datos remotos y climatizados, y los usuarios nunca los veían ni interactuaban con ellos directamente. En su lugar, los desarrolladores enviaban sus trabajos a la máquina a distancia y esperaban los resultados. Muchos cientos o miles de usuarios compartirían la misma infraestructura informática, y cada uno recibiría simplemente una factura por la cantidad de tiempo de procesador o recursos que utilizara.

No era rentable que cada empresa u organización comprara y mantuviera su propio hardware informático, así que surgió un modelo de negocio en el que los usuarios compartían la potencia informática de máquinas remotas, propiedad de terceros y gestionadas por ellos.

Si eso suena a ahora mismo, en lugar de al siglo pasado, no es casualidad. La palabra revolución significa "movimiento circular", y la informática ha vuelto, en cierto modo, al punto de partida. Aunque los ordenadores se han hecho mucho más potentes a lo largo de los años -el Apple Watch de hoy equivale a unos tres de los ordenadores centrales mostrados en la Figura 1-1-, el acceso compartidoy de pago a los recursos informáticos es una idea muy antigua. Ahora la llamamos nube, y la revolución que comenzó con los mainframes de tiempo compartido ha cerrado el círculo.

IBM System/360 Model 91
Figura 1-1. El primer ordenador en nube: el IBM System/360 Modelo 91, en el Centro de Vuelo Espacial Goddard de la NASA

Comprar tiempo

La idea central de la nube es la siguiente: en lugar de comprar un ordenador, compras computación. Es decir, en lugar de invertir grandes cantidades de capital en maquinaria física, que es difícil de escalar, se estropea mecánicamente y se queda obsoleta con rapidez, simplemente compras tiempo en el ordenador de otra persona y dejas que se ocupe del escalado, el mantenimiento y la actualización. En los tiempos de las máquinas bare-metal -la "Edad de Hierro", si quieres- la potencia informática era un gasto de capital. Ahora es un gasto operativo, y eso ha marcado la diferencia.

La nube no es sólo potencia informática alquilada a distancia. También se trata de sistemas distribuidos. Puedes comprar recursos informáticos en bruto (como una instancia de Google Compute, o una función AWS Lambda) y utilizarlos para ejecutar tu propio software, pero cada vez más también alquilas servicios en la nube: esencialmente, el uso del software de otra persona. Por ejemplo, si utilizas PagerDuty para monitorizar tus sistemas y alertarte cuando algo no funciona, estás utilizando un servicio en la nube (a veces denominado software como servicio, o SaaS). El éxito de estos servicios SaaS se debe en parte a esta reciente revolución de la nube. Ahora casi cualquiera puede crear una nueva aplicación o sitio web, alojarla en un proveedor de nube pública y ampliarla a un público mundial si encuentra cierto éxito.

Infraestructura como servicio

Cuando utilizas infraestructura en la nube para ejecutar tus propios servicios, lo que estás comprando es infraestructura como servicio (IaaS). No tienes que gastar capital para comprarla, no tienes que construirla y no tienes que actualizarla. Es sólo una mercancía, como la electricidad o el agua. La computación en nube es una revolución en la relación entre las empresas y su infraestructura informática.

Externalizar el hardware es sólo una parte de la historia; la nube también te permite externalizar el software que no escribes: sistemas operativos, bases de datos, agrupación en clústeres, replicación, redes, monitoreo, alta disponibilidad, procesamiento de colas y flujos, y toda la miríada de capas de software y configuración que se extienden entre tu código y la CPU. Los servicios gestionados pueden encargarse de casi todo este trabajo pesado indiferenciado por ti (encontrarás más información sobre las ventajas de los servicios gestionados en el Capítulo 3).

La revolución de la nube también ha desencadenado otra revolución en las personas que la utilizan: el movimiento DevOps.

El amanecer de DevOps

Antes de DevOps, el desarrollo y el funcionamiento del software eran esencialmente dos trabajos separados, realizados por dos grupos de personas diferentes. Los desarrolladores escribían el software y lo pasaban al personal de operaciones, que lo ejecutaba y mantenía en producción (es decir, al servicio de los usuarios reales, en lugar de simplemente ejecutarlo internamente con fines de prueba o desarrollo de funciones). Al igual que los enormes ordenadores centrales que necesitaban su propia planta del edificio, esta separación tenía sus raíces a mediados del siglo pasado. El desarrollo de software era un trabajo muy especializado, al igual que el manejo de ordenadores, y había muy poco solapamiento entre estas dos funciones.

Los dos departamentos tenían objetivos e incentivos bastante diferentes, que a menudo entraban en conflicto entre sí. Los desarrolladores tendían a centrarse en lanzar nuevas funciones rápidamente, mientras que los equipos de operaciones se preocupaban sobre todo de hacer que los servicios fueran estables y fiables a largo plazo. En algunos casos, había políticas de seguridad que impedían a los desarrolladores de software acceder siquiera a los registros o métricas de sus propias aplicaciones en producción. Tenían que pedir permiso al equipo de operaciones para depurar la aplicación e implementar cualquier corrección. Y a menudo se culpaba al equipo de operaciones cada vez que había un problema con una aplicación, independientemente de la causa.

A medida que la computación en nube se hizo más popular, el sector cambió. Los sistemas distribuidos son complejos, e Internet es muy grande. Los aspectos técnicos de estos sistemas distribuidos -cuando se trata de recuperarse de fallos, gestionar tiempos de espera, actualizar versiones sin problemas- no son tan fáciles de separar del diseño, la arquitectura y la implementación del sistema.

Además, "el sistema" ya no es sólo tu software: comprende software interno, servicios en la nube, recursos de red, equilibradores de carga, monitoreo, redes de distribución de contenidos, cortafuegos, DNS, etc. Todas estas cosas están íntimamente interconectadas y son interdependientes. Las personas que escriben el software tienen que entender cómo se relaciona con el resto del sistema, y las personas que manejan el sistema tienen que entender cómo funciona y falla el software.

Mejorar los bucles de realimentación

Los orígenes del movimiento DevOps se encuentran en los intentos de unir a estos dos grupos: colaborar, compartir conocimientos, compartir la responsabilidad de la fiabilidad de los sistemas y la corrección del software, y mejorar la escalabilidad tanto de los sistemas de software como de los equipos de personas que los construyen.

DevOps consiste en mejorar los bucles de retroalimentación y los puntos de traspaso que existen entre varios equipos cuando escriben código, crean aplicaciones, ejecutan pruebas e implementan cambios para garantizar que las cosas funcionan sin problemas y con eficacia.

¿Qué significa DevOps?

En ocasiones,DevOps ha sido un término controvertido de definir, tanto por quienes insisten en que no es más que una etiqueta moderna para las buenas prácticas existentes en el desarrollo de software, como por quienes rechazan de plano la necesidad de una mayor colaboración entre desarrollo y operaciones.

También existe un malentendido generalizado sobre lo que es realmente DevOps: ¿Un puesto de trabajo? ¿Un equipo? ¿Una metodología? ¿Un conjunto de habilidades? El influyente escritor sobre DevOps John Willis ha identificado cuatro pilares clave de DevOps, a los que denomina cultura, automatización, medición e intercambio (CAMS). Las organizaciones que practican DevOps tienen una cultura que adopta la colaboración, rechaza el aislamiento del conocimiento entre los equipos, e inventa formas de medir cómo pueden mejorar constantemente. Otra forma de desglosarlo es lo que Brian Dawson ha denominado la trinidad DevOps: personas y cultura, proceso y práctica, y herramientas y tecnología.

Algunas personas piensan que la nube y los contenedores significan que ya no necesitamos DevOps, un punto de vista que a veces se denomina NoOps. La idea es que, dado que todas las operaciones de TI se externalizan a un proveedor de la nube, o a otro servicio de terceros, las empresas no necesitan personal de operaciones a tiempo completo.

La falacia NoOps se basa en una interpretación errónea de lo que implica realmente el trabajo DevOps:

Con DevOps, gran parte del trabajo tradicional de operaciones de TI tiene lugar antes de que el código llegue a producción. Cada versión incluye monitoreo, registro y pruebas A/B. Los conductos CI/CD ejecutan automáticamente pruebas unitarias, escáneres de seguridad y comprobaciones de políticas en cada confirmación. Las Implementaciones son automáticas. Los controles, tareas y requisitos no funcionales se implementan ahora antes de la publicación, en lugar de durante el frenesí y las secuelas de una interrupción crítica.

Jordan Bach(AppDynamics)

Por el momento, encontrarás muchas ofertas de empleo con el título de Ingeniero DevOps y una gran variedad de lo que se espera de esa función, dependiendo de la organización. A veces se parecerá más a una función tradicional de "administrador de sistemas" y tendrá poca interacción con los ingenieros de software. A veces, la función estará integrada junto a los desarrolladores que construyen e implementan sus propias aplicaciones. Es importante considerar lo que DevOps significa para ti y cómo quieres que sea en una organización.

Lo más importante que hay que entender sobre DevOps es que se trata principalmente de una cuestión organizativa y humana, no técnica. Esto concuerda con la Segunda Ley de la Consultoría de Jerry Weinberg:

No importa lo que parezca al principio, siempre es un problema de personas.

Gerald M. Weinberg, Los secretos de la consultoría

Y DevOps funciona de verdad. Los estudios sugieren regularmente que las empresas que adoptan los principios DevOps lanzan mejor software más rápidamente, reaccionan mejor y más rápido a los fallos y problemas, son más ágiles en el mercado y mejoran drásticamente la calidad de sus productos:

DevOps no es una moda, sino la forma en que las organizaciones de éxito industrializan hoy la entrega de software de calidad, y será la nueva línea de base mañana y en los años venideros.

Brian Dawson, CloudBees

Infraestructura como código

Hubo un tiempo en que los desarrolladores se ocupaban del software, mientras que los equipos de operaciones se ocupaban del hardware y de los sistemas operativos que se ejecutaban en ese hardware.

Ahora que el hardware está en la nube, todo, en cierto sentido, es software. El movimiento DevOps lleva las habilidades de desarrollo de software a las operaciones: herramientas y flujos de trabajo para la construcción rápida, ágil y colaborativa de sistemas complejos. A menudo se denomina infraestructura como código (IaC).

En lugar de montar y cablear físicamente ordenadores y conmutadores, la infraestructura de la nube puede aprovisionarse automáticamente mediante software. En lugar de desplegar y actualizar manualmente el hardware, los ingenieros de operaciones se han convertido en las personas que escriben el software que automatiza la nube.

El tráfico no es sólo unidireccional. Los desarrolladores están aprendiendo de los equipos de operaciones cómo anticiparse a los fallos y problemas inherentes a los sistemas distribuidos basados en la nube, cómo mitigar sus consecuencias y cómo diseñar software que se degrade con elegancia y falle con seguridad.

Aprender juntos

Tanto los equipos de desarrollo como los de operaciones están aprendiendo a trabajar juntos. Están aprendiendo a diseñar y construir sistemas, a monitorizar y obtener información sobre los sistemas en producción, y a utilizar esa información para mejorar los sistemas. Y lo que es aún más importante, están aprendiendo a mejorar la experiencia de sus usuarios y a ofrecer un mayor valor a la empresa que los financia.

La escala masiva de la nube y la naturaleza colaborativa y centrada en el código del movimiento DevOps han convertido las operaciones en un problema de software. Al mismo tiempo, también han convertido el software en un problema de operaciones. Todo ello plantea estas preguntas:

  • ¿Cómo se implementa y actualiza el software en redes grandes y diversas de diferentes arquitecturas de servidores y sistemas operativos?

  • ¿Cómo se implementa en entornos distribuidos, de forma fiable y reproducible, utilizando componentes en gran medida estandarizados?

Entra en la tercera revolución: el contenedor.

La llegada de los contenedores

Para implementar un programa en , no sólo necesitas el programa en sí, sino también sus dependencias. Es decir, bibliotecas, intérpretes, subpaquetes, compiladores, extensiones, etc.

También necesitas su configuración: ajustes, detalles específicos del sitio, claves de licencia, contraseñas de la base de datos... todo lo que convierte el software en bruto en un servicio utilizable.

El estado de la técnica

Los intentos anteriores de resolver este problema incluyen el uso de sistemas de gestión de la configuración, como Puppet o Ansible, que consisten en código para instalar, ejecutar, configurar y actualizar el software.

Otra solución es el paquete ómnibus, que, como su nombre indica, intenta meter todo lo que necesita la aplicación dentro de un único archivo. Un paquete ómnibus contiene el software, su configuración, sus componentes de software dependientes, su configuración, sus dependencias, etc. (Por ejemplo, un paquete ómnibus Java contendría el tiempo de ejecución Java, así como todos los archivos Java Archive [JAR] de la aplicación).

Algunos proveedores han ido incluso un paso más allá y han incluido todo el sistema informático necesario para ejecutarlo, como una imagen de máquina virtual (imagen VM), pero éstas son grandes y difíciles de manejar, requieren mucho tiempo para construirlas y mantenerlas, son frágiles de manejar, lentas de descargar y desplegar, y enormemente ineficientes en cuanto a rendimiento y consumo de recursos.

Desde el punto de vista de las operaciones, no sólo tienes que gestionar estos distintos tipos de paquetes, sino también una flota de servidores en los que ejecutarlos.

Hay que aprovisionar los servidores, conectarlos en red, implementarlos, configurarlos, mantenerlos actualizados con parches de seguridad, monitorizarlos, gestionarlos, etc.

Todo esto requiere una cantidad significativa de tiempo, habilidad y esfuerzo sólo para proporcionar una plataforma sobre la que ejecutar software. ¿No hay una forma mejor?

Pensar dentro de la caja

Para resolver estos problemas, la industria tecnológica tomó prestada una idea de la industria naviera: el contenedor. En los años 50, un camionero llamado Malcolm McLean propuso que, en lugar de descargar laboriosamente las mercancías individualmente de los remolques de los camiones que las llevaban a los puertos y cargarlas en los barcos, los propios camiones -o mejor dicho, las carrocerías de los camiones- podrían cargarse en el barco.

Un remolque de camión es esencialmente una gran caja metálica con ruedas. Si puedes separar la caja -el contenedor- de las ruedas y el chasis utilizados para transportarlo, tienes algo que es muy fácil de levantar, cargar, apilar y descargar, y que puede ir directamente a un barco o a otro camión en el otro extremo del viaje. Los contenedores también utilizan dimensiones estándar, lo que permite a todo el sector del transporte marítimo, incluidos barcos, trenes y camiones, saber a qué atenerse cuando se trata de trasladarlos de un lugar a otro(Figura 1-2).

La empresa de transporte de contenedores de McLean, Sea-Land, tuvo mucho éxito utilizando este sistema para enviar mercancías de forma mucho más barata, y los contenedores se pusieron rápidamente de moda. Hoy se envían cientos de millones de contenedores al año, que transportan mercancías por valor de billones de dólares.

A crane lifting a shipping container
Figura 1-2. Los contenedores estandarizados reducen drásticamente el coste del transporte de mercancías a granel (foto de Lucarelli, bajo licencia Creative Commons)

Poner el software en contenedores

El contenedor de software es exactamente la misma idea: un formato estándar de empaquetado y distribución que es genérico y está muy extendido, lo que permite aumentar enormemente la capacidad de carga, reducir costes, realizar economías de escala y facilitar el manejo. El formato contenedor contiene todo lo que la aplicación necesita para ejecutarse, horneado en un archivo de imagen que puede ser ejecutado por un tiempo de ejecución contenedor.

¿En qué se diferencia de una imagen de máquina virtual? Ésta también contiene todo lo que la aplicación necesita para funcionar, pero mucho más. Una imagen típica de máquina virtual ocupa alrededor de 1 GiB.1 En cambio, una imagen de contenedor bien diseñada puede ser cien veces más pequeña.

Como la máquina virtual contiene montones de programas no relacionados, bibliotecas y cosas que la aplicación nunca utilizará, la mayor parte de su espacio se desperdicia. Transferir imágenes de máquinas virtuales a través de la red es mucho más lento que los contenedores optimizados.

Peor aún, las máquinas virtuales son virtuales: la CPU física subyacente implementa efectivamente una CPU emulada, sobre la que se ejecuta la máquina virtual. La capa de virtualización tiene un efecto dramático y negativo en el rendimiento: en las pruebas, las cargas de trabajo virtualizadas funcionan un 30% más despacio que los contenedores equivalentes.

En comparación, los contenedores se ejecutan directamente en la CPU real, sin sobrecarga de virtualización, igual que los ejecutables binarios ordinarios.

Y como los contenedores sólo contienen los archivos que necesitan, son mucho más pequeños que las imágenes de las máquinas virtuales. También utilizan una técnica inteligente de capas direccionables del sistema de archivos, que pueden compartirse y reutilizarse entre contenedores.

Por ejemplo, si tienes dos contenedores, cada uno derivado de la misma imagen base de Debian Linux, la imagen base sólo necesita descargarse una vez, y cada contenedor puede simplemente hacer referencia a ella.

El tiempo de ejecución del contenedor reunirá todas las capas necesarias y sólo descargará una capa si no está ya almacenada localmente. Esto hace un uso muy eficiente del espacio en disco y del ancho de banda de la red.

Aplicaciones Plug and Play

El contenedor no sólo es la unidad de implementación y la unidad de empaquetado; también es la unidad de reutilización (la misma imagen de contenedor puede utilizarse como componente de muchos servicios diferentes ), la unidad de escalado y la unidad de asignación de recursos (un contenedor puede ejecutarse en cualquier lugar donde haya suficientes recursos disponibles para sus propias necesidades específicas).

Los desarrolladores ya no tienen que preocuparse de mantener distintas versiones del software para que funcione en distintas distribuciones de Linux, con distintas versiones de bibliotecas y lenguajes, etc. Lo único de lo que depende el contenedor es del núcleo del sistema operativo (Linux, por ejemplo).

Sólo tienes que proporcionar tu aplicación en una imagen de contenedor, y se ejecutará en cualquier plataforma que admita el formato de contenedor estándar y tenga un núcleo compatible.

Los desarrolladores de Kubernetes Brendan Burns y David Oppenheimer lo explican así en su artículo "Patrones de diseño para sistemas distribuidos basados en contenedores":

Al estar herméticamente sellados, llevar consigo sus dependencias y proporcionar una señal de implementación atómica ("correcto"/"fallido"), [los contenedores] mejoran drásticamente el estado anterior de la técnica de implementación de software en el centro de datos o la nube. Pero los contenedores tienen el potencial de ser mucho más que un vehículo de implementación mejor: creemos que están destinados a ser análogos a los objetos en los sistemas de software orientados a objetos, y como tales permitirán el desarrollo de patrones de diseño de sistemas distribuidos.

Dirigir la Orquesta de Contenedores

También los equipos de operaciones ven su carga de trabajo enormemente simplificada por los contenedores. En lugar de tener que mantener un extenso parque de máquinas de diversos tipos, arquitecturas y sistemas operativos, todo lo que tienen que hacer es ejecutar un orquestador de contenedores: un software diseñado para unir muchas máquinas diferentes en un clúster. Un orquestador de contenedores es una especie de sustrato informático unificado, que aparece ante el usuario como un único ordenador muy potente en el que pueden ejecutarse contenedores.

Los términos orquestación y programación suelen utilizarse vagamente como sinónimos. Sin embargo, en sentido estricto, orquestación en este contexto significa coordinar y secuenciar diferentes actividades al servicio de un objetivo común (como los músicos de una orquesta). Programar significa gestionar los recursos disponibles y asignar las cargas de trabajo donde puedan ejecutarse con mayor eficacia. (No confundir con programar en el sentido de trabajos programados, que se ejecutan en momentos preestablecidos).

Una tercera actividad importante es la gestión de clústeres: unir varios servidores físicos o virtuales en un grupo unificado, fiable, tolerante a fallos y aparentemente sin fisuras.

El término orquestador de contenedores suele referirse a un único servicio que se encarga de la programación, la orquestación y la gestión de clusters.

La contenedorización (el uso de contenedores como método estándar de implementación y ejecución de software) ofrecía ventajas obvias, y un formato de contenedor estándar de facto ha hecho posible todo tipo de economías de escala. Pero un problema seguía obstaculizando la adopción generalizada de contenedores: la falta de un sistema estándar de orquestación de contenedores.

Mientras varias herramientas diferentes para programar y orquestar contenedores compitieron en el mercado, las empresas se mostraron reacias a hacer apuestas costosas sobre qué tecnología utilizar. Pero todo eso estaba a punto de cambiar.

Kubernetes

Google utilizaba contenedores a escala para cargas de trabajo de producción mucho antes que nadie. Casi todos los servicios de Google se ejecutan en contenedores: Gmail, Google Search, Google Maps, Google App Engine, etc. Como en aquel momento no existía ningún sistema de orquestación de contenedores adecuado, Google se vio obligado a inventar uno.

De Borg a Kubernetes

Para resolver el problema de ejecutar un gran número de servicios a escala global en millones de servidores, Google desarrolló un sistema interno y privado de orquestación de contenedores al que llamó Borg.

Borg es esencialmente un sistema de gestión centralizado que asigna y programa contenedores para que se ejecuten en un conjunto de servidores. Aunque es muy potente, Borg está estrechamente vinculado a las tecnologías internas y propietarias de Google, es difícil de ampliar e imposible de hacer público.

En 2014, Google fundó un proyecto de código abierto llamado Kubernetes (de la palabra griega κυβερνήτης, que significa "timonel, piloto") que desarrollaría un orquestador de contenedores que todo el mundo pudiera utilizar, basado en las lecciones aprendidas de Borg y su sucesor en , Omega.

El ascenso de Kubernetes ha sido meteórico. Aunque existían otros sistemas de orquestación de contenedores antes de Kubernetes, ninguno ha tenido la misma adopción generalizada que Kubernetes. Con la llegada de un orquestador de contenedores verdaderamente libre y de código abierto, la adopción tanto de contenedores como de Kubernetes creció a un ritmo fenomenal.

Kubernetes sigue ganando popularidad y se está convirtiendo en la norma para ejecutar aplicaciones en contenedores. Según un informe publicado por Datadog:

Kubernetes se ha convertido en el estándar de facto para la orquestación de contenedores. En la actualidad, la mitad de las organizaciones que ejecutan contenedores utilizan Kubernetes, ya sea en clústeres autogestionados o a través de un servicio de proveedor en la nube... La adopción de Kubernetes se ha más que duplicado desde 2017, y sigue creciendo de forma constante, sin signos de desaceleración.

Al igual que los contenedores estandarizaron la forma de empaquetar e implementar el software, Kubernetes está estandarizando la plataforma en la que ejecutar esos contenedores.

¿Por qué Kubernetes?

Kelsey Hightower, defensora de los desarrolladores en Google, coautora de Kubernetes Up & Running (O'Reilly) y toda una leyenda en la comunidad de Kubernetes, lo ha expresado así:

Kubernetes hace las cosas que haría el mejor administrador de sistemas: automatización, conmutación por error, registro centralizado, monitoreo. Toma lo que hemos aprendido en la comunidad DevOps y lo convierte en algo predeterminado, listo para usar.

Kelsey Hightower

Muchas de las tareas tradicionales de administrador de sistemas, como actualizar servidores, instalar parches de seguridad, configurar redes y ejecutar copias de seguridad, son menos preocupantes en el mundo nativo de la nube. Kubernetes puede automatizar estas cosas por ti para que tu equipo pueda concentrarse en hacer su trabajo principal.

Algunas de estas funciones, como el equilibrio de carga y el autoescalado, están integradas en el núcleo de Kubernetes; otras las proporcionan complementos, extensiones y herramientas de terceros que utilizan la API de Kubernetes. El ecosistema de Kubernetes es amplio y no para de crecer.

Kubernetes facilita la implementación

El personal de operaciones adora Kubernetes por estas razones, pero también hay algunas ventajas significativas para los desarrolladores. Kubernetes reduce enormemente el tiempo y el esfuerzo necesarios para la implementación. Las implementaciones sin tiempo de inactividad son habituales, porque Kubernetes realiza actualizaciones continuas por defecto (iniciando los contenedores con la nueva versión, esperando a que estén sanos y cerrando los antiguos).

Kubernetes también proporciona facilidades para ayudarte a implantar prácticas de implementación continua, como las implementaciones canarias: desplegar gradualmente las actualizaciones de un servidor a la vez para detectar los problemas a tiempo (consulta "Implementaciones canarias"). Otra práctica habitual son las Implementaciones Azul/Verde: poner en marcha una nueva versión del sistema en paralelo, y cambiar el tráfico a ella una vez que esté completamente en funcionamiento (ver "Implementaciones Azul/Verde").

Los picos de demanda ya no harán caer tu servicio, porque Kubernetes soporta el autoescalado. Por ejemplo, si la utilización de la CPU por un contenedor alcanza un determinado nivel, Kubernetes puede seguir añadiendo nuevas réplicas del contenedor hasta que la utilización caiga por debajo del umbral. Cuando caiga la demanda, Kubernetes volverá a reducir las réplicas, liberando capacidad del clúster para ejecutar otras cargas de trabajo.

Como Kubernetes incorpora redundancia y conmutación por error, tu aplicación será más fiable y resistente. Algunos servicios gestionados pueden incluso escalar el propio clúster de Kubernetes hacia arriba y hacia abajo en respuesta a la demanda, de modo que nunca pagues por un clúster mayor del que necesites en un momento dado (ver "Autoescalado"). Esto significa que tus aplicaciones deben estar diseñadas para funcionar en un entorno dinámico, pero Kubernetes te ofrece formas estándar de aprovechar ese tipo de infraestructura.

A las empresas también les encantará Kubernetes, porque reduce los costes de infraestructura y aprovecha mucho mejor un conjunto determinado de recursos. Los servidores tradicionales, incluso los de la nube, están ociosos la mayor parte del tiempo. El exceso de capacidad que necesitas para manejar los picos de demanda se desperdicia esencialmente en condiciones normales.

Kubernetes aprovecha esa capacidad desperdiciada y la utiliza para ejecutar cargas de trabajo, de modo que puedes lograr una utilización mucho mayor de tus máquinas, y además obtienes escalado, equilibrio de carga y conmutación por error de forma gratuita.

Aunque algunas de estas funciones, como el autoescalado, estaban disponibles antes de Kubernetes, siempre estaban vinculadas a un proveedor o servicio de nube concreto. Kubernetes es independiente del proveedor: una vez definidos los recursos que utilizas, puedes ejecutarlos en cualquier clúster de Kubernetes, independientemente del proveedor de la nube subyacente.

Eso no significa que Kubernetes te limite al mínimo común denominador. Kubernetes asigna tus recursos a las funciones específicas del proveedor adecuado: por ejemplo, un servicio Kubernetes con equilibrio de carga en Google Cloud creará un equilibrador de carga de Google Cloud; en Amazon, creará un equilibrador de carga de Amazon Web Services (AWS). Kubernetes elimina los detalles específicos de la nube, permitiéndote centrarte en definir el comportamiento de tu aplicación.

Al igual que los contenedores son una forma portátil de definir el software, los recursos de Kubernetes proporcionan una definición portátil de cómo debe ejecutarse ese software.

¿Desaparecerá Kubernetes?

Curiosamente, a pesar del entusiasmo actual en torno a Kubernetes, puede que no hablemos mucho de ello en los próximos años. Muchas cosas que en su día fueron nuevas y revolucionarias forman ahora tanto parte del tejido de la informática que no pensamos realmente en ellas: los microprocesadores, el ratón, Internet.

También es probable que Kubernetes pase a un segundo plano y se convierta en parte de la fontanería. Es aburrido, ¡en el buen sentido! Una vez que aprendas lo que necesitas saber para implementar tu aplicación en Kubernetes, podrás dedicar tu tiempo a añadir funciones a tu aplicación.

Es probable que las ofertas de servicios gestionados para Kubernetes hagan cada vez más el trabajo pesado de ejecutar Kubernetes. En 2021, Google Cloud Platform (GCP) lanzó una nueva oferta para su servicio existente de Kubernetes, denominada Autopilot, que se encarga de las actualizaciones del clúster, la conexión en red y la ampliación y reducción de las máquinas virtuales en función de la demanda. Otros proveedores de nube también se están moviendo en esa dirección y ofrecen plataformas basadas en Kubernetes en las que los desarrolladores sólo tienen que preocuparse de ejecutar su aplicación y no centrarse en la infraestructura subyacente.

Kubernetes no es una panacea

¿Toda la infraestructura de software del futuro estará totalmente basada en Kubernetes? Probablemente no. ¿Es increíblemente fácil y sencillo ejecutar cualquier tipo de carga de trabajo? No del todo.

Por ejemplo, ejecutar bases de datos en sistemas distribuidos requiere una cuidadosa consideración de lo que ocurre en los reinicios y cómo garantizar que los datos siguen siendo coherentes.

Orquestar software en contenedores implica hacer girar nuevas instancias intercambiables sin que sea necesaria la coordinación entre ellas. Pero las réplicas de bases de datos no son intercambiables; cada una tiene un estado único, y la implementación de una réplica de base de datos requiere coordinación con otros nodos para garantizar que cosas como los cambios de esquema se produzcan en todas partes al mismo tiempo.

Sean Loiselle, Laboratorios Cucaracha

Aunque es perfectamente posible ejecutar cargas de trabajo con estado como bases de datos en Kubernetes con fiabilidad de nivel empresarial, requiere una gran inversión de tiempo e ingeniería que puede no tener sentido para tu empresa (ver "Ejecutar menos software"). En su lugar, suele ser más rentable utilizar un servicio gestionado de bases de datos.

En segundo lugar, es posible que algunas cosas no necesiten Kubernetes y puedan ejecutarse en lo que a veces se denominan plataformas sin servidor, mejor llamadas plataformas de funciones como servicio (FaaS).

Funciones en la nube

AWS Lambda, por ejemplo, es una plataforma FaaS que te permite ejecutar código escrito en Go, Python, Java, Node.js, C# y otros lenguajes sin que tengas que compilar o implementar tu aplicación en absoluto. Amazon hace todo eso por ti. Google Cloud tiene ofertas similares con Cloud Run y Functions, y Microsoft también ofrece Azure Functions.

Como se te factura por el tiempo de ejecución en incrementos de milisegundos, el modelo FaaS es perfecto para cálculos que sólo se ejecutan cuando los necesitas, en lugar de pagar por un servidor en la nube, que funciona todo el tiempo tanto si lo utilizas como si no.

Estas funciones en la nube son más cómodas que los contenedores en algunos aspectos (aunque algunas plataformas FaaS también pueden ejecutar contenedores). Pero son más adecuadas para trabajos cortos e independientes (AWS Lambda limita las funciones a 15 minutos de tiempo de ejecución, por ejemplo), especialmente las que se integran con servicios de computación en la nube ya existentes, como Azure Cognitive Services o la API Google Cloud Vision.

Este tipo de plataformas basadas en eventos suelen denominarse modelos "sin servidor". Técnicamente, sigue habiendo un servidor implicado: sólo que es el servidor de otra persona. La cuestión es que no tienes que aprovisionar y mantener ese servidor; el proveedor de la nube se ocupa de ello por ti.

No todas las cargas de trabajo son adecuadas para ejecutarse en plataformas FaaS, ni mucho menos, pero es probable que siga siendo una tecnología clave para las aplicaciones nativas de la nube en el futuro.

Las funciones en la nube tampoco se limitan a plataformas FaaS públicas como Lambda Functions o Azure Functions: si ya tienes un clúster Kubernetes y quieres ejecutar aplicaciones FaaS en él, proyectos de código abierto como OpenFaaS y Knative lo hacen posible.

Algunas de estas plataformas sin servidor Kubernetes abarcan tanto contenedores de larga ejecución como funciones de corta duración impulsadas por eventos, lo que puede significar que en el futuro la distinción entre estos tipos de computación se difumine o desaparezca por completo.

Nativo de la nube

El término nativo de la nube se ha convertido en una forma abreviada cada vez más popular de hablar de aplicaciones y servicios modernos que aprovechan la nube, los contenedores y la orquestación, a menudo basados en software de código abierto.

De hecho, la Cloud Native Computing Foundation (CNCF) se fundó en 2015 para, en sus palabras, "fomentar una comunidad en torno a una constelación de proyectos de alta calidad que orquestan contenedores como parte de una arquitectura de microservicios".

Parte de la Fundación Linux, la CNCF existe para reunir a desarrolladores, usuarios finales y proveedores, incluidos los principales proveedores de nubes públicas. El proyecto más conocido bajo el paraguas de la CNCF es el propio Kubernetes, pero la fundación también incuba y promueve otros componentes clave del ecosistema nativo de la nube: Prometheus, Envoy, Helm, Fluentd, gRPC y muchos más.

Entonces, ¿qué entendemos exactamente por nube nativa? Como la mayoría de estas cosas, significa cosas distintas para personas distintas, pero quizá haya algo en común.

En primer lugar, nube no significa necesariamente un proveedor de nube pública, como AWS o Azure. Muchas organizaciones gestionan sus propias plataformas internas de "nube", a menudo utilizando simultáneamente uno o varios proveedores públicos para diferentes cargas de trabajo. El término nube significa, en sentido amplio, la plataforma de servidores utilizada para ejecutar infraestructura de software, y eso puede adoptar muchas formas.

¿Qué hace que una aplicación sea nativa de la nube? Tomar una aplicación existente y ejecutarla en una instancia de computación en la nube no la convierte en nativa de la nube. Tampoco se trata sólo de ejecutarla en un contenedor, o de utilizar servicios en la nube como Cosmos DB de Azure o Pub/Sub de Google, aunque pueden ser aspectos importantes de una aplicación nativa en la nube.

Así que veamos algunas de las características de los sistemas nativos de la nube en las que la mayoría de la gente puede estar de acuerdo:

Automatizable

Si las aplicaciones van a ser implementadas y gestionadas por máquinas, en lugar de por humanos, tienen que atenerse a normas, formatos e interfaces comunes. Kubernetes proporciona estas interfaces estándar de forma que los desarrolladores de aplicaciones ni siquiera tienen que preocuparse por ellas.

Ubicua y flexible

Al estar desvinculados de recursos físicos como los discos, o de cualquier conocimiento específico sobre el nodo informático en el que se ejecutan, los microservicios en contenedores pueden trasladarse fácilmente de un nodo a otro, o incluso de un clúster a otro.

Resistente y escalable

Las aplicaciones tradicionales tienden a tener puntos únicos de fallo: la aplicación deja de funcionar si su proceso principal se bloquea, o si la máquina subyacente tiene un fallo de hardware, o si un recurso de red se congestiona. Las aplicaciones nativas de la nube, al estar intrínsecamente distribuidas, pueden tener una alta disponibilidad mediante la redundancia y la degradación gradual.

Dinámico

Un orquestador de contenedores como Kubernetes puede programar contenedores para aprovechar al máximo los recursos disponibles. Puede ejecutar muchas copias de contenedores para lograr una alta disponibilidad, y realizar actualizaciones continuas para mejorar los servicios sin interrumpir el tráfico.

Observable

Las aplicaciones nativas de la nube, por su naturaleza, son más difíciles de inspeccionar y depurar. Por eso, un requisito clave de los sistemas distribuidos es la observabilidad: el monitoreo, el registro, el rastreo y las métricas ayudan a los ingenieros a comprender lo que hacen sus sistemas (y lo que hacen mal).

Distribuido

La nube nativa es un enfoque para crear y ejecutar aplicaciones que aprovecha la naturaleza distribuida y descentralizada de la nube. Se trata de cómo funciona tu aplicación, no de dónde se ejecuta. En lugar de desplegar tu código como una entidad única (conocida como monolito), las aplicaciones nativas de la nube tienden a estar compuestas por múltiples microservicios distribuidos que cooperan entre sí. Un microservicio es simplemente un servicio autónomo que hace una cosa. Si juntas suficientes microservicios, obtienes una aplicación.

No se trata sólo de microservicios

Sin embargo, los microservicios tampoco son la panacea. Los monolitos son más fáciles de entender, porque todo está en un solo lugar, y puedes rastrear las interacciones de las distintas partes. Pero es difícil escalar un monolito, tanto en términos del propio código como de los equipos de desarrolladores que lo mantienen. A medida que el código crece, las interacciones entre sus distintas partes crecen exponencialmente, y el sistema en su conjunto crece más allá de la capacidad de un solo cerebro para comprenderlo todo.

Una aplicación nativa de la nube bien diseñada se compone de microservicios, pero decidir cuáles deben ser esos microservicios, dónde están los límites y cómo deben interactuar los distintos servicios no es un problema fácil. Un buen diseño de servicios nativos de la nube consiste en tomar decisiones acertadas sobre cómo separar las distintas partes de tu arquitectura. Sin embargo, incluso una aplicación nativa de la nube bien diseñada sigue siendo un sistema distribuido, lo que lo hace inherentemente complejo, difícil de observar y razonar, y propenso a fallar de formas sorprendentes.

Aunque los sistemas nativos de la nube tienden a ser distribuidos, sigue siendo posible ejecutar aplicaciones monolíticas en la nube, utilizando contenedores, y obtener un valor empresarial considerable al hacerlo. Esto puede ser un paso en el camino hacia la migración gradual de partes del monolito hacia microservicios modernos, o una medida provisional a la espera de rediseñar el sistema para que sea totalmente nativo de la nube.

El futuro de las operaciones

Las operaciones, la ingeniería de infraestructuras y la administración de sistemas son empleos altamente cualificados. ¿Están en peligro en un futuro basado en la nube? Creemos que no.

Por el contrario, estas habilidades serán cada vez más importantes. Diseñar y razonar sobre sistemas distribuidos es difícil. Las redes y los orquestadores de contenedores son complicados. Todo equipo que desarrolle aplicaciones nativas de la nube necesitará habilidades y conocimientos sobre operaciones. La automatización libera al personal del trabajo aburrido, repetitivo y manual para que se ocupe de problemas más complejos, interesantes y divertidos que los ordenadores aún no pueden resolver por sí mismos.

Eso no significa que todos los trabajos de operaciones actuales estén garantizados. Antes, los administradores de sistemas podían arreglárselas sin conocimientos de programación, excepto para preparar algún script de shell sencillo. En el mundo nativo de la nube, eso no bastará para tener éxito.

En un mundo definido por software, la capacidad de escribir, comprender y mantener software se convierte en algo crítico. Si no quieres aprender nuevas habilidades, la industria te dejará atrás, y siempre ha sido así.

DevOps distribuidos

En lugar de concentrarse en un único equipo de operaciones que preste servicio a otros equipos, la experiencia en operaciones se distribuirá entre muchos equipos.

Cada equipo de desarrollo necesitará al menos un especialista en operaciones, responsable de la salud de los sistemas o servicios que presta el equipo. También será un desarrollador, pero además será el experto en redes, Kubernetes, rendimiento, resiliencia y las herramientas y sistemas que permiten a los demás desarrolladores entregar su código en la nube.

Gracias a la revolución DevOps, en la mayoría de las organizaciones ya no habrá sitio para desarrolladores que no sepan operar, ni para operadores que no desarrollen. La distinción entre estas dos disciplinas ha quedado obsoleta y se está borrando rápidamente por completo. Desarrollar y operar software no son más que dos aspectos de la misma cosa.

Algunas cosas seguirán centralizadas

¿Existen límites para DevOps? ¿O desaparecerá por completo el equipo central tradicional de TI y operaciones, disolviéndose en un grupo de consultores internos itinerantes, que entrenan, enseñan y solucionan problemas de operaciones?

Creemos que no, o al menos no del todo. Algunas cosas siguen beneficiándose de estar centralizadas. No tiene sentido que cada aplicación o equipo de servicio tenga su propia forma de detectar y comunicar las incidencias de producción, por ejemplo, o su propio sistema de tickets, o herramientas de implementación. No tiene sentido que cada uno reinvente su propia rueda.

Ingeniería de Productividad para Desarrolladores

La cuestión es que el autoservicio tiene sus límites, y el objetivo de DevOps es acelerar a los equipos de desarrollo, no ralentizarlos con trabajo innecesario y redundante.

Sí, gran parte de las operaciones tradicionales pueden y deben transferirse a otros equipos, principalmente a los que implementan el código y responden a los incidentes relacionados con él. Pero para que eso ocurra, tiene que haber un equipo central fuerte que construya y apoye el ecosistema DevOps en el que operan todos los demás equipos.

En lugar de llamar a este equipo operaciones, nos gusta el nombre de ingeniería de productividad del desarrollador. Algunas organizaciones llaman a esta función ingeniero de plataforma o incluso ingeniero DevOps. La cuestión es que estos equipos hacen lo que sea necesario para ayudar a otros equipos de ingeniería de software a hacer su trabajo mejor y más rápido: hacer funcionar la infraestructura, crear herramientas, resolver problemas.

Y aunque la ingeniería de la productividad del desarrollador sigue siendo un conjunto de habilidades especializadas, los propios ingenieros pueden desplazarse hacia el exterior de la organización para llevar esa experiencia allí donde se necesite.

El ingeniero de Lyft Matt Klein ha sugerido que, aunque un modelo DevOps puro tiene sentido para las startups y las pequeñas empresas, a medida que una organización crece, existe una tendencia natural a que los expertos en infraestructura y fiabilidad graviten hacia un equipo central. Pero dice que ese equipo no puede escalarse indefinidamente:

En el momento en que una organización de ingeniería alcanza ~75 personas, es casi seguro que existe un equipo de infraestructura central que empieza a construir las características comunes del sustrato que necesitan los equipos de producto que construyen microservicios. Pero llega un punto en el que el equipo de infraestructura central ya no puede seguir construyendo y operando la infraestructura crítica para el éxito del negocio, al tiempo que mantiene la carga de apoyo de ayudar a los equipos de producto con las tareas operativas.

Matt Klein

Llegados a este punto, no todos los desarrolladores pueden ser expertos en infraestructura, del mismo modo que un único equipo de expertos en infraestructura no puede dar servicio a un número cada vez mayor de desarrolladores. Para las grandes organizaciones, aunque sigue siendo necesario un equipo central de infraestructura, también hay razones para integrar ingenieros de fiabilidad del sitio (SRE) en cada equipo de desarrollo o producto. Aportan su experiencia a cada equipo como consultores y también forman un puente entre el desarrollo de productos y las operaciones de infraestructura.

Tú eres el futuro

Si estás leyendo este libro, significa que formas parte de este nuevo futuro nativo de la nube. En los capítulos restantes, cubriremos todos los conocimientos y habilidades que necesitarás como desarrollador o ingeniero de operaciones que trabaja con infraestructura en la nube, contenedores y Kubernetes.

Algunas de estas cosas te resultarán familiares y otras serán nuevas, pero esperamos que cuando hayas terminado el libro te sientas más seguro de tu propia capacidad para adquirir y dominar las habilidades nativas de la nube. Sí, hay mucho que aprender, pero no es nada que no puedas manejar. ¡Tú puedes!

Sigue leyendo.

Resumen

Necesariamente te hemos dado una vuelta bastante rápida por el panorama, incluyendo la historia de DevOps, la computación en la nube y la norma emergente de utilizar contenedores y Kubernetes para ejecutar aplicaciones nativas de la nube. Esperamos que sea suficiente para ponerte al día sobre algunos de los retos en este campo y cómo es probable que cambien la industria de TI.

Una rápida recapitulación de los puntos principales antes de que pasemos a conocer Kubernetes en persona en el próximo capítulo:

  • La computación en nube te libera del gasto y la sobrecarga de gestionar tu propio hardware, lo que te permite construir sistemas distribuidos resistentes, flexibles y escalables.

  • DevOps es un reconocimiento de que el desarrollo de software moderno no se detiene en el envío del código: se trata de cerrar el bucle de retroalimentación entre los que escriben el código y los que lo utilizan.

  • DevOps también aporta un enfoque centrado en el código y buenas prácticas de ingeniería de software al mundo de las infraestructuras y las operaciones.

  • Los contenedores te permiten implementar y ejecutar software en unidades pequeñas, estandarizadas y autónomas. Esto facilita y abarata la construcción de sistemas grandes, diversos y distribuidos, mediante la conexión de microservicios en contenedores.

  • Los sistemas de orquestación se encargan de la implementación de tus contenedores, la programación, el escalado, la conexión en red y todas las cosas que haría un buen administrador de sistemas, pero de forma automatizada y programable.

  • Kubernetes es el sistema de orquestación de contenedores estándar de facto, y está listo para que lo utilices en producción ahora mismo, hoy mismo. Sigue siendo un proyecto en rápida evolución, y todos los principales proveedores de la nube están ofreciendo más servicios gestionados para manejar automáticamente los componentes básicos subyacentes de Kubernetes.

  • La computación "sin servidor" basada en eventos también se está haciendo popular para las aplicaciones nativas de la nube, a menudo utilizando contenedores como tiempo de ejecución. Existen herramientas para ejecutar este tipo de funciones en clústeres Kubernetes.

  • Nube nativa es una abreviatura útil para hablar de sistemas distribuidos, en contenedores y basados en la nube, formados por microservicios cooperantes, gestionados dinámicamente por una infraestructura automatizada como código.

  • Las competencias en operaciones e infraestructura, lejos de quedar obsoletas por la revolución nativa de la nube, son y serán más importantes que nunca.

  • Lo que desaparecerá es la distinción tajante entre ingenieros de software e ingenieros de operaciones. Ahora todo es software, y todos somos ingenieros.

1 El gibibyte (GiB) es la unidad de datos de la Comisión Electrotécnica Internacional (CEI), definida como 1.024 mebibytes (MiB), y el kibibibyte (KiB), se define como 1.024 bytes. Utilizaremos las unidades IEC (GiB, MiB, KiB) a lo largo de este libro para evitar cualquier ambigüedad.

Get DevOps Nativo en la Nube con Kubernetes, 2ª Edición now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.