Servicios en Kubernetes.

Los servicios en Kubernetes permiten la comunicación entre varios componentes dentro y fuera de la aplicación. Los servicios de Kubernetes ayudan a conectar aplicaciones con otras aplicaciones o usuarios. Supongamos que una aplicación tiene grupos de PODs que ejecutan varias secciones. Un grupo puede servir a nuestra interfaz. Otro grupo ejecuta procesos de back-end. Y un tercer grupo se conecta a una fuente de datos externa. Los servicios permiten la conectividad entre estos grupos  y hacen que los módulos de back end y front end se comuniquen a una fuente de datos externa. Por lo tanto, los servicios permiten un acoplamiento flexible entre los micro servicios en las aplicaciones.

Hasta ahora hablamos sobre cómo las cápsulas se comunican entre sí a través de redes internas. Pero hay otros aspectos de las redes como la comunicación externa. Si tenemos un POD con una aplicación web ejecutándose en él, no podemos acceder a la página directamente como un usuario externo. Cómo el nodo Kubernetes está en la misma red que el ordenador donde se ejecuta (por ejemplo 192.168.1.2 y 192.168.1.10) y la red de POD interna está en otra (por ejemplo 10.244.0.2), no se puede acceder directamente.

Desde el nodo Kubernetes (192.168.1.2) sí se puede acceder a la página web de los PODs haciendo un curl o, si el nodo tiene una GUI, abriríamos una página web en el navegador y veríamos la página web en un navegador siguiendo la dirección http://10.244.0.2. Pero esto es desde el interior del nodo Kubernetes. Si se quiere acceder desde el ordenador sin tener que ingresar en el nodo Kubernetes, simplemente accediendo a la IP, se necesita algo en el medio que  ayude a asignar la solicitud al nodo desde nuestro ordenador a través del nodo hasta el POD que ejecuta el contenedor web.

Los servicios en Kubernetes

Aquí es donde entra en juego los servicios en Kubernetes. Es un objeto como los PODs, los conjuntos de réplicas o los despliegues que vimos en otros artículos. Su función es la de escuchar un puerto en el nodo y reenviar la solicitud en ese puerto a un puerto en el POD. Este tipo de servicio se conoce como un servicio de puerto de nodo porque escucha el puerto en el nodo y reenvía las solicitudes a los PODs.

kubernetes servicesHay otros tipos de servicios disponibles, como el ClusterIP. En este caso, el servicio crea una IP virtual dentro del clúster para permitir la comunicación entre diferentes servicios en Kubernetes, como un conjunto de servidores front-end a un conjunto de servidores back-end. Otro tipo es un balanceador que proporciona equilibrio de carga para aplicaciones en proveedores de nube. Un ejemplo es la distribución de la carga a través de diferentes servidores web en su nivel de front-end.

Puerto de nodo.

Hemos visto que un servicio puede ayudarnos asignando un puerto en el nodo a un puerto en el POD. Para la tarea hay tres puertos involucrados. El puerto en el POD, que es donde se está ejecutando el servidor web real (puerto 80). Se conoce como el puerto de destino porque allí es donde el servicio reenvía la solicitud. El segundo puerto es el puerto del servicio en sí, y se conoce simplemente como el puerto. Estos términos son desde el punto de vista del servicio. De hecho, el servicio es como un servidor virtual dentro del nodo.

Dentro del clúster, tiene su propia dirección IP, denomina da IP del clúster del servicio. Finalmente tenemos el puerto en el nodo en sí mismo que usamos para acceder al servidor web externamente y que se conoce como el puerto del nodo (puerto 30008). Los puertos de nodo solo pueden estar en un rango válido que, por defecto, es de 30000 a 32767.

Creación

Para crear los servicios, al igual que se crea un conjunto de réplicas, despliegues o PODs, se utiliza un archivo de definición. La estructura de alto nivel del archivo sigue siendo la misma, con las secciones apiVersion, kind, metadata y spec. La versión de API es “v1”, el tipo es “Service”, los metadatos tendrán un nombre del servicio y, opcionalmente, etiquetas, y por último las especificaciones que es la parte más crucial del archivo. Como especificaciones tenemos “type” y “ports”. El tipo se refiere al tipo de servicio que estamos creando: “NodePort”, “NodeIP” o “NodeBalancer”.

Los puertos es una lista con información sobre cada servicio, y cada uno de ellos hay que ingresar la información de “targetPort”, “port” y “nodePort”. De ellos el único campo obligatorio es el puerto, si no se proporciona un puerto de destino, se supone que es el mismo que el puerto y si no proporciona un puerto de nodo, se asigna automáticamente un puerto libre en el rango válido entre 30000 y 32767. Se pueden tener múltiples asignaciones de puertos en un solo servicio.

Conexión

En toda la información anterior falta algo importante, no hay nada que conecte el servicio al POD. Se especifica el puerto de destino, pero podría haber cientos de otros PODs con servicios web ejecutándose en el mismo puerto. Para especificar el POD se hace como con los conjuntos de réplicas, usando la técnica de las etiquetas y selectores para vincularlos. Sabemos que el POD se creó con una etiqueta, así que llevamos esa etiqueta al archivo de definición de servicio. Tenemos una nueva propiedad en la sección de especificaciones llamada “selector”. Al igual que en un conjunto de réplicas y los archivos de definición de despliegues debajo del selector se pone una lista de etiquetas para identificar el POD. Para esto se hace referencia al archivo de definición de POD, extrayendo las etiquetas y colocándolas debajo de la sección del selector. Esto vincula el servicio al POD.

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  spec:
    type: NodePort
    ports:
      - targetPort: 80
        port: 80
        nodePort: 30008
selector:
  app: myapp
  type: front-end

Una vez terminado, se crea el servicio utilizando el comando “kubectl create -f <archivo def.>”. Para ver el servicio creado se ejecuta el comando “kubectl get services” que lista los servicios creados. Ahora podemos usar el puerto para acceder al servicio web mediante curl o un navegador web. Se puede utilizar “kubectl describe service” para obtener más información.

Múltiples nodos en los servicios en Kubernetes

kubernetes varios podsHasta ahora hemos hablado de un servicio asignado a un solo POD, pero no es lo normal. Habitualmente se tienen múltiples PODs en el entorno de producción, con varias instancias de una aplicación web ejecutándose para tener mayor disponibilidad y mejor equilibrio de carga. En este caso, hay múltiples POPDs similares que ejecutan la aplicación y todos tienen las mismas etiquetas, ya que la misma etiqueta se usa como selector durante la creación del servicio. Cuando se crea el servicio, busca un POD coincidente con la etiqueta y encuentra varios de ellos. El servicio selecciona automáticamente todos los PODs como puntos finales para reenviar las solicitudes, por lo que no hay que hacer ninguna configuración adicional. El algoritmo que se utiliza para equilibrar la carga entre todos los PODs es aleatorio. Por lo tanto, el servicio actúa como un balanceador de carga.

kuvernetes varios nodosSi los PODs se distribuyen en múltiples nodos separados, Kubernetes crea automáticamente un servicio que abarca todos los nodos y asigna ese puerto de destino al mismo puerto de nodo en todos ellos. De esta manera, se puede acceder a la aplicación usando la IP de cualquier nodo en el clúster y usando el mismo número de puerto.

Para resumir, ya sea un solo POD en un solo nodo, múltiples PODs en un solo nodo o múltiples PODs en múltiples nodos, el servicio se define exactamente igual sin que se tenga que realizar ningún paso adicional durante la creación del servicio. Cuando los PODs se eliminan o agregan el servicio se actualiza automáticamente haciendo que sea altamente flexible y adaptable. Una vez creado, normalmente no se tendrá que hacer ningún cambio de configuración adicional.

Cluster IP de Kubernetes.

Kubernetes ClusterIPUna aplicación web generalmente tiene diferentes tipos de PODs que alojan diferentes partes. Es posible que tenga una serie de PODs que ejecutan un servidor web front-end, otro conjunto que ejecutan una parte back-end, otro más ejecutan un almacén de valores clave y otro conjunto pueden ejecutar una base de datos persistente como mySQL. El servidor front-end web debe comunicarse con los servidores back-end y los servidores back-end deben comunicarse con la base de datos, así como con los servicios de valores clave, etc.

Todos los PODs tienen una dirección IP asignada, pero son estáticas. Además, los PODs pueden apagarse en cualquier momento y crearse nuevos. Por lo tanto, no se puede confiar en estas direcciones IP para la comunicación interna entre la aplicación. Por último, los PODs de front-end necesitan conectarse a los de back-end, pero ¿a cual y quién toma esa decisión?

Un servicio de Kubernetes puede ayudarnos a agrupar los PODs y proporcionar una interfaz única para acceder a ellos en un grupo. Por ejemplo, un servicio creado para los de back-end ayudará a agrupar todos ellos y proporcionará una única interfaz para que otros PODs accedan a este servicio. Las solicitudes se envían a uno de los PODs al azar gracias a este servicio. Del mismo modo, se pueden crear servicios adicionales para el servidor de claves que permita que los módulos de back-end accedan a ese sistema.

Creación

Esto nos permite implementar de manera fácil y efectiva una aplicación basada en microservicios en el clúster de Kubernetes. Cada capa ahora puede escalar o moverse según sea necesario sin afectar la comunicación entre los diversos servicios. Cada servicio recibe una IP y un nombre asignados dentro del clúster y ese es el nombre que deben usar otros PODs para acceder al servicio. Este tipo de servicio se conoce como IP de clúster.

Para crear un servicio se usa la misma plantilla predeterminada con su “apiVersion”, “kind”, “metadatos” y “spec”. La apiVersion es v1, el tipo es “Service”, le daremos un nombre al servicio en los metadatos, por ejemplo “back-end”. Bajo las especificación tenemos el “type” y “Ports”. El tipo es “IP de clúster”, de hecho, la IP de clúster es el tipo predeterminado, por lo que incluso si no se especifica, automáticamente asumirá que ese tipo es IP de clúster en los puertos. Y, por último, tenemos un puerto de destino, que es el puerto donde está expuesto el back-end, y el puerto de servicio que es donde está expuesto el servicio. Por último hay que copiará las etiquetas de la definición del POD debajo del selector y eso debería ser todo.

Más información: https://kubernetes.io/docs/concepts/services-networking/service/