Capítulo 1. Introducción Introducción
Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com
Kubernetes es un orquestador de código abierto para la implementación de aplicaciones en contenedores. Fue desarrollado originalmente por Google, inspirándose en una década de experiencia en el despliegue de sistemas escalables y fiables en contenedores a través de API orientadas a aplicaciones.1
Desde su introducción en 2014, Kubernetes ha crecido hasta convertirse en uno de los proyectos de código abierto más grandes y populares del mundo. Se ha convertido en la API estándar para construir aplicaciones nativas de la nube, presente en casi todas las nubes públicas. Kubernetes es una infraestructura probada para sistemas distribuidos que resulta adecuada para desarrolladores nativos de la nube de todas las escalas, desde un clúster de ordenadores Raspberry Pi hasta un centro de datos lleno de máquinas de última generación. Proporciona el software necesario para construir e implementar con éxito sistemas distribuidos fiables y escalables.
Quizá te preguntes a qué nos referimos cuando hablamos de "sistemas distribuidos fiables y escalables". Cada vez se prestan más servicios a través de la red mediante API. A menudo, estas API se prestan mediante un sistema distribuido, en el que las distintas piezas que implementan la API se ejecutan en máquinas diferentes, conectadas a través de la red y coordinando sus acciones mediante la comunicación de red. Dado que cada vez dependemos más de estas API para todos los aspectos de nuestra vida cotidiana (por ejemplo, para encontrar la dirección del hospital más cercano), estos sistemas deben ser altamente fiables. No pueden fallar, aunque una parte del sistema se bloquee o deje de funcionar. Del mismo modo, deben mantener la disponibilidad incluso durante los lanzamientos de software u otros eventos de mantenimiento. Por último, dado que cada vez más personas se conectan a Internet y utilizan estos servicios, deben ser altamenteescalables, de modo que puedan aumentar su capacidad para seguir el ritmo de un uso cada vez mayor sin un rediseño radical del sistema distribuido que implementa los servicios. En muchos casos, esto también significa aumentar (y reducir) la capacidad automáticamente para que tu aplicación pueda ser lo más eficiente posible.
Dependiendo de cuándo y por qué hayas llegado a tener este libro en tus manos, puede que tengas diversos grados de experiencia con contenedores, sistemas distribuidos y Kubernetes. Puede que estés planeando construir tu aplicación sobre una infraestructura de nube pública, en centros de datos privados o en algún entorno híbrido. Independientemente de tu experiencia, este libro debería permitirte sacar el máximo partido a Kubernetes.
Hay muchas razones por las que la gente utiliza contenedores y API de contenedores como Kubernetes, pero creemos que todas ellas pueden atribuirse a una de estas ventajas:
-
Velocidad de desarrollo
-
Ampliación (tanto del software como de los equipos)
-
Abstraer tu infraestructura
-
Eficacia
-
Ecosistema nativo en la nube
En las secciones siguientes, describimos cómo Kubernetes puede ayudar a proporcionar cada una de estas características.
Velocidad
La velocidad es el componente clave en casi todo el desarrollo de software actual. La industria del software ha evolucionado desde el envío de productos en cajas de CD o DVD al software que se entrega a través de la red mediante servicios basados en la web que se actualizan cada hora. Este paisaje cambiante significa que la diferencia entre tú y tus competidores es a menudo la velocidad con la que puedes desarrollar e implementar nuevos componentes y funciones, o la velocidad con la que puedes responder a las innovaciones desarrolladas por otros.
Sin embargo, es importante tener en cuenta que la velocidad no se define simplemente en términos de velocidad bruta. Aunque tus usuarios siempre buscan mejoras iterativas, están más interesados en un servicio altamente fiable. Hubo un tiempo en que no pasaba nada si un servicio se caía por mantenimiento todas las noches a medianoche. Pero hoy en día, todos los usuarios esperan un tiempo de actividad constante, aunque el software que utilicen cambie constantemente.
En consecuencia, la velocidad no se mide en términos del número bruto de funciones que puedes enviar por hora o día, sino en términos del número de cosas que puedes enviar manteniendo un servicio de alta disponibilidad.
De este modo, los contenedores y Kubernetes pueden proporcionarte las herramientas que necesitas para moverte con rapidez, sin dejar de estar disponible. Los conceptos básicos que permiten esto son:
-
Inmutabilidad
-
Configuración declarativa
-
Sistemas de autocuración en línea
-
Bibliotecas y herramientas reutilizables compartidas
Todas estas ideas se interrelacionan para mejorar radicalmente la velocidad con la que puedes implementar un nuevo software de forma fiable.
El valor de la inmutabilidad
Los contenedores y Kubernetes animan a los desarrolladores a construir sistemas distribuidos que se adhieran a los principios de la infraestructura inmutable. Con una infraestructura inmutable, una vez que se crea un artefacto en el sistema, éste no cambia mediante modificaciones del usuario.
Tradicionalmente, los ordenadores y los sistemas de software se han tratado como infraestructura mutable. Con la infraestructura mutable, los cambios se aplican como actualizaciones incrementales a un sistema existente. Estas actualizaciones pueden producirse todas a la vez, o repartidas a lo largo de un período de tiempo prolongado. Una actualización del sistema a través de la herramienta apt-get update
es un buen ejemplo de actualización de un sistema mutable. Ejecutando apt
se descargan secuencialmente los binarios actualizados, se copian sobre los binarios antiguos y se realizan actualizaciones incrementales de los archivos de configuración. Con un sistema mutable, el estado actual de la infraestructura no se representa como un único artefacto, sino como una acumulación de actualizaciones incrementales y cambios a lo largo del tiempo. En muchos sistemas, estas actualizaciones incrementales no sólo proceden de las actualizaciones del sistema, sino también de las modificaciones de los operadores. Además, en cualquier sistema gestionado por un gran equipo, es muy probable que estos cambios hayan sido realizados por muchas personas diferentes y, en muchos casos, no habrán quedado registrados en ninguna parte.
En cambio, en un sistema inmutable, en lugar de una serie de actualizaciones y cambios incrementales, se construye una imagen completa totalmente nueva, en la que la actualización simplemente sustituye toda la imagen por la imagen más nueva en una sola operación. No hay cambios incrementales. Como puedes imaginar, se trata de un cambio significativo respecto al mundo más tradicional de la gestión de la configuración.
Para concretar esto en el mundo de los contenedores, considera dos formas distintas de actualizar tu software:
-
Puedes entrar en un contenedor, ejecutar un comando para descargar tu nuevo software, matar el servidor antiguo e iniciar el nuevo.
-
Puedes crear una nueva imagen de contenedor, enviarla a un registro de contenedores, matar el contenedor existente e iniciar uno nuevo.
A primera vista, estos dos enfoques pueden parecer prácticamente indistinguibles. Entonces, ¿qué tiene el acto de construir un nuevo contenedor que mejora la fiabilidad?
La diferenciación clave es el artefacto que creas, y el registro de cómo lo creaste. Estos registros facilitan comprender exactamente las diferencias en alguna nueva versión y, si algo va mal, determinar qué ha cambiado y cómo solucionarlo.
Además, crear una imagen nueva en lugar de modificar una existente significa que la imagen antigua sigue existiendo y puede utilizarse rápidamente para revertirla si se produce un error. Por el contrario, una vez que copias tu nuevo binario sobre un binario existente, tal reversión es casi imposible.
Las imágenes de contenedores inmutables son el núcleo de todo lo que construirás en Kubernetes. Es posible cambiar imperativamente los contenedores en ejecución, pero se trata de un antipatrón que sólo debe utilizarse en casos extremos en los que no haya otras opciones (por ejemplo, si es la única forma de reparar temporalmente un sistema de producción de misión crítica). E incluso entonces, los cambios también deben registrarse mediante una actualización declarativa de la configuración en algún momento posterior, una vez apagado el incendio.
Configuración declarativa
La inmutabilidad se extiende más allá de los contenedores que se ejecutan en tu clúster, hasta la forma en que describes tu aplicación a Kubernetes. Todo en Kubernetes es un objeto de configuración declarativo que representa el estado deseado del sistema. El trabajo de Kubernetes es garantizar que el estado real del mundo coincida con este estado deseado.
De forma muy parecida a la infraestructura mutable frente a la inmutable, la configuración declarativa es una alternativa a la configuración imperativa, en la que el estado del mundo se define mediante la ejecución de una serie de instrucciones en lugar de una declaración del estado deseado del mundo. Mientras que las órdenes imperativas definen las acciones, las configuraciones declarativas definen el estado.
Para entender estos dos enfoques, considera la tarea de producir tres réplicas de una pieza de software. Con un enfoque imperativo, la configuración diría "ejecuta A, ejecuta B y ejecuta C". La configuración declarativa correspondiente sería "réplicas igual a tres".
Como describe el estado del mundo, la configuración declarativa no tiene que ejecutarse para entenderse. Su impacto se declara de forma concreta. Como los efectos de la configuración declarativa pueden comprenderse antes de ejecutarse, la configuración declarativa es mucho menos propensa a errores. Además, las herramientas tradicionales de desarrollo de software, como el control de código fuente, la revisión de código y las pruebas unitarias, pueden utilizarse en la configuración declarativa de formas que son imposibles para las instrucciones imperativas. La idea de almacenar la configuración declarativa en el control de código fuente suele denominarse "infraestructura como código".
Últimamente, la idea de GitOps ha empezado a formalizar la práctica de la infraestructura como código, con el control de fuentes como fuente de verdad. Cuando adoptas GitOps, los cambios en la producción se realizan enteramente mediante envíos a un repositorio Git, que luego se reflejan en tu clúster mediante automatización. De hecho, tu clúster Kubernetes de producción se considera un entorno de sólo lectura. Además, GitOps se está integrando cada vez más en los servicios Kubernetes proporcionados por la nube como la forma más sencilla de gestionar declarativamente tu infraestructura nativa en la nube.
La combinación del estado declarativo almacenado en un sistema de control de versiones y la capacidad de Kubernetes para hacer que la realidad coincida con este estado declarativo hace que revertir un cambio sea trivialmente fácil. Se trata simplemente de restablecer el estado declarativo anterior del sistema. Esto suele ser imposible con los sistemas imperativos, porque aunque las instrucciones imperativas describen cómo llegar del punto A al punto B, rara vez incluyen las instrucciones inversas que pueden hacerte volver.
Sistemas de autocuración
Kubernetes es un sistema en línea y autorreparable. Cuando recibe una configuración de estado deseada, no se limita a realizar un conjunto de acciones para que el estado actual coincida con el estado deseado una sola vez. Realiza acciones continuamente para asegurarse de que el estado actual coincide con el estado deseado. Esto significa que Kubernetes no sólo inicializará tu sistema, sino que lo protegerá contra cualquier fallo o perturbación que pueda desestabilizarlo y afectar a su fiabilidad.
Una reparación de operador más tradicional implica una serie manual de pasos de mitigación, o intervención humana, realizada en respuesta a algún tipo de alerta. Una reparación imperativa como ésta es más cara (ya que generalmente requiere que un operador de guardia esté disponible para ejecutar la reparación). También suele ser más lenta, ya que a menudo un humano debe despertarse e iniciar sesión para responder. Además, es menos fiable porque la serie imperativa de operaciones de reparación sufre todos los problemas de la gestión imperativa descritos en la sección anterior. Los sistemas autorreparadores como Kubernetes reducen la carga de los operadores y mejoran la fiabilidad general del sistema al realizar reparaciones fiables con mayor rapidez.
Como ejemplo concreto de este comportamiento autorregenerador, si afirmas a Kubernetes un estado deseado de tres réplicas, no se limita a crear tres réplicas, sino que se asegura continuamente de que haya exactamente tres réplicas. Si creas manualmente una cuarta réplica, Kubernetes destruirá una para que el número vuelva a ser tres. Si destruyes manualmente una réplica, Kubernetes creará una para volver de nuevo al estado deseado.
Los sistemas de autorreparación en línea mejoran la velocidad de los desarrolladores, porque el tiempo y la energía que de otro modo habrían dedicado a las operaciones y el mantenimiento pueden dedicarse, en cambio, a desarrollar y probar nuevas funciones.
En una forma más avanzada de autocuración, se ha trabajado mucho recientemente en el paradigma del operador para Kubernetes. Con los operadores, la lógica más avanzada necesaria para mantener, escalar y curar un software específico (MySQL, por ejemplo) se codifica en una aplicación de operador que se ejecuta como contenedor en el clúster. El código del operador es responsable de una detección y curación de la salud más específica y avanzada que la que puede conseguirse mediante la autocuración genérica de Kubernetes. A menudo esto se empaqueta como "operadores", que se tratan en el Capítulo 17.
Ampliar tu servicio y tus equipos
A medida que tu producto crece, es inevitable que necesites escalar tanto tu software como los equipos que lo desarrollan. Afortunadamente, Kubernetes puede ayudarte con ambos objetivos. Kubernetes logra la escalabilidad favoreciendo las arquitecturas desacopladas.
Desacoplamiento
En una arquitectura desacoplada, cada componente está separado de los demás mediante API definidas y equilibradores de carga de servicios. Las API y los equilibradores de carga aíslan cada pieza del sistema de las demás. Las API proporcionan un amortiguador entre el implementador y el consumidor, y los equilibradores de carga proporcionan un amortiguador entre las instancias en ejecución de cada servicio.
Desacoplar componentes mediante equilibradores de carga hace que sea fácil escalar los programas que componen tu servicio, porque aumentar el tamaño (y por tanto la capacidad) del programa puede hacerse sin ajustar o reconfigurar ninguna de las otras capas de tu servicio.
Desacoplar servidores mediante API facilita la escalabilidad de los equipos de desarrollo, porque cada equipo puede centrarse en un único microservicio, más pequeño y con una superficie comprensible. Las API nítidas entre microservicios limitan la cantidad de sobrecarga de comunicación entre equipos necesaria para crear e implementar software. Esta sobrecarga de comunicación suele ser el principal factor restrictivo a la hora de escalar equipos.
Fácil escalado para aplicaciones y clusters
Concretamente, cuando necesites escalar tu servicio, la naturaleza inmutable y declarativa de Kubernetes hace que este escalado sea trivial de implementar. Como tus contenedores son inmutables, y el número de réplicas es simplemente un número en una configuración declarativa, escalar tu servicio hacia arriba es simplemente cuestión de cambiar un número en un archivo de configuración, afirmar este nuevo estado declarativo a Kubernetes, y dejar que él se ocupe del resto. Como alternativa, puedes configurar el autoescalado y dejar que Kubernetes lo haga por ti.
Por supuesto, ese tipo de escalado supone que hay recursos disponibles en tu clúster para consumir. A veces, en realidad necesitas escalar el propio clúster. De nuevo, Kubernetes facilita esta tarea. Dado que muchas máquinas de un clúster son totalmente idénticas a otras máquinas de ese conjunto y que las propias aplicaciones están desacopladas de los detalles de la máquina por contenedores, añadir recursos adicionales al clúster es simplemente cuestión de imaginar una nueva máquina de la misma clase y unirla al clúster. Esto puede hacerse mediante unos sencillos comandos o mediante una imagen de máquina preconfeccionada.
Uno de los retos de escalar los recursos de máquinas es predecir su uso. Si estás funcionando en una infraestructura física, el tiempo para obtener una nueva máquina se mide en días o semanas. Tanto en infraestructuras físicas como en la nube, predecir los costes futuros es difícil porque es difícil prever las necesidades de crecimiento y escalado de aplicaciones concretas.
Kubernetes puede simplificar la previsión de futuros costes de computación. Para entender por qué esto es cierto, considera el escalado de tres equipos: A, B y C. Históricamente has visto que el crecimiento de cada equipo es muy variable y, por tanto, difícil de predecir. Si aprovisionas máquinas individuales para cada servicio, no tienes más remedio que hacer previsiones basadas en el crecimiento máximo previsto para cada servicio, ya que las máquinas dedicadas a un equipo no pueden utilizarse para otro equipo. En cambio, si utilizas Kubernetes para desacoplar los equipos de las máquinas concretas que utilizan, puedes prever el crecimiento basándote en el crecimiento agregado de los tres servicios. Combinar tres tasas de crecimiento variables en una única tasa de crecimiento reduce el ruido estadístico y produce una previsión más fiable del crecimiento previsto. Además, desacoplar los equipos de las máquinas concretas significa que los equipos pueden compartir partes fraccionarias de las máquinas de los demás, lo que reduce aún más los gastos generales asociados a la previsión del crecimiento de los recursos informáticos.
Por último, Kubernetes hace posible el escalado automático (tanto hacia arriba como hacia abajo) de los recursos. Especialmente en un entorno de nube en el que se pueden crear nuevas máquinas a través de las API, combinar Kubernetes con el autoescalado tanto de las aplicaciones como de los propios clústeres significa que siempre puedes ajustar tus costes a la carga actual.
Escalar los equipos de desarrollo con microservicios
Como se ha señalado en diversas investigaciones, el tamaño ideal de un equipo es el de "dos pizzas", es decir, entre seis y ocho personas. Los equipos más grandes tienden a sufrir problemas de jerarquía, poca visibilidad y luchas internas, que dificultan la agilidad y el éxito.
Sin embargo, muchos proyectos requieren muchos más recursos para tener éxito y alcanzar sus objetivos. En consecuencia, existe una tensión entre el tamaño ideal del equipo para la agilidad y el tamaño necesario del equipo para los objetivos finales del producto.
La solución común a esta tensión ha sido el desarrollo de equipos desacoplados, orientados al servicio, que construyen cada uno un único microservicio. Cada pequeño equipo es responsable del diseño y entrega de un servicio que es consumido por otros pequeños equipos. La agregación de todos estos servicios proporciona, en última instancia, la implementación de la superficie global del producto.
Kubernetes proporciona numerosas abstracciones y API que facilitan la construcción de estas arquitecturas de microservicios desacoplados:
-
Los pods, o grupos de contenedores, pueden agrupar imágenes de contenedores desarrolladas por distintos equipos en una única unidad desplegable.
-
Los servicios de Kubernetes proporcionan equilibrio de carga, nomenclatura y descubrimiento para aislar un microservicio de otro.
-
Los espacios de nombres proporcionan aislamiento y control de acceso, de modo que cada microservicio puede controlar el grado en que otros servicios interactúan con él.
-
Los objetosIngress proporcionan un frontend fácil de usar que puede combinar varios microservicios en una única superficie API externalizada.
Por último, desacoplar la imagen del contenedor de la aplicación y la máquina significa que diferentes microservicios pueden colocarse en la misma máquina sin interferir unos con otros, reduciendo la sobrecarga y el coste de las arquitecturas de microservicios. Las funciones de comprobación de estado y despliegue de Kubernetes garantizan un enfoque coherente del despliegue y la fiabilidad de las aplicaciones, lo que asegura que la proliferación de equipos de microservicios no se traduzca también en una proliferación de enfoques diferentes del ciclo de vida y las operaciones de producción de los servicios.
Separación de intereses para la coherencia y la ampliación
Además de la coherencia que Kubernetes aporta a las operaciones, el desacoplamiento y la separación de preocupaciones que produce la pila de Kubernetes conducen a una coherencia significativamente mayor para los niveles inferiores de tu infraestructura. Esto te permite escalar las operaciones de infraestructura para gestionar muchas máquinas con un único equipo pequeño y centrado. Hemos hablado largo y tendido sobre la disociación entre el contenedor de aplicaciones y la máquina/sistema operativo (SO), pero un aspecto importante de esta disociación es que la API de orquestación de contenedores se convierte en un contrato nítido que separa las responsabilidades del operador de aplicaciones del operador de orquestación de clústeres. A esto lo llamamos la línea "ni mi mono, ni mi circo". El desarrollador de la aplicación confía en el acuerdo de nivel de servicio (SLA) proporcionado por la API de orquestación de contenedores, sin preocuparse por los detalles de cómo se consigue este SLA. Del mismo modo, el ingeniero de fiabilidad de la API de orquestación de contenedores se centra en cumplir el ANS de la API de orquestación, sin preocuparse de las aplicaciones que se ejecutan sobre ella.
Desacoplar las preocupaciones significa que un pequeño equipo que ejecute un clúster de Kubernetes puede ser responsable de dar soporte a cientos o incluso miles de equipos que ejecuten aplicaciones dentro de ese clúster(Figura 1-1). Del mismo modo, un pequeño equipo puede ser responsable de docenas (o más) de clústeres que se ejecutan en todo el mundo. Es importante señalar que la misma disociación de contenedores y SO permite a los ingenieros de fiabilidad del SO centrarse en el SLA del SO de cada máquina. Esto se convierte en otra línea de responsabilidad separada, en la que los operadores de Kubernetes confían en el SLA del SO, y los operadores del SO se preocupan únicamente de cumplir ese SLA. De nuevo, esto te permite escalar un pequeño equipo de expertos en SO a una flota de miles de máquinas.
Por supuesto, dedicar incluso un pequeño equipo a gestionar un SO está fuera del alcance de muchas organizaciones. En estos entornos, un servicio gestionado de Kubernetes (KaaS) proporcionado por un proveedor de nube pública es una gran opción. A medida que Kubernetes se ha hecho cada vez más omnipresente, KaaS también se ha hecho cada vez más disponible, hasta el punto de que ahora se ofrece en casi todas las nubes públicas. Por supuesto, utilizar KaaS tiene algunas limitaciones, ya que el operador toma decisiones por ti sobre cómo se construyen y configuran los clústeres de Kubernetes. Por ejemplo, muchas plataformas KaaS desactivan las funciones alfa porque pueden desestabilizar el clúster gestionado.
Además de un servicio Kubernetes totalmente gestionado, existe un próspero ecosistema de empresas y proyectos que ayudan a instalar y gestionar Kubernetes. Existe todo un espectro de soluciones entre hacerlo "por las malas" y un servicio totalmente gestionado.
En consecuencia, utilizar KaaS o gestionarlo tú mismo (o algo intermedio) es una decisión que cada usuario debe tomar en función de las habilidades y exigencias de su situación. A menudo, para las organizaciones pequeñas, KaaS proporciona una solución fácil de usar que les permite centrar su tiempo y energía en crear el software que respalde su trabajo, en lugar de gestionar un clúster. Para las organizaciones más grandes que pueden permitirse un equipo dedicado a gestionar su clúster de Kubernetes, gestionarlo de esa manera puede tener sentido, ya que permite una mayor flexibilidad en términos de capacidades y operaciones del clúster.
Abstraer tu infraestructura
El objetivo de la nube pública es proporcionar a los desarrolladoresuna infraestructura fácil de usar y de autoservicio para consumir. Sin embargo, con demasiada frecuencia las API de la nube están orientadas a reflejar la infraestructura que los informáticos esperan (por ejemplo, "máquinas virtuales"), y no los conceptos (por ejemplo, "aplicaciones") que los desarrolladores quieren consumir. Además, en muchos casos la nube viene con detalles particulares de implementación o servicios que son específicos del proveedor de la nube. Consumir directamente estas API dificulta la ejecución de tu aplicación en varios entornos, o la dispersión entre la nube y los entornos físicos.
El paso a API de contenedores orientadas a aplicaciones, como Kubernetes, tiene dos ventajas concretas. En primer lugar, como hemos descrito anteriormente, separa a los desarrolladores de máquinas específicas. Esto facilita la función de TI orientada a las máquinas, ya que éstas pueden añadirse simplemente en conjunto para escalar el clúster, y en el contexto de la nube también permite un alto grado de portabilidad, ya que los desarrolladores consumen una API de nivel superior que se implementa en términos de las API específicas de la infraestructura de la nube.
Cuando tus desarrolladores construyen sus aplicaciones en términos de imágenes de contenedor y las implementan en términos de API portátiles de Kubernetes, transferir tu aplicación entre entornos, o incluso ejecutarla en entornos híbridos, es simplemente cuestión de enviar la configuración declarativa a un nuevo clúster. Kubernetes dispone de una serie de complementos que pueden abstraerte de una nube concreta. Por ejemplo, los servicios de Kubernetes saben cómo crear equilibradores de carga en las principales nubes públicas, así como en distintas infraestructuras privadas y físicas. Del mismo modo, los PersistentVolumes y PersistentVolumeClaims de Kubernetes pueden utilizarse para abstraer tus aplicaciones de implementaciones de almacenamiento específicas. Por supuesto, para lograr esta portabilidad, tienes que evitar los servicios gestionados en la nube (por ejemplo, DynamoDB de Amazon, Cosmos DB de Azure o Cloud Spanner de Google), lo que significa que te verás obligado a implementar y gestionar soluciones de almacenamiento de código abierto como Cassandra, MySQL o MongoDB.
En conjunto, construir sobre las abstracciones orientadas a aplicaciones de Kubernetes garantiza que el esfuerzo que dedicas a construir, implementar y gestionar tu aplicación sea realmente portátil en una amplia variedad de entornos.
Eficacia
Además de las ventajas para los desarrolladores y para la gestión de TI que ofrecen los contenedores y Kubernetes, la abstracción tiene también un beneficio económico concreto. Como los desarrolladores ya no piensan en términos de máquinas, sus aplicaciones pueden colocarse en las mismas máquinas sin que ello afecte a las propias aplicaciones. Esto significa que las tareas de varios usuarios pueden empaquetarse apretadamente en menos máquinas.
La eficiencia puede medirse por la relación entre el trabajo útil realizado por una máquina o proceso y la cantidad total de energía gastada en hacerlo. Cuando se trata de implementar y gestionar aplicaciones, muchas de las herramientas y procesos disponibles (por ejemplo, los scripts bash, las actualizaciones de apt
o la gestión imperativa de la configuración) son algo ineficientes. Cuando se habla de eficiencia, suele ser útil pensar tanto en el coste monetario de hacer funcionar un servidor como en el coste humano necesario para gestionarlo.
El funcionamiento de un servidor conlleva un coste basado en el uso de energía, los requisitos de refrigeración, el espacio del centro de datos y la potencia de cálculo bruta. Una vez que un servidor se monta y se enciende (o se pincha y se pone en marcha), el contador empieza a correr literalmente. Cualquier tiempo ocioso de la CPU es dinero perdido. Por lo tanto, se convierte en parte de las responsabilidades del administrador del sistema mantener la utilización en niveles aceptables, lo que requiere una gestión continua. Aquí es donde entran en juego los contenedores y el flujo de trabajo de Kubernetes. Kubernetes proporciona herramientas que automatizan la distribución de aplicaciones a través de un clúster de máquinas, garantizando niveles de utilización superiores a los posibles con las herramientas tradicionales.
Otro aumento de la eficiencia se debe al hecho de que el entorno de pruebas de un desarrollador puede crearse de forma rápida y barata como un conjunto de contenedores que se ejecutan en una vista personal de un clúster compartido de Kubernetes (utilizando una función denominada espacios de nombres). Antes, poner en marcha un clúster de pruebas para un desarrollador podía significar poner en marcha tres máquinas. Con Kubernetes, es sencillo hacer que todos los desarrolladores compartan un único clúster de pruebas, agregando su uso a un conjunto mucho menor de máquinas. Reducir el número total de máquinas utilizadas aumenta a su vez la eficiencia de cada sistema: puesto que se utiliza una mayor parte de los recursos (CPU, RAM, etc.) de cada máquina individual, el coste total de cada contenedor es mucho menor.
Reducir el coste de las instancias de desarrollo en tu pila permite prácticas de desarrollo que antes podrían haber sido prohibitivas desde el punto de vista de los costes. Por ejemplo, con tu aplicación desplegada a través de Kubernetes, es posible desplegar y probar cada commit aportado por cada desarrollador en toda tu pila.
Cuando el coste de cada implementación se mide en términos de un pequeño número de contenedores, en lugar de múltiples máquinas virtuales (VM) completas, el coste en que incurres por dichas pruebas es drásticamente inferior. Volviendo al valor original de Kubernetes, este aumento de las pruebas también incrementa la velocidad, ya que dispones de señales sólidas en cuanto a la fiabilidad de tu código, así como de la granularidad de detalle necesaria para identificar rápidamente dónde puede haberse introducido un problema.
Por último, como se ha mencionado en secciones anteriores, el uso del escalado automático para añadir recursos cuando sean necesarios, pero eliminarlos cuando no lo sean, también puede utilizarse para impulsar la eficiencia general de tus aplicaciones, manteniendo al mismo tiempo sus características de rendimiento requeridas.
Ecosistema Nativo en la Nube
Kubernetes se diseñó desde el principio para ser un entorno extensible y una comunidad amplia y acogedora. Estos objetivos de diseño y su ubicuidad en tantos entornos informáticos han dado lugar a un vibrante y amplio ecosistema de herramientas y servicios que han crecido en torno a Kubernetes. Siguiendo el ejemplo de Kubernetes (y de Docker y Linux antes que él), la mayoría de estos proyectos son también de código abierto. Esto significa que un desarrollador que empiece a construir no tiene que empezar desde cero. En los años transcurridos desde su lanzamiento, se han creado para Kubernetes herramientas para casi todas las tareas, desde el aprendizaje automático hasta el desarrollo continuo y los modelos de programación sin servidor. De hecho, en muchos casos el reto no es encontrar una solución potencial, sino decidir cuál de las muchas soluciones es la más adecuada para la tarea. La riqueza de herramientas del ecosistema nativo de la nube se ha convertido en sí misma en una razón de peso para que muchas personas adopten Kubernetes. Cuando aprovechas el ecosistema nativo de la nube, puedes utilizar proyectos creados y respaldados por la comunidad para casi todas las partes de tu sistema, lo que te permite centrarte en el desarrollo de la lógica empresarial central y los servicios que son exclusivamente tuyos.
Como ocurre con cualquier ecosistema de código abierto, el principal reto es la variedad de soluciones posibles y el hecho de que a menudo hay una falta de integración de extremo a extremo. Una posible forma de navegar por esta complejidad es la orientación técnica de la Cloud Native Computing Foundation (CNCF). La CNCF actúa como un hogar neutral para el código y la propiedad intelectual de los proyectos nativos de la nube. Tiene tres niveles de madurez de proyecto para ayudar a guiar tu adopción de proyectos nativos de la nube. La mayoría de los proyectos del CNCF se encuentran en la fase de sandbox. Sandbox indica que un proyecto está aún en una fase temprana de desarrollo, y no se recomienda su adopción a menos que seas uno de los primeros en adoptarlo y/o estés interesado en contribuir a su desarrollo. La siguiente etapa de madurez es la incubación. Los proyectos en incubación son aquellos que han demostrado su utilidad y estabilidad mediante la adopción y el uso en producción; sin embargo, aún están desarrollando y haciendo crecer sus comunidades. Mientras que hay cientos de proyectos sandbox, apenas hay más de 20 proyectos en incubación. La etapa final de los proyectos del CNCF es la graduación. Estos proyectos están totalmente maduros y ampliamente adoptados. Sólo hay unos pocos proyectos graduados, incluido el propio Kubernetes.
Otra forma de navegar por el ecosistema nativo de la nube es mediante la integración con Kubernetes-as-a-Service. En este momento, la mayoría de las ofertas de KaaS de también tienen servicios adicionales a través de proyectos de código abierto del ecosistema nativo de la nube. Como estos servicios están integrados en productos soportados por la nube, puedes estar seguro de que los proyectos están maduros y listos para la producción.
Resumen
Kubernetes se creó para cambiar radicalmente la forma en que se crean e implementan las aplicaciones en la nube. Fundamentalmente, se diseñó para dar a los desarrolladores más velocidad, eficiencia y agilidad. En este momento, muchos de los servicios y aplicaciones de Internet que utilizas a diario se ejecutan sobre Kubernetes. Probablemente ya eres usuario de Kubernetes, ¡sólo que no lo sabías! Esperamos que este capítulo te haya dado una idea de por qué deberías implementar tus aplicaciones utilizando Kubernetes. Ahora que estás convencido de ello, los capítulos siguientes te enseñarán cómo implementar tus aplicaciones.
1 Brendan Burns y otros, "Borg, Omega y Kubernetes: Lecciones aprendidas de tres sistemas de gestión de contenedores a lo largo de una década", ACM Queue 14 (2016): 70-93, disponible en https://oreil.ly/ltE1B.
Get Kubernetes: Up and Running, 3ª 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.