Guía de Kubernetes, Parte 1: Aplicaciones, microservicios y contenedores

A petición nuestra, Habr creó el centro Kubernetes y nos complace publicar la primera publicación en él. Suscribete!

Kubernetes es fácil. ¿Por qué los bancos me pagan mucho dinero por trabajar en esta área, mientras que cualquiera puede dominar esta tecnología en solo unas pocas horas?



Si duda de que se pueda aprender Kubernetes tan rápido, le sugiero que intente hacerlo usted mismo. Es decir, habiendo dominado este material, podrá ejecutar la aplicación basada en microservicios en el clúster de Kubernetes. Puedo garantizar esto, porque es precisamente por la metodología utilizada aquí que entreno a Kubernetes para trabajar con nuestros clientes. ¿Qué distingue este manual de otros? De hecho, muchas cosas. Por lo tanto, la mayoría de estos materiales comienzan con una explicación de cosas simples: conceptos de Kubernetes y características del equipo de kubectl. Los autores de estos materiales creen que su lector está familiarizado con el desarrollo de aplicaciones, microservicios y contenedores Docker. Nosotros iremos por el otro lado. Primero, hablemos sobre cómo ejecutar una aplicación basada en microservicios en una computadora. Luego considere el ensamblaje de las imágenes del contenedor para cada microservicio. Después de eso, conoceremos a Kubernetes y analizaremos la implementación de una aplicación basada en microservicios en un clúster administrado por Kubernetes.

Tal enfoque, con un enfoque gradual a Kubernetes, le dará la profundidad de comprensión que le está sucediendo a una persona común para comprender cuán simple se arregla todo en Kubernetes. Kubernetes es, por supuesto, una tecnología simple, siempre que cualquiera que quiera aprenderlo sepa dónde y cómo se usa.

Ahora, sin más preámbulos, pongámonos a trabajar y hablemos sobre la aplicación con la que trabajaremos.

Aplicación experimental


Nuestra aplicación realizará solo una función. Acepta, como entrada, una oración, y luego, utilizando los medios de análisis de texto, realiza un análisis de sentimientos de esta oración, recibiendo una estimación de la actitud emocional del autor de la oración hacia un determinado objeto.

Así es como se ve la ventana principal de esta aplicación.


Aplicación web para análisis de sentimiento de texto

Desde un punto de vista técnico, la aplicación consta de tres microservicios, cada uno de los cuales resuelve un cierto conjunto de tareas:

  • SA-Frontend es un servidor web Nginx que sirve React archivos estáticos.
  • SA-WebApp es una aplicación web basada en Java que procesa solicitudes desde el front-end.
  • SA-Logic es una aplicación de Python que realiza análisis de sentimientos de texto.

Es importante tener en cuenta que los microservicios no existen de forma aislada. Implementan la idea de "separación de deberes", pero, sin embargo, necesitan interactuar entre sí.


Flujos de datos de aplicaciones

En el diagrama anterior, puede ver las etapas numeradas del sistema, que ilustran los flujos de datos en la aplicación. Analicémoslos:

  1. El navegador solicita el archivo index.html del servidor (que, a su vez, descarga el paquete de la aplicación React).
  2. El usuario interactúa con la aplicación, esto provoca una llamada a una aplicación web basada en Spring.
  3. La aplicación web redirige la solicitud de análisis de texto a la aplicación Python.
  4. La aplicación Python analiza la tonalidad del texto y devuelve el resultado como respuesta a la solicitud.
  5. La aplicación Spring envía una respuesta a la aplicación React (y, a su vez, muestra el resultado del análisis de texto al usuario).

El código para todas estas aplicaciones se puede encontrar aquí . Le recomiendo que ahora copie este repositorio para usted, ya que hay muchos experimentos interesantes por delante.

Inicio de una aplicación basada en microservicios en una computadora local


Para que la aplicación funcione, necesitamos ejecutar los tres microservicios. Comencemos con el más lindo de ellos, con la aplicación front-end.

▍Configuración Reaccionar para el desarrollo local


Para ejecutar la aplicación React, debe instalar las plataformas Node.js y NPM en su computadora. Después de instalar todo esto, vaya a través de la terminal a la carpeta del proyecto sa-frontend y ejecute el siguiente comando:

 npm install 

Gracias a la ejecución de este comando, las dependencias de la aplicación React, cuyas entradas se encuentran en el archivo package.json , se cargarán en la carpeta node_modules . Después de descargar las dependencias en la misma carpeta, ejecute el siguiente comando:

 npm start 

Eso es todo Ahora que la aplicación React se está ejecutando, puede acceder a ella yendo a la dirección localhost:3000 en el navegador. Puedes cambiar algo en su código. Inmediatamente verá el efecto de estos cambios en el navegador. Esto es posible gracias al llamado reemplazo "en caliente" de los módulos. Gracias a esto, el desarrollo front-end se convierte en una tarea simple y agradable.

▍Preparación de una aplicación React para salida a producción


Para el uso real de la aplicación React, necesitamos convertirla en un conjunto de archivos estáticos y entregarlos a los clientes que usan un servidor web.

Para compilar la aplicación React, nuevamente, usando el terminal, vaya a la carpeta sa-frontend y ejecute el siguiente comando:

 npm run build 

Esto creará un directorio de build en la carpeta del proyecto. Contendrá todos los archivos estáticos necesarios para que la aplicación React funcione.

▍Servicio de archivos estáticos con herramientas Nginx


Primero debe instalar y ejecutar el servidor web Nginx. Aquí puede descargarlo y encontrar las instrucciones de instalación y arranque. Luego, debe copiar el contenido de la carpeta sa-frontend/build carpeta [your_nginx_installation_dir]/html .

Con este enfoque, el archivo index.html generado durante la compilación de la aplicación React estará disponible en [your_nginx_installation_dir]/html/index.html . Este es el archivo que, por defecto, el servidor Nginx emite al acceder. El servidor está configurado para escuchar en el puerto 80 , pero puede configurarlo según lo necesite editando el archivo [your_nginx_installation_dir]/conf/nginx.conf .

Ahora abra su navegador y vaya a localhost:80 . Verá la página de la aplicación React.


Reaccionar aplicación servida por el servidor Nginx

Si escribe algo en el campo Type your sentence ahora y hace clic en el botón Send , no pasará nada. Pero, si mira la consola, puede ver mensajes de error allí. Para entender exactamente dónde ocurren estos errores, analicemos el código de la aplicación.

▍Análisis del código de aplicación front-end


App.js mirar el código del archivo App.js , podemos ver que al hacer clic en el botón Send se llama al método analyzeSentence() . El código para este método se proporciona a continuación. Al mismo tiempo, preste atención al hecho de que para cada línea para la cual hay un comentario del # formulario, hay una explicación debajo del código. Del mismo modo, analizaremos otras piezas de código.

 analyzeSentence() {   fetch('http://localhost:8080/sentiment', {  // #1       method: 'POST',       headers: {           'Content-Type': 'application/json'       },       body: JSON.stringify({                      sentence: this.textField.getValue()})// #2   })       .then(response => response.json())       .then(data => this.setState(data));  // #3 } 

1. URL en la que se ejecuta la solicitud POST. Se entiende que esta dirección contiene una aplicación que está esperando tales solicitudes.

2. El cuerpo de la solicitud enviado a la aplicación. Aquí hay un ejemplo de cuerpo de solicitud:

 {   sentence: "I like yogobella!" } 

3. Al recibir una respuesta a la solicitud, se actualiza el estado del componente. Esto hace que el componente se vuelva a representar. Si recibimos datos (es decir, un objeto JSON que contiene los datos ingresados ​​y la puntuación de texto calculada), Polarity componente Polarity , ya que se cumplirán las condiciones correspondientes. Así es como describimos el componente:

 const polarityComponent = this.state.polarity !== undefined ?   <Polarity sentence={this.state.sentence}             polarity={this.state.polarity}/> :   null; 

El código parece estar funcionando bastante bien. ¿Qué está mal aquí, después de todo? Si asume que en la dirección donde la aplicación está tratando de enviar una solicitud POST, hasta ahora no hay nada que pueda aceptar y procesar esta solicitud, entonces tendrá toda la razón. Es decir, para procesar las solicitudes que llegan a la dirección http://localhost:8080/sentiment , necesitamos ejecutar una aplicación web basada en Spring.


Necesitamos una aplicación Spring que pueda aceptar una solicitud POST.

▍ Configurar la aplicación web basada en Spring


Para implementar la aplicación Spring, necesitará JDK8 y Maven y las variables de entorno configuradas correctamente. Después de instalar todo esto, puede continuar trabajando en nuestro proyecto.

▍Paquetear la aplicación en un archivo jar


Vaya, usando el terminal, a la carpeta sa-webapp e ingrese el siguiente comando:

 mvn install 

Después de ejecutar este comando, el directorio de target se creará en la carpeta sa-webapp . Habrá una aplicación Java empaquetada en un archivo jar representado por sentiment-analysis-web-0.0.1-SNAPSHOT.jar .

▍Inicie la aplicación Java


Vaya a la carpeta de target e inicie la aplicación con el siguiente comando:

 java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar 

Se producirá un error durante la ejecución de este comando. Para comenzar a solucionarlo, podemos analizar la información de excepción en los datos de seguimiento de la pila:

 Error creating bean with name 'sentimentController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'sa.logic.api.url' in value "${sa.logic.api.url}" 

Lo más importante para nosotros aquí es la mención de la imposibilidad de determinar el significado de sa.logic.api.url . Analicemos el código en el que se produce el error.

▍ Análisis de código de aplicación Java


Aquí está el fragmento de código donde se produce el error.

 @CrossOrigin(origins = "*") @RestController public class SentimentController {   @Value("${sa.logic.api.url}")    // #1   private String saLogicApiUrl;   @PostMapping("/sentiment")   public SentimentDto sentimentAnalysis(       @RequestBody SentenceDto sentenceDto)   {       RestTemplate restTemplate = new RestTemplate();       return restTemplate.postForEntity(               saLogicApiUrl + "/analyse/sentiment",    // #2               sentenceDto, SentimentDto.class)               .getBody();   } } 

  1. S entimentController tiene un campo saLogicApiUrl . Su valor lo establece la propiedad sa.logic.api.url .
  2. La cadena saLogicApiUrl concatena con el valor /analyse/sentiment . Juntos forman una dirección para acceder a un microservicio que realiza análisis de texto.

▍Configurar el valor de la propiedad


En Spring, la fuente estándar de valores de propiedad es el archivo application.properties , que se puede encontrar en sa-webapp/src/main/resources . Pero su uso no es la única forma de establecer valores de propiedad. Puede hacer esto con un comando como el siguiente:

 java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=WHAT.IS.THE.SA.LOGIC.API.URL 

El valor de esta propiedad debe apuntar a la dirección de nuestra aplicación Python.

Al configurarlo, le decimos a la aplicación web Spring dónde debe ir para ejecutar solicitudes de análisis de texto.

Para no complicarnos la vida, decidimos que la aplicación Python estará disponible en localhost:5000 y tratamos de no olvidarnos de ella. Como resultado, el comando para iniciar la aplicación Spring se verá así:

 java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=http://localhost:5000 


Nuestro sistema carece de una aplicación Python

Ahora solo tenemos que iniciar la aplicación Python y el sistema funcionará como se espera.

▍Configurar una aplicación Python


Para ejecutar una aplicación Python, debe tener Python 3 y Pip instalados, y debe configurar correctamente las variables de entorno adecuadas.

▍Instalación de dependencias


Vaya a la carpeta del proyecto sa-logic/sa y ejecute los siguientes comandos:

 python -m pip install -r requirements.txt python -m textblob.download_corpora 

▍ Iniciar aplicación


Después de instalar las dependencias, estamos listos para iniciar la aplicación:

 python sentiment_analysis.py 

Después de ejecutar este comando, se nos informará lo siguiente:

 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 

Esto significa que la aplicación se está ejecutando y está esperando solicitudes en localhost:5000/

▍ Investigación de código


Considere el código de la aplicación Python para comprender cómo responde a las solicitudes:

 from textblob import TextBlob from flask import Flask, request, jsonify app = Flask(__name__)                                   #1 @app.route("/analyse/sentiment", methods=['POST'])      #2 def analyse_sentiment():   sentence = request.get_json()['sentence']           #3   polarity = TextBlob(sentence).sentences[0].polarity #4   return jsonify(                                     #5       sentence=sentence,       polarity=polarity   ) if __name__ == '__main__':   app.run(host='0.0.0.0', port=5000)                #6 

  1. Inicializando un objeto de Flask .
  2. Establecer la dirección para ejecutar solicitudes POST.
  3. Recuperando la propiedad de la sentence del cuerpo de la solicitud.
  4. Inicializando el objeto anónimo TextBlob y obteniendo el valor de polarity para la primera oración en el cuerpo de la solicitud (en nuestro caso, esta es la única oración aprobada para el análisis).
  5. El retorno de la respuesta, en cuyo cuerpo contiene el texto de la propuesta y el índice de polarity calculado para ella.
  6. Iniciando la aplicación Flask, que estará disponible en 0.0.0.0:5000 (también puede acceder a ella usando un localhost:5000 construct).

Ahora se están ejecutando los microservicios que componen la aplicación. Están configurados para interactuar entre sí. Así es como se ve el diagrama de la aplicación en esta etapa del trabajo.


Todos los microservicios que componen la aplicación se llevan a un estado saludable.

Ahora, antes de continuar, abra la aplicación React en un navegador e intente analizar alguna sugerencia al usarla. Si todo se hace correctamente, después de hacer clic en el botón Send , verá los resultados del análisis debajo del cuadro de texto.

En la siguiente sección, hablaremos sobre cómo ejecutar nuestros microservicios en contenedores Docker. Esto es necesario para preparar la aplicación para su lanzamiento en el clúster de Kubernetes.

Contenedores Docker


Kubernetes es un sistema para automatizar la implementación, el escalado y la administración de aplicaciones en contenedores. También se le llama el "orquestador de contenedores". Si Kubernetes trabaja con contenedores, primero debemos adquirir estos contenedores antes de usar este sistema. Pero primero, hablemos sobre qué son los contenedores. Quizás la mejor respuesta a la pregunta de qué se puede encontrar en la documentación de Docker:

Una imagen de contenedor es un paquete liviano, independiente y ejecutable que contiene algún tipo de aplicación que incluye todo lo que necesita para ejecutarlo: código de aplicación, tiempo de ejecución, herramientas del sistema y bibliotecas, configuraciones. Los programas en contenedores se pueden usar en entornos Linux y Windows, y siempre funcionarán igual independientemente de la infraestructura.

Esto significa que los contenedores se pueden ejecutar en cualquier computadora, incluidos los servidores de producción, y en cualquier entorno las aplicaciones incluidas funcionarán de la misma manera.

Para explorar las características de los contenedores y compararlos con otras formas de iniciar aplicaciones, considere un ejemplo de servir una aplicación React utilizando una máquina virtual y un contenedor.

▍Servir archivos estáticos de aplicaciones React usando una máquina virtual


Al tratar de organizar el mantenimiento de archivos estáticos por medio de máquinas virtuales, encontraremos las siguientes desventajas:

  1. Uso ineficiente de los recursos, ya que cada máquina virtual es un sistema operativo completo.
  2. Depende de la plataforma. Lo que funciona en una determinada computadora local puede no funcionar en un servidor de producción.
  3. Escalado lento e intensivo en recursos de una solución basada en máquina virtual.


Servidor web de servidor estático Nginx que se ejecuta en una máquina virtual

Si se usan contenedores para resolver un problema similar, entonces, en comparación con las máquinas virtuales, se pueden observar sus siguientes puntos fuertes:

  1. Uso eficiente de los recursos: trabajando con el sistema operativo usando Docker.
  2. Independencia de la plataforma. Un contenedor que un desarrollador pueda ejecutar en su computadora funcionará en cualquier lugar.
  3. Despliegue ligero a través del uso de capas de imagen.


Servidor web del servidor estático Nginx que se ejecuta en un contenedor

Comparamos máquinas virtuales y contenedores en solo unos pocos puntos, pero incluso esto es suficiente para sentir las fortalezas de los contenedores. Obtenga más información sobre los contenedores Docker aquí.

▍ Ensamblar una imagen de contenedor para una aplicación React


El bloque de construcción principal del contenedor Docker es el Dockerfile . Al comienzo de este archivo, haga un registro de la imagen básica del contenedor, luego incluya una secuencia de instrucciones que indique el orden en que se creará el contenedor que satisfaga las necesidades de una determinada aplicación.

Antes de comenzar a trabajar con el archivo Dockerfile , recordemos lo que hicimos para preparar los archivos de la aplicación React para cargarlos en el servidor Nginx:

  1. Cree un paquete de aplicación React ( npm run build ).
  2. Iniciando el servidor Nginx.
  3. Copie el contenido del directorio de build de la carpeta del proyecto sa-frontend a la carpeta del servidor nginx/html .

A continuación puede ver los paralelos entre la creación del contenedor y las acciones anteriores realizadas en la computadora local.

▍Preparación de un Dockerfile para SA-Frontend


Las instrucciones que se incluirán en el Dockerfile para la aplicación SA-Frontend consisten en solo dos comandos. El hecho es que el equipo de desarrollo de Nginx preparó una imagen básica para Nginx, que usaremos para crear nuestra imagen. Estos son los dos pasos que debemos describir:

  1. La base de la imagen que necesita para hacer la imagen de Nginx.
  2. El contenido de la carpeta sa-frontend/build debe copiarse en la carpeta de imágenes nginx/html .

Si pasamos de esta descripción al Dockerfile , se verá así:

 FROM nginx COPY build /usr/share/nginx/html 

Como puede ver, aquí todo es muy simple, mientras que el contenido del archivo es incluso bastante legible y comprensible. Este archivo le dice al sistema que tome la imagen nginx con todo lo que ya tiene y que copie el contenido del directorio de build directorio nginx/html .

Aquí puede tener una pregunta sobre dónde sé exactamente dónde necesito copiar los archivos de la carpeta de build , es decir, de dónde vino la ruta /usr/share/nginx/html . De hecho, y no hay nada complicado. El hecho es que la información relevante se puede encontrar en la descripción de la imagen.

▍Crear una imagen y subirla al repositorio


Antes de que podamos trabajar con la imagen terminada, debemos enviarla al repositorio de imágenes. Para hacer esto, utilizaremos la plataforma en la nube gratuita para alojar imágenes de Docker Hub. En esta etapa del trabajo, debe hacer lo siguiente:

  1. Instalar Docker .
  2. Regístrese en el sitio web de Docker Hub.
  3. Inicie sesión en la cuenta ejecutando el siguiente comando en la terminal:

     docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" 

Ahora necesita usar el terminal para ir al directorio sa-frontend y ejecutar el siguiente comando allí:

 docker build -f Dockerfile -t $DOCKER_USER_ID/sentiment-analysis-frontend . 

En lo sucesivo, en comandos similares, $DOCKER_USER_ID debe reemplazarse con su nombre de usuario en Docker Hub. Por ejemplo, esta parte del comando podría verse así: rinormaloku/sentiment-analysis-frontend .

Al mismo tiempo, este comando puede acortarse eliminando -f Dockerfile , ya que este archivo ya existe en la carpeta en la que ejecutamos este comando.

Para enviar la imagen terminada al repositorio, necesitamos el siguiente comando:

 docker push $DOCKER_USER_ID/sentiment-analysis-frontend 

Después de su ejecución, verifique la lista de sus repositorios en Docker Hub para comprender si la imagen se envió a la nube con éxito.

▍Iniciar contenedor


Ahora cualquiera puede descargar y ejecutar una imagen conocida como $DOCKER_USER_ID/sentiment-analysis-frontend . Para hacer esto, debe ejecutar la siguiente secuencia de comandos:

 docker pull $DOCKER_USER_ID/sentiment-analysis-frontend docker run -d -p 80:80 $DOCKER_USER_ID/sentiment-analysis-frontend 

Ahora se inicia el contenedor y podemos seguir trabajando, creando las otras imágenes que necesitamos. Pero, antes de continuar, echemos un 80:80 construcción 80:80 , que se encuentra en el comando de inicio de imagen y puede parecer incomprensible.

  • El primer número 80 es el número de puerto del host (es decir, la computadora local).
  • El segundo número 80 es el puerto del contenedor al que se debe redirigir la solicitud.

Considere la siguiente ilustración.


Reenvío de puertos

El sistema redirige las solicitudes desde el puerto <hostPort> puerto <containerPort> . Es decir, el acceso al puerto 80 computadora se redirige al puerto 80 contenedor.

Como el puerto 80 abierto en la computadora local, puede acceder a la aplicación desde esta computadora en localhost:80 . Si su sistema no es compatible con Docker, puede ejecutar la aplicación en la máquina virtual Docker, cuya dirección se verá como <docker-machine ip>:80 . Para averiguar la dirección IP de la máquina virtual Docker, puede usar el docker-machine ip .

En esta etapa, después de iniciar con éxito el contenedor de la aplicación frontend, debería poder abrir su página en un navegador.

▍ archivo .dockerignore


Al recopilar la imagen de la aplicación SA-Frontend , podríamos notar que este proceso es extremadamente lento. Esto sucede debido al hecho de que el contexto de compilación de la imagen debe enviarse al demonio Docker. El directorio que representa el contexto de compilación se especifica mediante el último argumento del docker build . En nuestro caso, al final de este comando es un punto. Esto da como resultado que la siguiente estructura se incluya en el contexto del ensamblaje:

 sa-frontend: |   .dockerignore |   Dockerfile |   package.json |   README.md +---build +---node_modules +---public \---src 

Pero de todas las carpetas presentes aquí, solo necesitamos la carpeta de build . Descargar cualquier otra cosa es una pérdida de tiempo. Las compilaciones pueden acelerarse diciéndole a Docker qué directorios ignorar. Es para hacer esto que necesitamos un archivo .dockerignore . Si está familiarizado con el archivo .gitignore , la estructura de este archivo seguramente le resultará familiar. Enumera los directorios que el sistema de ensamblaje de imágenes puede ignorar. En nuestro caso, el contenido de este archivo se ve así:

 node_modules src public 

El archivo .dockerignore debe estar en la misma carpeta que el Dockerfile . Ahora ensamblar la imagen tomará unos segundos.

Ahora echemos un vistazo a la aplicación Java.

▍ Java-


, . .

Dockerfile , sa-webapp . , , ENV EXPOSE :

 ENV SA_LOGIC_API_URL http://localhost:5000 … EXPOSE 8080 

ENV Docker. , URL API , .

EXPOSE Docker , . . , Dockerfile SA-Frontend . , , , Dockerfile .

, . — README.md sa-webapp .

▍ Python-


Dockerfile sa-logic , . , , , README.md sa-logic .

▍


- , ? . .

  1. sa-logic 5050 :

     docker run -d -p 5050:5000 $DOCKER_USER_ID/sentiment-analysis-logic 
  2. sa-webapp 8080 . , , Python- Java-, SA_LOGIC_API_URL :

     $ docker run -d -p 8080:8080 -e SA_LOGIC_API_URL='http://<container_ip or docker machine ip>:5000' $DOCKER_USER_ID/sentiment-analysis-web-app 

, IP- Docker — README .

sa-frontend :

 docker run -d -p 80:80 $DOCKER_USER_ID/sentiment-analysis-frontend 

, localhost:80 .

, sa-webapp , Docker, App.js sa-frontend , IP- analyzeSentence() , . .

.




: Kubernetes?


Dockerfile , , Docker. , , .dockerignore . Docker. , Kubernetes. . :
, - . . , sa-webapp sa-logic . , ?

Source: https://habr.com/ru/post/438982/


All Articles