Hasta ahora hemos planteado nuestro entorno pensando solo en una o varías aplicaciones que realmente funcionan de manera autonóma, es decir, si pensamos en nuestro POD con el fork del juego de SUPER MARIO vemos como realmente no tiene comunicación con nada más y en un primer momento no la necesita (o nosotros a la hora de usarlo tampoco).

Ahora propongo otro escenario, como pudiera ser que tenemos un pequeño portal donde el usuario necesita hacer login antes de poder acceder a nuestro juego. Si lo planteamos como si realmente fueran servicios distintos tendriamos por ejemplo:

  • Lo que es el front, que no sería más que una miniweb con un login y a lo mejor una lista de posibles juegos.
  • Puede que un microservicio que gestionaría los usuarios y nos permitiría hacer login o un microservicio que fuera realmente la API con la lista de juegos disponibles
  • Y por dejarlo simple un microservicio que sería el fork de nuestro juego de SUPER MARIO y otro que puede ser un fork del SONIC por ejemplo.

Es posible que este escenario no tenga ningún sentido ojo, por el tema de la autenticación y demás, es solo para que entendamos que tendríamos varios microservicios distintos que gestionar. Esto con los objetos y configuraciones que hemos visto hasta ahora puede que lo pudieramos conseguir si tenemos un objeto de tipo SERVICE:NODEPORT por cada microservicio y el microservicio de front sepa donde esta todo (superfeo) o a lo mejor hacerlo con subdominios y con DNS o cosas así (se me están ocurriendo sobre la marcha pueden no tener sentido). El caso es que a no ser que lo gestionaramos en un servicio cloud que nos pudiera hacer el enrutamiento no tenemos una forma clara de hacerlo. Bueno pues para esto tenemos en kubernetes el objeto de tipo INGRESS.

Este objeto lo que hace es definir como se deben gestionar las peticiones que vienen desde fuera de nuestro cluster, es decir, hacia donde debe redireccionar cada petición. Veamos una diagrama de la documentación oficial donde creo yo que se explica bastante bien cual es la tarea de nuestro INGRESS

Captura-de-pantalla-2021-01-17-a-las-18.58.18

Este diagrama que vemos resume un escenario típico que tendríamos en producción:

  1. El cliente envía una petición que lo primero que hace es llegar al balanceador de carga de nuestro cloud. Este balanceador de carga está manejado por un INGRESS CONTROLLER que es el que se encarga de asegurarse de que se cumplan las reglas que definimos en nuestro objeto INGRESS
  2. Según las reglas que hayamos definido nuestro INGRESS CONTROLLER decide a que servicio (objeto de tipo SERVICE) de nuestro cluster debe enviar la petición en cuestión
  3. Por último este service envía la petición al primero de sus PODS que este disponible

Un detalle que no hemos dejado claro todavía es que las reglas que definimos en el objeto de tipo INGRESS no son manejadas realmente por kubernetes, si no que necesitamos de un controlador externo (INGRESS CONTROLLER para que las gestione). Como tal existen opciones de configuración de ingress disponibles para NGINX, HAPROXY, TRAEFIK... para la mayoría de los servicios de proxy, uno de los más típicos es el de nginx. En un entorno en cloud seria necesario tener un POD con nginx que sería nuestro INGRESS CONTROLLER.

Comentar que el entorno completo en cloud con su loadbalancer, su ingress y demás no lo veremos de momento, en la documentación oficial viene todo lo necesario creo yo, por ahora con motivos puramente de prueba o académicos usaremos la opción que nos provee minikube para tener nuestro propio INGRESS CONTROLLER.

Veamos lo primero un ejemplo de objeto tipo INGRESS, como no parece existir de momento comando dry-run para verlo, nos tocará copiar un ejemplo como este

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mario-ingress
spec:
  rules:
  - host: mariogame.fulldev.ninja
    http:
      paths:
      - path: /mario
        pathType: Prefix
        backend:
          service:
            name: mario-service
            port:
              number: 8000
  defaultBackend:
    service:
      name: default-service
      port:
        number: 8001

Creo que es bastante intuitivo lo que hace cada cosa pero hablemos un poco en detalle de algunos puntos:

  • apiVersion: networking.k8s.io/v1: Aquí si nos fijamos tenemos un cambio respecto a lo que soliamos indicar en el resto de objetos, en este caso debemos especificar que pertenece a la api de networking de kubernetes.
  • spec: Como siempre dentro de spec tenemos siempre la definición de lo que queremos hacer.
  • rules: Dentro de rules como su propio nombre indica es donde definiremos las reglas que queremos usar dentro de nuestro ingress
    • host: hostname al cual enviará el cliente las peticiones
    • http -> paths: Estos serán los paths que usará nuestro ingress controller para redireccionar la petición a un servicio o a otro.
    • pathType: Como se filtrarán los paths, el caso más típico es el de Prefix que buscará coincidencias en el path completo separandolo por /
    • backend -> service: El servicio que debe responder al path indicado
  • defaultBackend: Aquí definimos el servicio por defecto en caso de que no se encontraran coincidencias en el resto de reglas

Como siempre existen muchas más reglas pero estas son las básicas y que me han parecido relevantes para empezar (vuelvo a recomendar leer la documentación oficial)

Una vez visto lo básico, veamos como configurar un ingress controller en minikube (recordemos que en un entorno cloud tenemos que tener nuestro propio pod que haga de controller).
Para ello lo primero es hablar de los addons de minikube. Minikube dispone de ciertos extras que podemos habilitar según nos insterese, uno de ellos es el ingress controller, este ingress que nos provee minikube es una propia intancia de nginx preparada para este uso y que en este caso no podremos ver como uno de los pods que hemos estado viendo hasta ahora (en un momento veremos lo que pasa)

OJO esta parte solo funciona si has iniciado minikube con algún gestor de máquinas virtuales como virtualbox doc oficial. Ver al final del post el apartodo INICIAR MINIKUBE CON VIRTUALBOX o también es posible jugar con este playground

Primero veamos la lista de addons, para ello solo es necesario que ejecutemos este comando:

minikube addons list

Esto nos mostrará una lista de los addons disponibles indicándonos si están habilitados o no (algunos estarán habilitados por defecto según nuestra instalación)

Captura-de-pantalla-2021-01-22-a-las-10.42.44

Si os fijáis uno de los addons que aparecen es el de ingress, habilitemoslo

minikube addons enable ingress

Captura-de-pantalla-2021-01-22-a-las-11.08.49

Con esto ya tendríamos habilitado nuestro ingress controller con nginx, pero como he comentado no nos aparece como un pod normal en este entorno.

Captura-de-pantalla-2021-01-22-a-las-11.10.12

Minikube en este caso lo crea como un pod propio del sistema de minikube por lo que para verlo tendríamos que listar los pods que pertenecen a minikube, para ello

kubectl get pods -n kube-system

Y esto nos listará todos los pods que va creando minikube

Captura-de-pantalla-2021-01-22-a-las-11.12.23

Si nos fijamos tenemos uno en específico que se llama nginx-controller.

Bien con esto ya tendríamos nuestro ingress controller, ahora vamos a trabajar con los mismos ejemplos que la documentación oficial (el de mario da algunos problemas con los direccionamientos y por no entrenernos), primero el deploy

example-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:1.0
        name: hello-app
        resources: {}
status: {}

El service

mario-service.yaml

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: web
  type: NodePort
status:
  loadBalancer: {}

Hacemos los create pertinentes que ya hemos visto anteriormente

kubectl create -f example-deploy.yaml
kubectl create -f example-service.yaml

Y por último preparamos nuestro ingress

example-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
    - host: hello-world.info
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 8080

Y creamos nuestro ingress

kubectl create -f example-ingress.yaml

Esto nos creará nuestro ingress tardará un poco en tenerlo todo (fijaos en el ADDRESS)

Captura-de-pantalla-2021-01-22-a-las-12.26.20

Como véis tenemos nuestro ingress creado, un detalle para que no nos alarmemos es el warning que aparece. Nosotros en nuestra definición de ingress hemos definido el uso de la api de kubernetes v1, lo que pasa es que el comando get ingress comprueba la existencia de ingress desde la primera versión que tiene disponible, por eso el aviso, no quiere decir que nuestra definición de ingress esté realmente mal.

Bien ahora que ya tenemos nuestro ingress desplegado veamos como podemos acceder a el. La primera intención puede ser intentar acceder por la IP, pero si lo intentamos veremos un 404 de nginx. Esto no es del todo malo, comprobamos que tenemos comunicación con nuestro ingress controller

Captura-de-pantalla-2021-01-22-a-las-11.35.58

Para el que no sepa realmente como funcionan los proxys como nginx, lo que hacen normalmente es esperar que el acceso se produzca con un nombre de host específico, es posible que tengamos varios hostname distintos bajo el mismo nginx. En nuestro mismo caso podemos querer tener otro hostname para otro servicio que bye-world.info

Entonces lo que tenemos que hacer es modificar nuestra definición local de redirecciones IP/HOSTNAME, en mi caso lo tengo que hacer en el fichero /etc/hosts

Captura-de-pantalla-2021-01-22-a-las-12.26.20-1

Una vez modificado si accedemos al hostname en cuestión veremos como accedemos sin problema al servicio pertinente

Captura-de-pantalla-2021-01-22-a-las-12.28.09

Con esto tendríamos funcionando un ingress controller que puede redireccionar multiples peticiones a distintos servicios basandonse en el nombre del hosts o un path (en nuestro hemos puesto / pero podría ser cualquier otro)

Con esto habríamos visto lo básico para trabajar con ingress, el resto ya es revisar la documentación y ver las distintas opciones que nos ofrece kubernetes para cumplir con nuestras necesidades, sin mucho más terminamos este post, nos vemos en el siguiente un abrazooooorrrr

INICIAR MINIKUBE CON VIRTUALBOX

Esta es una sección para los que hayan estado jugando con el propio driver de docker (el que nos provee docker-desktop) para probar kubernetes que al final llega un punto en el que algunas cosas no funcionan de ninguna forma (depende de las versiones, van incluyendo poco a poco funcionalidades compatibles).

Lo primero que tenemos que hacer es borrar minikube de nuestro entorno, recomiendo borrar todo y hacer una instalación limpia para ello lo primero es:

minikube delete --all --purge

Esto nos borra todo lo que tenemos de minikube

Captura-de-pantalla-2021-01-22-a-las-11.02.33

A continuación instalamos virtualbox -> Downlaads

Una vez instalado todo lo que hacemos es arrancar minikube con el driver de virtualbox

minikube start --driver=virtualbox

Captura-de-pantalla-2021-01-22-a-las-11.03.47

Esto tardara un rato hasta crea las máquinas virtuales pertinentes

Captura-de-pantalla-2021-01-22-a-las-11.06.40

Con esto ya tendriamos arrancado nuestro minikube con un cluster de maquines virtuales. Well done!!!