Requisitos para desarrollar una aplicación en Kubernetes

Hoy planeo hablar sobre cómo escribir aplicaciones y cuáles son los requisitos para que su aplicación funcione bien en Kubernetes. Para que no haya dolores de cabeza con la aplicación, para que no tenga que inventar y construir "grietas" a su alrededor, y todo funcione como lo concibió el propio Kubernetes.

Esta conferencia es parte de "Escuela nocturna Slurm en Kubernetes" Puedes consultar las conferencias teóricas abiertas de la Escuela Vespertina. en Youtube, agrupados en una lista de reproducción. Para aquellos que prefieren el texto al vídeo, hemos preparado este artículo.

Mi nombre es Pavel Selivanov, actualmente soy el ingeniero líder de DevOps en Mail.ru Cloud Solutions, creamos nubes, gestionamos kubernetes, etc. Mis tareas ahora incluyen asistencia en el desarrollo, implementación de estas nubes, implementación de las aplicaciones que escribimos y desarrollo directo de las herramientas que brindamos a nuestros usuarios.

Requisitos para desarrollar una aplicación en Kubernetes

He estado haciendo DevOps, creo, durante los últimos tres años, probablemente. Pero, en principio, he estado haciendo lo que hace DevOps probablemente durante unos cinco años. Antes de eso, me dedicaba principalmente a tareas administrativas. Empecé a trabajar con Kubernetes hace mucho tiempo; probablemente hayan pasado unos cuatro años desde que comencé a trabajar con él.

En general, comencé cuando Kubernetes tenía la versión 1.3, probablemente, y tal vez la 1.2, cuando aún estaba en su infancia. Ahora ya no está en su infancia, y es obvio que existe una gran demanda en el mercado de ingenieros a quienes les gustaría poder hacer Kubernetes. Y las empresas tienen una demanda muy alta de estas personas. Por eso, de hecho, apareció esta conferencia.

Si hablamos del plan de lo que hablaré, se ve así, entre paréntesis está escrito (TL;DR) - “demasiado largo; no leer". Mi presentación de hoy consistirá en listas interminables.

Requisitos para desarrollar una aplicación en Kubernetes

De hecho, a mí mismo no me gustan esas presentaciones cuando se hacen, pero este es un tema tal que cuando estaba preparando esta presentación, simplemente no entendí cómo organizar esta información de otra manera.

Porque, en general, esta información es "ctrl+c, ctrl+v", de, entre otras cosas, nuestra Wiki en la sección DevOps, donde escribimos los requisitos para los desarrolladores: "chicos, para que iniciemos su aplicación en Kubernetes, debería ser así."

Por eso la presentación resultó ser una lista tan grande. Lo siento. Intentaré contar todo lo posible para que no resulte aburrido a ser posible.

Lo que vamos a ver ahora:

  • estos son, en primer lugar, registros (¿registros de aplicaciones?), qué hacer con ellos en Kubernetes, qué hacer con ellos, cuáles deberían ser;
  • qué hacer con las configuraciones en Kubernetes, cuáles son las mejores y peores formas de configurar una aplicación para Kubernetes;
  • Hablemos de qué son las comprobaciones de accesibilidad en general, cómo deberían verse;
  • hablemos de lo que es un cierre elegante;
  • volvamos a hablar de recursos;
  • Toquemos una vez más el tema del almacenamiento de datos;
  • y al final les diré cómo se llama esta misteriosa aplicación nativa de la nube. Cloudnativeness, como adjetivo de este término.

Registros

Sugiero comenzar con los registros: dónde deben colocarse estos registros en Kubernetes. Ahora ha iniciado una aplicación en Kubernetes. Según los clásicos, anteriormente las aplicaciones siempre escribían registros en algún lugar de un archivo. Las aplicaciones defectuosas escribieron registros en un archivo en el directorio de inicio del desarrollador que inició la aplicación. Las buenas aplicaciones escribieron registros en un archivo en algún lugar de /var/log.

Requisitos para desarrollar una aplicación en Kubernetes

En consecuencia, además, los buenos administradores tenían algunas cosas configuradas en sus infraestructuras para que estos registros pudieran rotar: el mismo rsyslog, que mira estos registros y cuando les sucede algo, hay muchos, crea copias de seguridad y coloca los registros allí. , elimina archivos antiguos, de más de una semana, seis meses y algunos más. En teoría, deberíamos tener disposiciones para que simplemente porque la aplicación escriba registros, el espacio en los servidores de producción (¿servidores de combate?) no se agote. Y, en consecuencia, toda la producción no se detuvo a causa de los troncos.

Cuando nos trasladamos al mundo de Kubernetes y ejecutamos lo mismo allí, lo primero a lo que podemos prestar atención es al hecho de que las personas, a medida que escriben registros en un archivo, continúan escribiéndolos.

Resulta que si hablamos de Kubernetes, el lugar correcto para escribir registros en algún lugar desde un contenedor acoplable es simplemente escribirlos desde la aplicación en el llamado Stdout/Stderr, es decir, los flujos de salida estándar del sistema operativo, error estándar. producción . Esta es la forma más correcta, sencilla y lógica de poner logs en principio en Docker y concretamente en Kubernetis. Porque si su aplicación escribe registros en Stdout/Stderr, entonces depende de Docker y el complemento de Kubernetes decidir qué hacer con estos registros. Docker creará de forma predeterminada sus archivos especiales en formato JSON.

Aquí surge la pregunta, ¿qué harás a continuación con estos registros? La forma más fácil es clara, tenemos la capacidad de hacerlo. kubectl logs y mire estos registros de estas “vainas”. Pero probablemente esta no sea una muy buena opción: es necesario hacer algo más con los registros.

Por ahora, hablemos al mismo tiempo, ya que tocamos el tema de los registros, sobre cómo deberían verse los registros. Es decir, esto no se aplica directamente a Kubernetes, pero cuando empecemos a pensar en qué hacer con los registros, sería bueno pensar en esto también.

Necesitamos algún tipo de herramienta, de manera amigable, que tome estos registros que nuestra ventana acoplable coloca en sus archivos y los envíe a alguna parte. En general, generalmente lanzamos algún tipo de agente dentro de Kubernetes en forma de DaemonSet, un recopilador de registros, al que simplemente se le dice dónde se encuentran los registros que recopila Docker. Y este agente recopilador simplemente los toma, tal vez incluso de alguna manera los analiza a lo largo del camino, tal vez los enriquece con alguna metainformación adicional y, en última instancia, los envía para su almacenamiento en algún lugar. Allí ya son posibles variaciones. El más común es probablemente Elasticsearch, donde puede almacenar registros y recuperarlos cómodamente desde allí. Luego, utilizando una solicitud, utilizando Kibana, por ejemplo, cree gráficos basados ​​en ellos, cree alertas basadas en ellos, etc.

La idea más importante, quiero repetirla nuevamente, es que dentro de Docker, en particular dentro de Kubernetes, almacenar sus registros en un archivo es una muy mala idea.

Porque, en primer lugar, es difícil colocar los registros dentro del contenedor en un archivo. Primero debe ingresar al contenedor, ejecutar allí y luego mirar los registros. El siguiente punto es que si tiene registros en un archivo, los contenedores generalmente tienen un entorno minimalista y no hay utilidades que generalmente se necesitan para el trabajo normal con registros. Entiérralos, míralos, ábrelos en un editor de texto. El siguiente momento es cuando tenemos registros en un archivo dentro de un contenedor, si este contenedor se elimina, los registros morirán junto con él. En consecuencia, cualquier reinicio del contenedor significa que no hay más registros. De nuevo, mala opción.

Y el último punto es que dentro de los contenedores normalmente tienes tu aplicación y eso es todo; suele ser el único proceso en ejecución. No se habla en absoluto de ningún proceso que rote archivos con sus registros. Tan pronto como los registros comiencen a escribirse en un archivo, esto significa que, disculpe, comenzaremos a perder el servidor de producción. Porque, en primer lugar, son difíciles de encontrar, nadie los rastrea y nadie los controla; en consecuencia, el archivo crece sin cesar hasta que simplemente se agota el espacio en el servidor. Por lo tanto, repito que iniciar sesión en Docker, en particular en Kubernetes, en un archivo es una mala idea.

El siguiente punto, aquí quiero volver a hablar de esto: dado que tocamos el tema de los registros, sería bueno hablar sobre cómo deben verse los registros para que sea conveniente trabajar con ellos. Como dije, el tema no está directamente relacionado con Kubernetes, pero se relaciona muy bien con el tema de DevOps. Sobre el tema de la cultura de desarrollo y la amistad entre estos dos departamentos diferentes: Dev y Ops, para que todos se sientan cómodos.

Esto significa que, hoy en día, lo ideal es que los registros se escriban en formato JSON. Si tiene alguna aplicación propia incomprensible, que escribe registros en formatos incomprensibles porque inserta algún tipo de impresión o algo así, entonces es hora de buscar en Google algún tipo de marco, algún tipo de contenedor que le permita implementar el registro normal; habilite los parámetros de registro en JSON allí, debido a que JSON es un formato simple, analizarlo es simple.

Si su JSON no funciona de acuerdo con algún criterio, nadie sabe cuál, entonces al menos escriba registros en un formato que pueda analizarse. Aquí, más bien, vale la pena pensar en el hecho de que, por ejemplo, si está ejecutando un montón de contenedores o simplemente procesos con nginx, y cada uno tiene su propia configuración de registro, entonces probablemente le resultará muy inconveniente analizarlos. Porque para cada nueva instancia de nginx necesitas escribir tu propio analizador, porque escriben registros de manera diferente. Nuevamente, probablemente valió la pena pensar en asegurarse de que todas estas instancias de nginx tuvieran la misma configuración de registro y escribieran todos sus registros de manera absolutamente uniforme. Lo mismo se aplica a absolutamente todas las aplicaciones.

Al final, también quiero echar más leña al fuego de que, idealmente, se deberían evitar los registros en formato de varias líneas. Esta es la cuestión: si alguna vez ha trabajado con recopiladores de registros, lo más probable es que haya visto lo que le prometen: que pueden trabajar con registros de varias líneas, saber cómo recopilarlos, etc. De hecho, en mi opinión, hoy en día ni un solo recopilador puede recopilar registros de varias líneas de forma normal, completa y sin errores. De forma humana, para que sea cómodo y sin errores.

Requisitos para desarrollar una aplicación en Kubernetes

Pero el seguimiento de la pila son siempre registros de varias líneas y cómo evitarlos. La pregunta aquí es que un registro es un registro de un evento y stactrace no es en realidad un registro. Si recopilamos registros y los colocamos en algún lugar de Elasticsearch y luego dibujamos gráficos a partir de ellos, creamos algunos informes de la actividad del usuario en su sitio, cuando obtenga un seguimiento de la pila, significa que está sucediendo algo inesperado, una situación no controlada en su aplicación. Y tiene sentido cargar automáticamente un seguimiento de la pila en algún lugar de un sistema que pueda rastrearlos.

Este es un software (el mismo Sentry) que está diseñado específicamente para funcionar con seguimiento de pila. Puede crear inmediatamente tareas automatizadas, asignarlas a alguien, alertar cuando se producen stacttraces, agrupar estas stacttraces por un tipo, etc. En principio, no tiene mucho sentido hablar de stactraces cuando hablamos de logs, porque después de todo son cosas diferentes con propósitos diferentes.

Configuración

A continuación hablamos de la configuración en Kubernetes: qué hacer con ella y cómo se deben configurar las aplicaciones dentro de Kubernetes. En general, suelo decir que Docker no se trata de contenedores. Todo el mundo sabe que Docker se trata de contenedores, incluso aquellos que no han trabajado mucho con Docker. Repito, Docker no se trata de contenedores.

Docker, en mi opinión, se trata de estándares. Y existen estándares para prácticamente todo: estándares para crear su aplicación, estándares para instalar su aplicación.

Requisitos para desarrollar una aplicación en Kubernetes

Y esto, lo usamos antes, se volvió especialmente popular con la llegada de los contenedores, se llama variables ENV (de entorno), es decir, variables de entorno que están en su sistema operativo. Generalmente, esta es una forma ideal de configurar su aplicación, porque si tiene aplicaciones en JAVA, Python, Go, Perl, Dios no lo quiera, y todas pueden leer las variables del host de la base de datos, el usuario de la base de datos y la contraseña de la base de datos, entonces es ideal. Tienes aplicaciones en cuatro idiomas diferentes configuradas en el plan de base de datos de la misma forma. No hay más configuraciones diferentes.

Todo se puede configurar usando variables ENV. Cuando hablamos de Kubernetes, existe una excelente manera de declarar variables ENV directamente dentro de Deployment. En consecuencia, si estamos hablando de datos secretos, podemos insertar inmediatamente datos secretos de las variables ENV (contraseñas de bases de datos, etc.) en un secreto, crear un clúster secreto e indicar en la descripción de ENV en Implementación que no estamos declarando directamente. el valor de esta variable y el valor de esta variable de contraseña de la base de datos se leerán del secreto. Este es el comportamiento estándar de Kubernetes. Y esta es la opción más ideal para configurar tus aplicaciones. Sólo a nivel de código, nuevamente esto se aplica a los desarrolladores. Si es DevOps, puede preguntar: “Chicos, enseñen a su aplicación a leer variables de entorno. Y todos seremos felices”.

Si todos en la empresa leen las mismas variables de entorno con el mismo nombre, entonces es genial. Para que no suceda que algunos estén esperando la base de datos de Postgres, otros estén esperando el nombre de la base de datos, otros estén esperando algo más, otros estén esperando un dbn de algún tipo, para que, en consecuencia, haya uniformidad.

El problema surge cuando tienes tantas variables de entorno que simplemente abres Deployment y hay quinientas líneas de variables de entorno. En este caso, simplemente ha superado las variables de entorno y ya no necesita torturarse. En este caso, tendría sentido empezar a utilizar configuraciones. Es decir, entrene su aplicación para usar configuraciones.

La única pregunta es que las configuraciones no son lo que crees. Config.pi no es una configuración que sea cómoda de usar. O alguna configuración en su propio formato, alternativamente dotada; esta tampoco es la configuración a la que me refiero.

De lo que hablo es de configuración en formatos aceptables, es decir, con diferencia el estándar más popular es el estándar .yaml. Está claro cómo leerlo, es legible para humanos, está claro cómo leerlo desde la aplicación.

En consecuencia, además de YAML, también puede, por ejemplo, utilizar JSON; el análisis es tan conveniente como YAML en términos de leer la configuración de la aplicación desde allí. Es notablemente más incómodo para la gente leer. Puedes probar el formato, al inicio. Es bastante cómodo de leer, desde un punto de vista humano, pero puede resultar inconveniente procesarlo automáticamente, en el sentido de que si alguna vez desea generar sus propias configuraciones, es posible que el formato ini ya sea incómodo de generar.

Pero en cualquier caso, sea cual sea el formato que elijas, la cuestión es que desde el punto de vista de Kubernetes es muy conveniente. Puede poner toda su configuración dentro de Kubernetes, en ConfigMap. Y luego tome este mapa de configuración y solicite que se monte dentro de su pod en algún directorio específico, donde su aplicación leerá la configuración de este mapa de configuración como si fuera solo un archivo. De hecho, esto es lo que es bueno hacer cuando tienes muchas opciones de configuración en tu aplicación. O es simplemente una especie de estructura compleja, hay anidamiento.

Si tiene un mapa de configuración, entonces puede enseñarle a su aplicación, por ejemplo, a rastrear automáticamente los cambios en el archivo donde está montado el mapa de configuración y también recargar automáticamente su aplicación cuando cambian las configuraciones. En general, esta sería una opción ideal.

Nuevamente, ya hablé de esto: la información secreta no está en el mapa de configuración, la información secreta no está en las variables, la información secreta no está en los secretos. A partir de ahí, conecte esta información secreta con la diplomacia. Por lo general, almacenamos todas las descripciones de los objetos, implementaciones, mapas de configuración y servicios de Kubernetes en git. En consecuencia, poner la contraseña de la base de datos en git, incluso si es su git, que tiene internamente en la empresa, es una mala idea. Porque, como mínimo, git recuerda todo y simplemente eliminar las contraseñas de allí no es tan fácil.

Chequeo

El siguiente punto es esto llamado Control de salud. En general, un control de estado consiste simplemente en comprobar que su aplicación está funcionando. Al mismo tiempo, la mayoría de las veces estamos hablando de ciertas aplicaciones web, para las cuales, en consecuencia, desde el punto de vista del control de estado (es mejor no traducir aquí y más), esta será una URL especial, que procesan como un estándar, normalmente lo hacen /health.

En consecuencia, al acceder a esta URL, nuestra aplicación dice "sí, está bien, todo está bien para mí, 200" o "no, no todo está bien para mí, unos 500". En consecuencia, si nuestra aplicación no es http, no es una aplicación web, ahora estamos hablando de algún tipo de demonio, podemos descubrir cómo realizar comprobaciones de estado. Es decir, no es necesario, si la aplicación no es http, entonces todo funciona sin un control de estado y esto no se puede hacer de ninguna manera. Puede actualizar periódicamente cierta información en el archivo, puede crear algún comando especial para su demonio, como, daemon status, que dirá "sí, todo está bien, el demonio está funcionando, está vivo".

¿Para qué sirve? Lo primero y más obvio es probablemente por qué se necesita un control de estado: para comprender que la aplicación está funcionando. Quiero decir, es simplemente estúpido, cuando está activo ahora, parece que está funcionando, así que puedes estar seguro de que está funcionando. Y resulta que la aplicación se está ejecutando, el contenedor se está ejecutando, la instancia está funcionando, todo está bien, y luego los usuarios ya cortaron todos los números de teléfono del soporte técnico y dijeron "¿qué estás..., tú?" Me quedé dormido, nada funciona”.

Un control de estado es una forma de ver, desde el punto de vista del usuario, que funciona. Uno de los métodos. Pongámoslo de esta manera. Desde el punto de vista de Kubernetes, esta también es una forma de comprender cuándo se inicia la aplicación, porque entendemos que existe una diferencia entre cuándo se inició, creó e inició el contenedor y cuándo se inició la aplicación directamente en este contenedor. Porque si tomamos una aplicación Java promedio e intentamos iniciarla en el Dock, durante cuarenta segundos, o incluso un minuto, o incluso diez, puede comenzar bien. En este caso, al menos puedes llamar a sus puertos, no responderá allí, es decir, aún no está listo para recibir tráfico.

Nuevamente, con la ayuda de una verificación de estado y con la ayuda del hecho de que estamos pasando aquí, podemos entender en Kubernetes que no solo el contenedor se ha levantado en la aplicación, sino que la aplicación en sí se ha iniciado, ya responde a la verificación de estado, lo que significa que podemos enviar tráfico allí.

Requisitos para desarrollar una aplicación en Kubernetes

A lo que me refiero ahora se llaman pruebas de preparación/actividad dentro de Kubernetes; en consecuencia, nuestras pruebas de preparación son responsables de la disponibilidad de la aplicación en equilibrio. Es decir, si se realizan pruebas de preparación en la aplicación, entonces todo está bien, el tráfico del cliente irá a la aplicación. Si no se realizan pruebas de preparación, entonces la aplicación simplemente no participa, esta instancia en particular no participa en el equilibrio, se elimina del equilibrio y el tráfico del cliente no fluye. En consecuencia, se necesitan pruebas de Liveness dentro de Kubernetes para que, si la aplicación se bloquea, se pueda reiniciar. Si la prueba de vida no funciona para una aplicación declarada en Kubernetes, entonces la aplicación no solo se elimina del equilibrio, sino que se reinicia.

Y aquí hay un punto importante que me gustaría mencionar: desde un punto de vista práctico, la prueba de preparación generalmente se usa con más frecuencia y es más necesaria que la prueba de vida. Es decir, simplemente declarar sin pensar pruebas de preparación y de vida, porque Kubernetes puede hacer eso, y usemos todo lo que puede hacer, no es una muy buena idea. Te explicaré por qué. Porque el punto número dos en las pruebas es que sería una buena idea verificar el servicio subyacente en sus controles de salud. Esto significa que si tiene una aplicación web que proporciona cierta información, ésta, a su vez, naturalmente, debe tomarse de algún lugar. En una base de datos, por ejemplo. Bueno, guarda la información que entra en esta API REST en la misma base de datos. Luego, en consecuencia, si su chequeo de salud responde simplemente como contactado con slashhealth, la aplicación dice "200, está bien, todo está bien" y al mismo tiempo la base de datos de su aplicación es inaccesible y la aplicación de chequeo de salud dice "200, está bien, todo está bien". ” - Este es un mal control de salud. No es así como debería funcionar.

Es decir, su aplicación, cuando le llega una solicitud. /health, no solo responde “200, ok”, primero va, por ejemplo, a la base de datos, intenta conectarse a ella, hace algo muy básico allí, como seleccionar uno, simplemente verifica que haya una conexión en la base de datos. base de datos y puede consultar la base de datos. Si todo esto fue exitoso, entonces la respuesta es “200, ok”. Si no tiene éxito dice que hay un error, la base de datos no está disponible.

Por lo tanto, en este sentido, vuelvo nuevamente a las pruebas de preparación/vivacidad: por qué lo más probable es que necesite una prueba de preparación, pero la prueba de vida está en duda. Porque si describe los controles de salud exactamente como acabo de decir, resultará que no está disponible en la parte de instancia.в или со всех instanceen una base de datos, por ejemplo. Cuando declaró una prueba de preparación, nuestras comprobaciones de estado comenzaron a fallar y, en consecuencia, todas las aplicaciones desde las cuales no se puede acceder a la base de datos simplemente se desconectan del equilibrio y, de hecho, se "cuelgan" simplemente en un estado descuidado y esperan a que sus bases de datos se recuperen. trabajar.

Si hemos declarado una prueba de vida, imagínese, nuestra base de datos se ha roto y en su Kubernetes la mitad de todo comienza a reiniciarse porque la prueba de vida falla. Esto significa que necesitas reiniciar. Esto no es en absoluto lo que quieres, incluso tuve experiencia personal en la práctica. Teníamos una aplicación de chat escrita en JS y alimentada a una base de datos Mongo. Y el problema fue que fue al comienzo de mi trabajo con Kubernetes que describimos la preparación y la viveza de las pruebas basándose en el principio de que Kubernetes puede hacerlo, así que lo usaremos. En consecuencia, en algún momento Mongo se volvió un poco "aburrido" y la muestra empezó a fallar. En consecuencia, según la prueba de lluvia, las vainas comenzaron a “matar”.

Como entiendes, cuando los "matan", esto es un chat, es decir, hay muchas conexiones de clientes colgados en él. También se "eliminan" - no, no clientes, solo conexiones - no todos al mismo tiempo, y debido al hecho de que no se eliminan al mismo tiempo, algunos antes, otros después, no comienzan al mismo tiempo. tiempo. Además del azar estándar, no podemos predecir con una precisión de milisegundos la hora de inicio de la aplicación cada vez, por lo que lo hacen una instancia a la vez. Un infospot sube, se suma al equilibrio, todos los clientes vienen allí, no puede soportar tal carga, porque está solo y, en términos generales, hay una docena de ellos trabajando allí, y cae. El siguiente sube, toda la carga recae sobre él, él también cae. Bueno, estas caídas siguen cayendo en cascada. Al final, cómo se resolvió esto: simplemente tuvimos que detener estrictamente el tráfico de usuarios a esta aplicación, dejar que todas las instancias aumentaran y luego iniciar todo el tráfico de usuarios a la vez para que ya estuviera distribuido entre las diez instancias.

Si no fuera por el anuncio de esta prueba de vida, que obligaría a reiniciar todo, la aplicación lo habría manejado bien. Pero todo, desde el equilibrio, está deshabilitado para nosotros, porque las bases de datos son inaccesibles y todos los usuarios se han "caído". Luego, cuando esta base de datos esté disponible, todo se incluye en el equilibrio, pero no es necesario que las aplicaciones se inicien de nuevo y no hay necesidad de perder tiempo y recursos en esto. Todos ya están aquí, están listos para el tráfico, por lo que el tráfico simplemente se abre, todo está bien: la aplicación está en su lugar, todo sigue funcionando.

Por lo tanto, las pruebas de preparación y vida son diferentes, incluso más aún, teóricamente puedes hacer diferentes controles de salud, un tipo radios, un tipo liv, por ejemplo, y verificar diferentes cosas. Durante las pruebas de preparación, verifique sus backends. Y en una prueba de vida, por ejemplo, no se verifica desde el punto de vista de que la prueba de vida generalmente es solo una aplicación que responde, si es que es capaz de responder.

Porque una prueba de vida, en general, es cuando nos “estancamos”. Se ha iniciado un bucle sin fin o algo así y no se procesan más solicitudes. Por lo tanto, tiene sentido incluso separarlos e implementar en ellos una lógica diferente.

Respecto a lo que debes responder cuando te hacen una prueba, cuando haces controles de salud. Es realmente un dolor. Aquellos que estén familiarizados con esto probablemente se reirán, pero en serio, he visto servicios en mi vida que responden "200" en el XNUMX% de los casos. Es decir, quién tiene éxito. Pero al mismo tiempo en el cuerpo de la respuesta escriben “tal o cual error”.

Es decir, le llega el estado de respuesta: todo fue exitoso. Pero al mismo tiempo, debes analizar el cuerpo, porque el cuerpo dice "lo siento, la solicitud finalizó con un error" y esto es simplemente la realidad. Vi esto en la vida real.

Y para que a algunas personas no les resulte divertido y a otras les resulte muy doloroso, vale la pena seguir una regla simple. En controles de estado, y en principio cuando se trabaja con aplicaciones web.

Si todo salió bien, responda con la respuesta número doscientas. En principio, cualquier respuesta número dos centésimas le conviene. Si lees muy bien ragsy y sabes que algunos estados de respuesta son diferentes a otros, responde con los adecuados: 204, 5, 10, 15, lo que sea. Si no es muy bueno, entonces simplemente “dos cero cero”. Si todo va mal y el control de salud no responde, responda con un quinientos. Nuevamente, si comprende cómo responder, verá en qué se diferencian los diferentes estados de respuesta entre sí. Si no lo entiende, entonces 502 es su opción para responder a los controles de salud si algo sale mal.

Este es otro punto, quiero volver un poco sobre la verificación de los servicios subyacentes. Si comienza, por ejemplo, a verificar todos los servicios subyacentes que respaldan su aplicación, todo en general. Lo que obtenemos desde el punto de vista de la arquitectura de microservicios es el concepto de "bajo acoplamiento", es decir, cuando sus servicios dependen mínimamente entre sí. Si uno de ellos falla, todos los demás que no tengan esta funcionalidad simplemente seguirán funcionando. Algunas de las funciones simplemente no funcionan. En consecuencia, si unes todos los controles de salud entre sí, terminarás con una cosa cayendo en la infraestructura, y debido a que cayó, todos los controles de salud de todos los servicios también comenzarán a fallar, y hay más infraestructura en general para el arquitectura de microservicio completa No. Allí todo se oscureció.

Por lo tanto, quiero repetir nuevamente que es necesario verificar los servicios subyacentes, aquellos sin los cuales su aplicación en el cien por ciento de los casos no puede hacer su trabajo. Es decir, es lógico que si tiene una API REST a través de la cual el usuario guarda en la base de datos o recupera datos de la base de datos, entonces, en ausencia de una base de datos, no puede garantizar el trabajo con sus usuarios.

Pero si sus usuarios, cuando los saca de la base de datos, se enriquecen adicionalmente con otros metadatos, de otro backend, que ingresa antes de enviar una respuesta al frontend, y este backend no está disponible, esto significa que le da su responder sin ninguna parte de los metadatos.

A continuación, también tenemos uno de los problemas dolorosos al iniciar aplicaciones.

De hecho, esto no sólo se aplica a Kubernetes en general; simplemente sucedió que la cultura de algún tipo de desarrollo masivo y DevOps en particular comenzó a extenderse casi al mismo tiempo que Kubernetes. Por lo tanto, en general, resulta que necesita cerrar con gracia su aplicación sin Kubernetes. Incluso antes de Kubernetes, la gente hacía esto, pero con la llegada de Kubernetes, comenzamos a hablar de ello en masa.

Apagado elegante

En general, ¿qué es Graceful Shutdown y por qué es necesario? Esto se trata de cuando su aplicación falla por algún motivo, debe hacer app stop - o recibe, por ejemplo, una señal del sistema operativo, su aplicación debe comprenderla y hacer algo al respecto. El peor de los casos, por supuesto, es cuando su aplicación recibe un SIGTERM y dice "SIGTERM, esperemos, trabajemos, no hagamos nada". Esta es una opción francamente mala.

Requisitos para desarrollar una aplicación en Kubernetes

Una opción casi igualmente mala es cuando tu aplicación recibe un SIGTERM y dice "dijeron segterm, eso significa que estamos terminando, no he visto, no conozco ninguna solicitud de usuario, no sé qué tipo de solicitudes en las que estoy trabajando ahora mismo, decían SIGTERM, eso significa que estamos terminando " Esta también es una mala opción.

¿Qué opción es buena? El primer punto es tener en cuenta la finalización de las operaciones. Una buena opción es que tu servidor aún tenga en cuenta lo que hace si recibe un SIGTERM.

SIGTERM es un apagado suave, está especialmente diseñado, se puede interceptar a nivel de código, se puede procesar, digamos que ahora, espere, primero terminaremos el trabajo que tenemos y luego saldremos.

Desde la perspectiva de Kubernetes, esto es lo que parece. Cuando le decimos a un pod que se está ejecutando en el clúster de Kubernetes, "deténgase, salga", o se reinicia, o se produce una actualización cuando Kubernetes recrea los pods, Kubernetes envía exactamente el mismo mensaje SIGTERM al pod, espera algún tiempo, y este es el tiempo que espera, también está configurado, hay un parámetro tan especial en los diplomas y se llama Graceful ShutdownTimeout. Como comprenderás, no en vano se llama así, y no en vano estamos hablando de ello ahora.

Allí podemos decir específicamente cuánto tiempo debemos esperar entre el momento en que enviamos SIGTERM a la aplicación y cuando entendemos que la aplicación parece haberse vuelto loca por algo o está "atascada" y no va a terminar, y debemos envíalo SIGKILL, es decir, completa con esfuerzo su trabajo. Es decir, en consecuencia, tenemos algún tipo de demonio en ejecución, que procesa operaciones. Entendemos que en promedio nuestras operaciones en las que trabaja el demonio no duran más de 30 segundos a la vez. En consecuencia, cuando llega SIGTERM, entendemos que nuestro demonio puede, como máximo, finalizar 30 segundos después de SIGTERM. Lo escribimos, por ejemplo, 45 segundos por si acaso y decimos que SIGTERM. Después de eso esperamos 45 segundos. En teoría, durante este tiempo el demonio debería haber completado su trabajo y acabarse a sí mismo. Pero si de repente no pudo, significa que lo más probable es que esté atascado: ya no procesa nuestras solicitudes con normalidad. Y en 45 segundos puedes, de hecho, atraparlo con seguridad.

Y aquí, de hecho, se pueden tener en cuenta incluso 2 aspectos. En primer lugar, comprenda que si recibió una solicitud, comenzó a trabajar con ella de alguna manera y no le dio una respuesta al usuario, pero recibió SIGTERM, por ejemplo. Tiene sentido perfeccionarlo y darle una respuesta al usuario. Este es el punto número uno a este respecto. El punto número dos aquí es que si escribe su propia aplicación, generalmente construye la arquitectura de tal manera que reciba una solicitud para su aplicación, luego comienza a trabajar, comienza a descargar archivos de algún lugar, descarga una base de datos y todo eso. Eso. En general, su usuario, su solicitud se cuelga durante media hora y espera a que le responda; entonces, lo más probable es que necesite trabajar en la arquitectura. Es decir, simplemente tenga en cuenta incluso el sentido común de que si sus operaciones son cortas, entonces tiene sentido ignorar SIGTERM y modificarlo. Si sus operaciones son largas, entonces no tiene sentido ignorar SIGTERM en este caso. Tiene sentido rediseñar la arquitectura para evitar operaciones tan largas. Para que los usuarios no se queden esperando. No lo sé, haga algún tipo de websocket allí, haga ganchos inversos que su servidor ya enviará al cliente, cualquier otra cosa, pero no obligue al usuario a colgar durante media hora y simplemente espere una sesión hasta que Contéstale. Porque es impredecible dónde podría romperse.

Cuando finalice su aplicación, debe proporcionar algún código de salida apropiado. Es decir, si a su aplicación se le pidió que se cerrara, se detuviera y pudo detenerse normalmente, entonces no necesita devolver ningún tipo de código de salida 1,5,255, etc. Todo lo que no sea código cero, al menos en los sistemas Linux, de eso estoy seguro, se considera fallido. Es decir, se considera que su solicitud en este caso terminó con un error. En consecuencia, de manera amistosa, si su solicitud se completó sin errores, diga 0 en el resultado. Si su aplicación falla por algún motivo, diga "no 0" en el resultado. Y puedes trabajar con esta información.

Y la última opción. Es malo cuando tu usuario envía una solicitud y se cuelga durante media hora mientras la procesas. Pero, en general, también me gustaría decir lo que generalmente vale la pena por parte del cliente. No importa si tienes una aplicación móvil, front-end, etc. Hay que tener en cuenta que por lo general se puede cerrar la sesión del usuario, puede pasar cualquier cosa. Una solicitud puede enviarse, por ejemplo, sin procesarse y no recibir respuesta. Su interfaz o su aplicación móvil (cualquier interfaz en general, digámoslo así) debe tener esto en cuenta. Si trabajas con websockets, este es generalmente el peor dolor que he tenido.

Cuando los desarrolladores de algunos chats habituales no lo saben, resulta que el websocket puede romperse. Para ellos, cuando sucede algo en el proxy, simplemente cambiamos la configuración y se recarga. Naturalmente, en este caso todas las sesiones de larga duración se rompen. Los desarrolladores vienen corriendo hacia nosotros y nos dicen: "Chicos, ¿qué están haciendo? ¡El chat se ha roto para todos nuestros clientes!" Les decimos: “¿Qué estás haciendo? ¿Sus clientes no pueden volver a conectarse? Dicen: "No, necesitamos que las sesiones no se rompan". En resumen, esto es realmente una tontería. Es necesario tener en cuenta el lado del cliente. Especialmente, como digo, con sesiones de larga duración como websockets, se puede romper y, sin que el usuario lo note, es necesario poder reinstalar dichas sesiones. Y luego todo es perfecto.

Recursos

En realidad, aquí les contaré una historia clara. De nuevo de la vida real. Lo más enfermizo que he oído jamás sobre los recursos.

Recursos en este caso, quiero decir, algún tipo de solicitudes, límites que puede poner en pods en sus clústeres de Kubernetes. Lo más divertido que escuché de un desarrollador... Uno de mis compañeros desarrolladores en un lugar de trabajo anterior dijo una vez: "Mi aplicación no se inicia en el clúster". Miré y vi que no arrancaba, pero o no entraba en los recursos o habían puesto unos límites muy pequeños. En resumen, la aplicación no puede iniciarse debido a recursos. Yo digo: “No arranca por recursos, tú decides cuánto necesitas y estableces un valor adecuado”. Él dice: "¿Qué tipo de recursos?" Comencé a explicarle que es necesario establecer Kubernetes, límites a las solicitudes y bla, bla, bla. El hombre escuchó durante cinco minutos, asintió y dijo: “Vine aquí para trabajar como desarrollador, no quiero saber nada sobre ningún recurso. Vine aquí para escribir código y eso es todo”. Es triste. Este es un concepto muy triste desde el punto de vista de un desarrollador. Especialmente en el mundo moderno, por así decirlo, de devops progresistas.

¿Por qué se necesitan recursos? Hay 2 tipos de recursos en Kubernetes. Algunas se llaman solicitudes, otras se llaman límites. Por recursos entenderemos que básicamente siempre existen sólo dos restricciones básicas. Es decir, límites de tiempo de CPU y límites de RAM para un contenedor que se ejecuta en Kubernetes.

Un límite establece un límite superior sobre cómo se puede utilizar un recurso en su aplicación. Es decir, en consecuencia, si dice 1 GB de RAM entre los límites, entonces su aplicación no podrá usar más de 1 GB de RAM. Y si de repente quiere e intenta hacer esto, entonces un proceso llamado oom killer, es decir, sin memoria, vendrá y eliminará su aplicación, es decir, simplemente se reiniciará. Las aplicaciones no se reiniciarán según la CPU. En términos de CPU, si una aplicación intenta utilizar mucho más de lo especificado en los límites, la CPU simplemente será seleccionada estrictamente. Esto no da lugar a reinicios. Este es el límite, este es el límite superior.

Y hay una petición. Una solicitud es la forma en que Kubernetes entiende cómo los nodos de su clúster de Kubernetes se llenan de aplicaciones. Es decir, una solicitud es una especie de confirmación de su aplicación. Dice lo que quiero usar: "Me gustaría que me reservaras tanta CPU y tanta memoria". Una analogía tan simple. ¿Qué pasa si tenemos un nodo que tiene, no sé, 8 CPU en total? Y allí llega un pod, cuyas solicitudes dicen 1 CPU, lo que significa que al nodo le quedan 7 CPU. Es decir, en consecuencia, tan pronto como lleguen 8 pods a este nodo, cada uno de los cuales tiene 1 CPU en sus solicitudes, el nodo, desde el punto de vista de Kubernetes, se ha quedado sin CPU y no se pueden enviar más pods con solicitudes. lanzado en este nodo. Si todos los nodos se quedan sin CPU, Kubernetes comenzará a decir que no hay nodos adecuados en el clúster para ejecutar sus pods porque la CPU se ha agotado.

¿Por qué se necesitan solicitudes y por qué sin solicitudes, creo que no es necesario iniciar nada en Kubernetes? Imaginemos una situación hipotética. Inicia su aplicación sin solicitudes, Kubernetes no sabe cuánto tiene, ni a qué nodos puede enviarla. Bueno, empuja, empuja, empuja sobre los nodos. En algún momento, comenzará a recibir tráfico hacia su aplicación. Y una de las aplicaciones de repente empieza a utilizar recursos hasta los límites que tiene según los límites. Resulta que hay otra aplicación cerca y también necesita recursos. De hecho, el nodo comienza a quedarse físicamente sin recursos, por ejemplo, OP. De hecho, el nodo comienza a quedarse físicamente sin recursos, por ejemplo, memoria de acceso aleatorio (RAM). Cuando un nodo se queda sin energía, primero la ventana acoplable dejará de responder, luego el cubelet y luego el sistema operativo. Simplemente quedarán inconscientes y TODO definitivamente dejará de funcionar para ti. Es decir, esto hará que tu nodo se atasque y tendrás que reiniciarlo. En definitiva, la situación no es muy buena.

Y cuando tiene solicitudes, los límites no son muy diferentes, al menos no muchas veces más que los límites o las solicitudes, entonces puede tener un llenado de aplicaciones tan normal y racional en los nodos de los clústeres de Kubernetes. Al mismo tiempo, Kubernetes es aproximadamente consciente de cuánto de lo que pone, dónde y cuánto de lo que se usa y dónde. Es decir, es uno de esos momentos. Es importante entenderlo. Y es importante controlar que así esté indicado.

Almacenamiento de datos

Nuestro siguiente punto es sobre el almacenamiento de datos. ¿Qué hacer con ellos y en general qué hacer con la persistencia en Kubernetes?

Pienso, nuevamente, dentro de nuestro escuela nocturna, hubo un tema sobre la base de datos en Kubernetes. Y me parece que sé incluso a grandes rasgos lo que le dijeron sus colegas cuando les preguntaron: "¿Es posible ejecutar una base de datos en Kubernetes?" Por alguna razón, me parece que sus colegas deberían haberle dicho que si se pregunta si es posible ejecutar una base de datos en Kubernetes, entonces es imposible.

La lógica aquí es simple. Por si acaso, lo explicaré una vez más, si eres un tipo realmente genial que puede construir un sistema de almacenamiento en red distribuido bastante tolerante a fallas, comprende cómo encajar una base de datos en este caso, cómo debería funcionar la nube nativa en contenedores. en una base de datos en general. Lo más probable es que no tengas dudas sobre cómo ejecutarlo. Si tiene esa pregunta y quiere asegurarse de que todo se desarrolle y se mantenga en producción y nunca caiga, entonces esto no sucede. Tiene la garantía de dispararse en el pie con este enfoque. Por tanto, es mejor no hacerlo.

¿Qué debemos hacer con los datos que nuestra aplicación quiere almacenar, algunas imágenes que suben los usuarios, algunas cosas que nuestra aplicación genera durante su funcionamiento, al inicio, por ejemplo? ¿Qué hacer con ellos en Kubernetes?

En general, idealmente, sí, por supuesto, Kubernetes está muy bien diseñado y, en general, fue concebido inicialmente para aplicaciones sin estado. Es decir, para aquellas aplicaciones que no almacenan información alguna. Esto es ideal.

Pero, por supuesto, no siempre existe la opción ideal. ¿Así que lo que? El primer punto y el más sencillo es llevar algún tipo de S3, pero no uno hecho en casa, cuyo funcionamiento tampoco está claro, sino de algún proveedor. Un proveedor bueno y normal, y enséñele a su aplicación a usar S3. Es decir, cuando su usuario quiera cargar un archivo, diga "aquí, por favor, cárguelo en S3". Cuando quiera recibirlo, diga: "Aquí hay un enlace al S3 y tómalo desde aquí". Esto es ideal.

Si de repente, por alguna razón, esta opción ideal no le conviene, tiene una aplicación que usted no escribió, no desarrolla, o es algún tipo de legado terrible, no puede usar el protocolo S3, pero debe trabajar con directorios locales en carpetas locales. Tomemos algo más o menos simple: implemente Kubernetes. Es decir, me parece que proteger inmediatamente a Ceph para algunas tareas mínimas es una mala idea. Porque Ceph, por supuesto, es bueno y está a la moda. Pero si realmente no comprende lo que está haciendo, una vez que coloque algo en Ceph, podrá fácil y simplemente no volver a sacarlo de allí nunca más. Porque, como sabes, Ceph almacena datos en su clúster en formato binario y no en forma de archivos simples. Por lo tanto, si de repente el clúster Ceph falla, existe una alta y completa probabilidad de que nunca más vuelva a obtener sus datos de allí.

Tendremos un curso sobre Ceph, puedes familiarícese con el programa y envíe una solicitud.

Por tanto, es mejor hacer algo sencillo como un servidor NFS. Kubernetes puede trabajar con ellos, puede montar un directorio en un servidor NFS; su aplicación es como un directorio local. Al mismo tiempo, naturalmente, debe comprender que, nuevamente, necesita hacer algo con su NFS, debe comprender que a veces puede volverse inaccesible y considerar la cuestión de qué hará en este caso. Quizás debería hacerse una copia de seguridad en algún lugar de una máquina separada.

El siguiente punto del que hablé es qué hacer si su aplicación genera algunos archivos durante la operación. Por ejemplo, cuando se inicia, genera algún archivo estático, que se basa en cierta información que la aplicación recibe solo en el momento del inicio. ¡Qué momento! Si no hay muchos datos de este tipo, entonces no tiene que preocuparse en absoluto, simplemente instale esta aplicación usted mismo y trabaje. La única pregunta aquí es qué, mira. Muy a menudo, todo tipo de sistemas heredados, como WordPress, etc., especialmente con algún tipo de complementos inteligentes modificados, los desarrolladores PHP inteligentes, a menudo saben cómo hacerlo para que generen algún tipo de archivo por sí mismos. En consecuencia, uno genera un archivo y el segundo genera un segundo archivo. Ellos son diferentes. El equilibrio ocurre en el clúster de Kubernetes de los clientes simplemente por casualidad. En consecuencia, resulta que, por ejemplo, no saben cómo trabajar juntos. Uno da una información, el otro le da al usuario otra información. Esto es algo que debes evitar. Es decir, en Kubernetes, se garantiza que todo lo que inicie podrá funcionar en múltiples instancias. Porque Kubernetes es algo en movimiento. En consecuencia, puede mover cualquier cosa, cuando quiera, sin preguntarle a nadie. Por lo tanto, debes contar con esto. Todo lo que se inicie en una instancia, tarde o temprano fallará. Cuantas más reservas tengas, mejor. Pero repito, repito, si tienes varios archivos de este tipo, puedes ponerlos justo debajo, pesan un poco. Si hay un poco más, probablemente no deberías empujarlos dentro del recipiente.

Te aconsejo que hay algo tan maravilloso en Kubernetes que puedes usar el volumen. En particular, hay un volumen de tipo directorio vacío. Es decir, es solo que Kubernetes creará automáticamente un directorio en sus directorios de servicios en el servidor donde comenzó. Y él te lo dará para que puedas usarlo. Sólo hay un punto importante. Es decir, sus datos no se almacenarán dentro del contenedor, sino en el host en el que se está ejecutando. Además, Kubernetes puede controlar dichos directorios vacíos en la configuración normal y puede controlar su tamaño máximo y no permitir que se exceda. El único punto es que lo que ha escrito en un directorio vacío no se pierde durante los reinicios del pod. Es decir, si su módulo cae por error y vuelve a subir, la información del directorio vacío no irá a ninguna parte. Puede volver a utilizarlo cuando empiece de nuevo, y eso es bueno. Si su grupo se va a algún lugar, entonces, naturalmente, se irá sin datos. Es decir, tan pronto como desaparece el pod del nodo donde se lanzó con el directorio vacío, se elimina el directorio vacío.

¿Qué más tiene de bueno el directorio vacío? Por ejemplo, se puede utilizar como caché. Imaginemos que nuestra aplicación genera algo sobre la marcha, se lo entrega a los usuarios y lo hace durante mucho tiempo. Por lo tanto, la aplicación, por ejemplo, lo genera y lo entrega a los usuarios, y al mismo tiempo lo almacena en algún lugar, de modo que la próxima vez que el usuario venga por lo mismo, será más rápido entregárselo inmediatamente generado. Se puede pedir a Kubernetes que cree un directorio vacío en la memoria. Y por lo tanto, sus cachés generalmente pueden funcionar a la velocidad del rayo, en términos de velocidad de acceso al disco. Es decir, tiene un directorio vacío en la memoria, en el sistema operativo está almacenado en la memoria, pero para usted, para el usuario dentro del pod, parece solo un directorio local. No necesitas la aplicación para enseñar magia específicamente. Simplemente toma y coloca su archivo directamente en un directorio, pero, de hecho, en la memoria del sistema operativo. Esta también es una característica muy conveniente en términos de Kubernetes.

¿Qué problemas tiene Minio? El principal problema con Minio es que para que funcione, debe estar ejecutándose en algún lugar y debe haber algún tipo de sistema de archivos, es decir, almacenamiento. Y aquí nos encontramos con los mismos problemas que tiene Ceph. Es decir, Minio debe almacenar sus archivos en algún lugar. Es simplemente una interfaz HTTP para sus archivos. Además, la funcionalidad es claramente peor que la del S3 de Amazon. Anteriormente, no podía autorizar adecuadamente al usuario. Ahora, hasta donde yo sé, ya puede crear depósitos con diferentes autorizaciones, pero nuevamente, me parece que el problema principal es, por así decirlo, el sistema de almacenamiento subyacente como mínimo.

¿Cómo afecta el directorio vacío en la memoria a los límites? No afecta los límites de ninguna manera. Se encuentra en la memoria del anfitrión y no en la memoria de su contenedor. Es decir, su contenedor no ve el directorio vacío en la memoria como parte de su memoria ocupada. El anfitrión ve esto. En consecuencia, sí, desde el punto de vista de Kubernetes, cuando empieces a usar esto, sería bueno entender que estás dedicando parte de tu memoria a vaciar el directorio. Y, en consecuencia, comprenda que la memoria puede agotarse no solo debido a las aplicaciones, sino también porque alguien escribe en estos directorios vacíos.

Natividad de la nube

Y el subtema final es qué es Cloudnative. ¿Por qué es necesario? Natividad de la nube, etc.

Es decir, aquellas aplicaciones que son capaces y están escritas para funcionar en una infraestructura de nube moderna. Pero, de hecho, Cloudnative tiene otro aspecto similar. Que esta no solo sea una aplicación que tenga en cuenta todos los requisitos de una infraestructura de nube moderna, sino que también sepa trabajar con esta infraestructura de nube moderna, aproveche las ventajas y desventajas de que funcione en estas nubes. No se exceda y trabaje en la nube, aproveche los beneficios de trabajar en la nube.

Requisitos para desarrollar una aplicación en Kubernetes

Tomemos a Kubernetes como ejemplo. Su aplicación se está ejecutando en Kubernetes. Su aplicación siempre puede, o más bien los administradores de su aplicación, siempre pueden crear una cuenta de servicio. Es decir, una cuenta para autorización en el propio Kubernetes en su servidor. Agregue algunos derechos que necesitamos allí. Y puede acceder a Kubernetes desde su aplicación. ¿Qué puedes hacer de esta manera? Por ejemplo, desde la aplicación, reciba datos sobre dónde se encuentran sus otras aplicaciones y otras instancias similares y, de alguna manera, se agruparán sobre Kubernetes, si es necesario.

Una vez más, literalmente tuvimos un caso recientemente. Tenemos un controlador que monitorea la cola. Y cuando aparecen algunas tareas nuevas en esta cola, van a Kubernetes y, dentro de Kubernetes, crean un nuevo pod. Le da a este pod alguna tarea nueva y, dentro del marco de este pod, el pod realiza la tarea, envía una respuesta al propio controlador y el controlador luego hace algo con esta información. Por ejemplo, suma una base de datos. Es decir, nuevamente, esta es una ventaja del hecho de que nuestra aplicación se ejecuta en Kubernetes. Podemos utilizar la funcionalidad incorporada de Kubernetes para expandir de alguna manera y hacer que la funcionalidad de nuestra aplicación sea más conveniente. Es decir, no ocultes algún tipo de magia sobre cómo iniciar una aplicación, cómo iniciar un trabajador. En Kubernetes, simplemente envía una solicitud en la aplicación si la aplicación está escrita en Python.

Lo mismo se aplica si vamos más allá de Kubernetes. Tenemos nuestro Kubernetes ejecutándose en algún lugar; es bueno si está en algún tipo de nube. Nuevamente, podemos usar, e incluso deberíamos, creo, usar las capacidades de la propia nube donde estamos ejecutando. De las cosas elementales que nos proporciona la nube. Equilibrio, es decir, podemos crear equilibradores en la nube y utilizarlos. Esta es una ventaja directa de lo que podemos usar. Porque el equilibrio de la nube, en primer lugar, simplemente nos elimina estúpidamente la responsabilidad de cómo funciona y cómo está configurado. Además, es muy conveniente porque Kubernetes normal puede integrarse con las nubes.

Lo mismo ocurre con la escala. Kubernetes normal puede integrarse con proveedores de nube. Sabe cómo entender que si el clúster se queda sin nodos, es decir, el espacio para los nodos se ha agotado, entonces debe agregar: el propio Kubernetes agregará nuevos nodos a su clúster y comenzará a lanzar pods en ellos. Es decir, cuando llega tu carga, el número de focos comienza a aumentar. Cuando los nodos del clúster se agotan para estos pods, Kubernetes lanza nuevos nodos y, en consecuencia, la cantidad de pods aún puede aumentar. Y es muy conveniente. Esta es una oportunidad directa para escalar el clúster sobre la marcha. No muy rápido, en el sentido de que no es un segundo, es más bien un minuto para agregar nuevos nodos.

Pero según mi experiencia, nuevamente, es lo más genial que he visto en mi vida. Cuando el clúster de Cloudnative escaló según la hora del día. Era un servicio backend que utilizaban las personas del back office. Es decir, llegan a trabajar a las 9 am, comienzan a iniciar sesión en el sistema y, en consecuencia, el clúster Cloudnative, donde todo está funcionando, comienza a crecer, lanzando nuevos pods para que todos los que vienen a trabajar puedan trabajar con la aplicación. Cuando salen del trabajo a las 8 o 6 de la tarde, los clústeres de Kubernetes notan que ya nadie usa la aplicación y comienzan a reducirse. Se garantizan ahorros de hasta el 30 por ciento. Funcionó en Amazon en ese momento; en ese momento no había nadie en Rusia que pudiera hacerlo tan bien.

Se lo diré claramente: el ahorro es del 30 por ciento simplemente porque usamos Kubernetes y aprovechamos las capacidades de la nube. Ahora esto se puede hacer en Rusia. Por supuesto, no le haré publicidad a nadie, pero digamos que hay proveedores que pueden hacer esto, proporcionándolo de inmediato con un botón.

Hay un último punto sobre el que también me gustaría llamar su atención. Para que su aplicación, su infraestructura sea Cloudnative, tiene sentido finalmente comenzar a adaptar el enfoque llamado Infraestructura como código, es decir, esto significa que su aplicación, o más bien su infraestructura, se necesita exactamente de la misma manera que la código Describe tu aplicación, tu lógica de negocio en forma de código. Y trabajar con él como código, es decir, probarlo, implementarlo, almacenarlo en git y aplicarle CICD.

Y esto es exactamente lo que le permite, en primer lugar, tener siempre control sobre su infraestructura, entender siempre en qué estado se encuentra. En segundo lugar, evite operaciones manuales que provoquen errores. En tercer lugar, evite simplemente lo que se llama rotación, cuando necesita realizar constantemente las mismas tareas manuales. En cuarto lugar, le permite recuperarse mucho más rápido en caso de fallo. En Rusia, cada vez que hablo de esto, siempre hay una gran cantidad de personas que dicen: "Sí, está claro, pero hay enfoques, en resumen, no hay necesidad de arreglar nada". Pero es verdad. Si algo está roto en su infraestructura, entonces desde el punto de vista del enfoque Cloudnative y desde el punto de vista de la Infraestructura como Código, en lugar de arreglarlo, ir al servidor, descubrir qué está roto y arreglarlo, es más fácil. para eliminar el servidor y crearlo nuevamente. Y haré restaurar todo esto.

Todas estas cuestiones se analizan con más detalle en Cursos en vídeo de Kubernetes: Junior, Básico, Mega. Siguiendo el enlace podrás familiarizarte con el programa y las condiciones. Lo conveniente es que puedes dominar Kubernetes estudiando desde casa o trabajando 1-2 horas al día.

Fuente: habr.com

Añadir un comentario