Objetivos

Al finalizar el tutorial el estudiante estará en capacidad de:

Pasos previos

En particular se utilizarán los siguientes recursos:

  1. Repositorio privado con la imagen de contenedor de la aplicación suma, el cual fue publicado en el tutorial Container Registry. Por favor realice ese tutorial antes de continuar con el desarrollo de esta guía.
  2. gcloud SDK para acceder a los servicios del proveedor Google Cloud Platform a partir de la consola. En caso de no tenerla instalada puede consultar el siguiente manual de instalación:https://cloud.google.com/sdk/docs/install
  3. Herramienta de control de Kubernetes, kubectl. En caso de no tenerla instalada puede consultar el siguiente manual de instalación: https://kubernetes.io/docs/tasks/tools/#kubectl

Para este tutorial manejaremos el repositorio de calculadora-numeros usado en los tutoriales pasados, en caso de no tenerlo clonado aún, puede consultarlo en el siguiente enlace. Trabajaremos sobre la rama feature/ingress, para ello cambie la rama del repositorio actual al respectivo hash del tag, para hacerlo ejecute en su terminal:

user@192 ~ % git checkout feature/ingress

Si ya se encuentra en esta rama, haga caso omiso al comando presentado anteriormente.

Kubernetes Ingress es un objeto API que proporciona reglas de enrutamiento para administrar el acceso a los servicios dentro de un clúster de Kubernetes. Por lo general, utiliza los protocolos HTTPS y HTTP para facilitar el enrutamiento.[1]

Ingress es la opción ideal para un entorno de producción. Los usuarios pueden exponer servicios dentro del clúster de Kubernetes sin tener que crear varios balanceadores de carga o exponer servicios manualmente.[1]

Figura tomada de https://kubernetes.io/docs/concepts/services-networking/ingress/

Para crear un ingress hemos creado un nuevo archivo yml donde se describe de forma declarativa el despliegue de todos los microservicios junto con el ingress. Abra el archivo nombre k8s-deployments.yml

Para los siguientes pasos se recomienda trabajar con un ambiente sin contenedores en ejecución. Para ello puede destruir los despliegues y los servicios haciendo uso del comando delete:

kubectl delete all --all -n default

En el archivo encontrará la configuración del servicio suma con el que ya hemos trabajado anteriormente. Modifique el la línea 22 con la URI de la imagen de la aplicación suma que trabajamos en talleres anteriores.

###################################
# SUMA
###################################
apiVersion: apps/v1
kind: Deployment
metadata:
  name: suma
  labels:
    app: suma
spec:
  replicas: 1
  selector:
    matchLabels:
      app: suma
  template:
    metadata:
      labels:
        app: suma
    spec:
      containers:
        - name: suma
          image: us-central1-docker.pkg.dev/uandes-native/uniandes-misw-native-calculadora-app/suma:1.0
          ports:
            - containerPort: 4000
          # Realizar pull siempre a la imagen
          imagePullPolicy: Always

Dónde <image-uri> es la uri de la imagen en su proyecto.

Posterior a la configuración del despliegue, encontrará el componente BackendConfig.

## BackendConfig Suma
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: calculadora-numeros-suma-config
spec:
  healthCheck:
    checkIntervalSec: 30
    port: 4000
    type: HTTP
    requestPath: /health/
---

Como puede observar este componente define el healthCheck de su servicio. Dado que nuestros servicios se ubicarán detrás de un único balanceador de carga configurado por el ingress, este estará realizando peticiones para verificar el estado del servicio, si el servicio no responde por medio del endpoint definido, el balanceador lo marcará como caído y no le enviará tráfico.

Por lo tanto, el endpoint de /health en el microservicio, se encargará principalmente de recibir peticiones y responder exitosamente si la contenedora está con vida. Es una estrategia de resiliencia a las fallas para conocer cuántas máquinas de nuestro cluster siguen disponibles. Esta sección abarca literales como:

  1. checkIntervalSec: Tiempo de sondeo para llamar al endpoint de /health.
  2. port: Puerto definido por la contenedora para recibir la solicitud.
  3. requestPath: Ruta del endpoint definido.
  4. type: Protocolo por el cual se va a validar la solicitud.

Posteriormente encontrará el servicio de suma.

---
kind: Service
apiVersion: v1
metadata:
  name: servicio-suma
  annotations:
    cloud.google.com/backend-config: '{"default": "calculadora-numeros-suma-config"}'
spec:
  type: NodePort
  selector:
    app: suma
  ports:
    - protocol: TCP
      port: 80
      targetPort: 4000
      nodePort: 31019
---

Si observamos el componente se declara básicamente igual que como lo hemos hecho antes, la diferencia reside en que declaramos un nodo de tipo NodePort y no de LoadBalancer. Un NodePort es un puerto abierto en cada nodo de su clúster. Kubernetes enruta de manera transparente el tráfico entrante en NodePort a su servicio, incluso si su aplicación se ejecuta en un nodo diferente. En este fragmento comprende información nueva como:

Note también que ahora el backend config se relaciona en el servicio.

La demás información presente en ese fragmento corresponde a metadata y anotaciones del CSP (Cloud service provider).

Para poder desplegar nuestros servicios como si fuera un solo nodo y beneficiarnos del servicio del ingress necesitamos otro servicio disponible. Para esto ponga en práctica lo aprendido en el tutorial de creación de imagen y cree una nueva imagen a partir del microservicio de multiplicación el cual encontrará en la carpeta /multiplicacion. Una vez creada la imagen publíquela en su artifact registry, luego de hacer el push podrá ver lo siguiente en la consola de GCP:

Con la imagen del microservicio de suma y el de multiplicación publicados. Ahora debemos agregar la nueva imagen a nuestro archivo k8s-deployment.yml. Modifique la línea 79 con la uri del repositorio de su imagen de multiplicación. Le recomendamos revisar el resto de la configuración del servicio multiplicación.

Ahora que nuestras imágenes están relacionadas en el archivo de nuestro despliegue, encontrará que en la parte inferior se declara el ingress. Analice cómo se configura cada uno de los servicios:

# INGRESS
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gateway-ingress
  labels:
    name: gateway-ingress
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: /suma
        backend:
          service:
            name: servicio-suma
            port: 
              number: 80
      - pathType: Prefix
        path: /multiplicar
        backend:
          service:
            name: servicio-multiplicacion
            port: 
              number: 80

Recuerde que el ingress ejerce la función de una puerta para conectar y dirigir el tráfico a los microservicios que tenga registrados, para lograrlo debemos declarar las siguientes líneas:

  1. ImplementationSpecific: la coincidencia de prefijo de ruta se delega al controlador de ingreso (IngressClass).
  2. Exact: coincide exactamente con la ruta de la URL (se distingue entre mayúsculas y minúsculas)
  3. Prefix: coincidencias basadas en un prefijo de ruta de URL dividido por /. La coincidencia distingue entre mayúsculas y minúsculas y se realiza elemento por elemento de ruta. [2]

Con el archivo de configuración completo, vamos a realizar el despliegue.

Para aplicar el ingress con la nueva configuración del archivo utilice el siguiente comando:

user@192 ~ % kubectl apply -f k8s-deployments.yml

Podrá observar lo siguiente:

user@192 ~ % kubectl apply -f k8s-deployments.yml
Warning: Autopilot set default resource requests for Deployment default/calculadora-numeros-suma, as resource requests were not specified. See deployment.apps/suma created
backendconfig.cloud.google.com/calculadora-numeros-suma-config created
service/servicio-suma configured
deployment.apps/multiplicacion created
backendconfig.cloud.google.com/calculadora-numeros-multiplicacion-config created
service/servicio-multiplicacion created
ingress.networking.k8s.io/gateway-ingress-8 created

Si se fija en los logs de despliegue con detenimiento, una parte se asocian a los de suma y los otros a los de multiplicación. Para validar que el ingress este desplegado con éxito, diríjase a la consola de GCP a la sección de kubernetes y podrá ver lo siguiente:

De click al nombre del ingress creado, allí podrá ver las rutas destinadas para cada microservicio declaradas en el archivo.

Luego de unos minutos podrá ver en su consola el check verde del despliegue. Si va a la pestaña del despliegue podrá ver la dirección IP asociada al ingress creado

En el caso del ejemplo corresponde a 35.190.90.190. Para probar que el despliegue está funcionando, identifique su IP externa y reemplazarla en el siguiente curl:

user@192 ~ % curl --location --request POST 'http://<IP-BALANCEADOR>/suma' \
--header 'Content-Type: application/json' \
--data-raw '{
    "num_1": 399,
    "num_2": 1
}'

Para el caso del ejemplo, el endpoint de suma corresponde a:

user@192 ~ % curl --location --request POST 'http://35.190.90.190/suma' \
--header 'Content-Type: application/json' \
--data-raw '{
    "num_1": 399,
    "num_2": 1
}'

Obteniendo el resultado:

{
    "message": "Estudiante la suma de los dos numeros es: 400",
    "result": 400
}

Para probar el endpoint de multiplicación simplemente cambie el path /suma por /multiplicar, para el caso del ejemplo se ve de la siguiente manera:

user@192 ~ % curl --location --request POST 'http://35.190.90.190/multiplicar' \
--header 'Content-Type: application/json' \
--data-raw '{
    "num_1": 399,
    "num_2": 1
}'

Obteniendo el resultado:

{
    "message": "Estudiante la multiplicacion de los dos numeros es: 399",
    "result": 399
}

¡Éxitos en el desarrollo del tutorial y nos vemos en una próxima oportunidad!

[1] 23, J. and Wickramasinghe, S. (2021) Kubernetes Ingress explained, BMC Blogs. Available at: https://www.bmc.com/blogs/kubernetes-ingress/ (Accessed: December 2, 2022).

[2]Kubernetes Ingress Goes Ga (no date) Google Open Source Blog. Available at: https://opensource.googleblog.com/2020/09/kubernetes-ingress-goes-ga.html (Accessed: December 2, 2022).