AKS: Creación de Azure Kubernetes Service y despliegue de aplicación multi-container (3/3)

1. Introducción

En este artículo, último de la serie (artículo 3/3), se muestra en primer lugar como crear un cluster de Azure Kubernetes Service (en adelante cluster AKS) para desplegar nuestra aplicación multi-container de Docker (artículo 1/3) utilizando Azure Container Registry (en adelante registro ACR) como almacen de repositorios de nuestras imágenes (artículo 2/3).

Además se proporcionan explicaciones detalladas sobre los ficheros de despliegue YAML en kubernetes, especialmente acerca de los objetos de tipo deployment, pod template y service, imprescindibles para entender la infraestructura básica que constituye el "interior" de kubernetes.

Por último, también se explica lo más destacado de la infraestructura interna de recursos generados en Azure para dar soporte al cluster AKS (Virtual Networks, Subnets, Network Security Groups, Virtual Machine Scale Sets, Load Balancers, Route Tables, etc.) y así entender mejor todo lo que hay "detrás" de AKS (que no es poco...).

2. Consideraciones Generales

Antes de crear y empezar a utilizar nuestro cluster AKS es preciso tener en cuenta las siguientes consideraciones previas:

  • Para crear el cluster AKS es preciso autenticarnos de forma previa en Azure con una cuenta con el rol de Owner sobre la suscripción en la que se procederá al despliegue de recursos.
  • El tamaño mínimo de máquina virtual (nodo en AKS) aceptado debe tener al menos 2 cores con 4GB de memoria. La selección por defecto son máquinas Linux con tamaño Standard_DS2_v2. En este caso se usará un tamaño más pequeño, en concreto Standard_B2s, con el consiguiente ahorro de costes ya que únicamente vamos a usar el cluster AKS con fines de desarrollo o demo | Ver documentación Azure-CLI az aks para obtener toda la lista de parámetros y valores por defecto usados en la creación de clusters AKS. 
  • AKS usará Azure Container Registry (ACR) para extraer imágenes (pull). Por tanto, AKS necesita autenticarse en ACR antes de realizar la acción de extracción o pull. Para resolver este tema hay dos posibilidades, ambas a ejecutar dentro del proceso de creación del cluster AKS y mediante uso de service principal
    • No referenciar ningún service principal existente y dejar que AKS lo cree por defecto.
    • Crear un nuevo service principal y referenciarlo en el proceso de creación del cluster AKS. Esta será la opción utilizada en este artículo, si bien podrías usar perfectamente la primera de ellas. Los pasos para crear el service principal puedes verlos a continuación, sustituye SP_NAME y SP_PASSWORD por los tuyos propios:
      • az ad sp create-for-rbac --name "SP_NAME"
      • az ad sp credential reset --name "SP_NAME" --password "SP_PASSWORD"
  • El service principal utilizado, de acuerdo al punto anterior y una vez creado el cluster, será provisto del rol ACRPull sobre el registro ACR de forma automática. En mi caso el SP_NAME utilizado ha sido jm-inn-aks-acr-pull-sp:

  • Se asume un conocimiento mínimo de los comandos básicos de kubectl (cliente CLI de kubernetes para administrar el cluster), si bien se irá explicando de forma práctica qué hace cada uno de los comandos empleados en este artículo.

3. Creación del Cluster de Azure Kubernetes Service

Antes de crear el cluster AKS es necesario autenticarse en Azure con una cuenta con permisos de Owner sobre la suscripción en la que vamos a crear el cluster AKS. Una vez autenticados con esta cuenta podemos ejecutar el código que se muestra a continuación con las explicaciones oportunas:

# Establece suscripción sobre la cual se va a crear el cluster AKS.
# Debes introducir los valores asociados a TU suscripción.
$subscription_id = "00000000-0000-0000-0000-000000000000"
 
# Establece suscripción de trabajo.
az account set --subscription $subscription_id

# Establece nombre del grupo de recursos en el que se creará el cluster AKS.
# Sustituye dicho valor por el tuyo propio.
$rg = "jm-inn-acr-aks-intro-rg"

# Establece el registro ACR usado por AKS para extraer imágenes.
# Sustituye dicho valor por el tuyo propio.
$acrName = "jminnacr"

# Tamaño de lás máquinas virtuales (nodos) del cluster AKS.
# Por defecto se establece Standard_DS2_v2.
# Modificamos el tamaño a uno más pequeño por ser un proyecto demo y ahorrar costes.
# El tamaño elegido debe tener al menos 2 cores y 4GB de memoria.
$node_vm_size= "Standard_B2s"

# Establece nombre del cluster AKS.
# Sustituye dicho valor por el tuyo propio.
$aksName = "jm-inn-aks"

# Referencia al service principal usado por AKS para acceder a ACR.
# Una vez creado el cluster, este service principal contendra el rol AcrPull sobre el ACR.
# Sustituye estos valores por el tuyos propios.
$client_id_aks_acr_pull_sp     = "00000000-0000-0000-0000-000000000000"
$client_secret_aks_acr_pull_sp  = "XXXXXXXX"

# Crea cluster AKS con 2 nodos.
# Se referencia ACR previamente creado para extraer las imágenes Docker.
# Referencia al service principal a utilizar por AKS para autenticarse y acceder a ACR.
az aks create --resource-group $rg --name $aksName --node-count 2 --generate-ssh-keys --attach-acr $acrName --service-principal $client_id_aks_acr_pull_sp --client-secret $client_secret_aks_acr_pull_sp --node-vm-size $node_vm_size

# Configura cliente de kubernetes (kubectl) para conectar al cluster AKS.
# La salida del comando debería ser similar a:
# Merged "jm-inn-aks" as current context in C:\Users\xxxxxx\.kube\config
az aks get-credentials --resource-group $rg --name $aksName --overwrite-existing

# Verifica conexión al cluster AKS consultando los nodos existentes.
kubectl get nodes
 
Esta es la salida del comando anterior. Como se ve en la imagen se han creado dos nodos denominados aks-nodepool1-10285740-vmss000000aks-nodepool1-10285740-vmss000001:
 
 
Con estos simples pasos quedaría creado nuestro cluster de kubernetes en Azure con dos nodos con sistema operativo Linux. Realmente sencillo.

4. Infraestructura Generada en Azure 

 Ahora vamos a investigar un poco más en detalle la infraestructura creada en Azure para dar soporte al cluster AKS:
 

- Lo primero que podemos ver es que el cluster AKS (jm-inn-aks) ha sido creado en el grupo de recursos fijado en el código incluido en el capítulo 3 (jm-inn-acr-aks-intro-rg):

 
Si accedemos al cluster AKS pulsando en el nombre jm-inn-aks, podemos ver algunos datos generales (opción de menu Overview) interesantes, a tener en cuenta a lo largo de este artículo, como la versión de kubernetes, pools, tamaño de los nodos e información de networking relativa al tipo de red implementada (kubenet), rangos de direcciones IP para servicios, pods, etc:
 
Node Pools:
 
Networking:
 
- Puedes echar un ojo también a la sección de menú Kubernetes Resources, aunque será mucho más interesante una vez despleguemos nuestras aplicaciones, para visualizar los deployments, services y pods asociados:
 
 
- Lo siguiente destacado que se observa es que Azure crea de forma automática un grupo de recursos adicional denominado MC_<nombre_grupo_recursos_original>_<nombre_region> de forma paralela al grupo de recursos donde hemos creado el cluster AKS. En mi caso este grupo autogenerado se denomina MC_jm-inn-acr-aks-intro-rg_jm-inn-aks_westeurope. Estos son los recursos generados en dicho grupo de recursos:
 
 
Es importante destacar la creación de un grupo de escalado de máquinas virtuales o Virtual machine scale set, denominado en mi caso aks-nodepool1-10285740-vmss, que incluye las máquinas virtuales que constituyen los nodos de kubernetes. Si accedemos a las instancias del Virtual machine scale set mediante el portal de Azure podemos comprobar la lista de instancias. Puedes verificar que el nombre de las instancias coincide con el nombre de los nodos devueltos por el comando kubectl get nodes visto anteriormente:
 
 
 
También es importante resaltar la creación de un distribuidor de carga o Load balancer, denominado kubernetes (echo en falta algún prefijo o sufijo del tipo lb para identificar el tipo de componente sólo con el nombre...), para distribuir tráfico sobre los diferentes nodos o instancias del Virtual machine scale set. Si accedemos al load balancer podemos comprobar que ha sido configurado con dos backend pools que incluyen todas las máquinas del Virtual machine scale set, el primer backend relacionado con el tráfico saliente (aksOutboundBackendPool) y el segundo (kubernetes) para dar cobertura al tráfico entrante recibido por el load balancer
 
 
Asociada al backend aksOutboundBackendPool del load balancer también se ha creado una regla de salida (outbound rule) denominada aksOutboudRule que permite accionar la traducción de direcciones IP de salida para el tráfico saliente procedente de cualquier máquina virtual existente en el backend (SNAT - Source Network Address Translation). El uso de reglas de salida requiere un SKU de tipo standard en el load balancer (que precisamente es el valor por defecto cuando se crea el cluster AKS) y al menos una dirección IP pública en el frontend del load balancer.
 
 
 
Así pues, asociada a la regla de salida aksOutboudRule, también se ha creado una dirección IP pública asignada al frontend existente hasta el momento en el load balancer:
 
 
Cuando una máquina virtual ("desde IP Origen") inicie una petición al "exterior" ("hacia IP Destino"), la dirección IP Origen es sustituida por la dirección IP pública asociada al frontend en la regla de salida una vez la petición sale del load balancer (proceso SNAT). El "exterior" no ve la dirección IP interna de la máquina virtual, sino que ve la dirección IP pública por la que ha sido reemplazada y a esa misma IP pública enviará la respuesta. Una vez recibida la respuesta en el load balancer, ésta será reenviada a la máquina virtual interna usando algoritmos basados en mapeos de direcciones IP y puertos (PAT o Port Address Translation). Puedes obtener más detalles en Outbound connections in Azure (Escenario 2: Uso de load balancer con máquinas virtuales sin direcciones públicas propias asignadas). Rescato del enlace anterior el resumen (en inglés) de los procesos SNAT y PAT:
 
When Virtual Machine creates an outbound flow, Azure translates the private source IP address of the outbound flow to the public IP address of the public Load Balancer frontend via SNAT (Source Network Address Translation). Ephemeral ports of the load balancer's frontend public IP address are used to distinguish individual flows originated by the Virtual Machine via PAT (Port Address Translation).
 
El backend kubernetes será utilizado para dar soporte a la distribución del tráfico entrante en el load balancer una vez despleguemos nuestra aplicación sobre el cluster AKS. Como se verá posteriormente, cada vez que se despliega una nueva aplicación (expuesta por un servicio tipo load balancer en kubernetes) que debe interactuar con el exterior, un nuevo frontend será creado en el load balancer con una dirección IP pública nueva así como nuevas reglas de balanceo de carga (load balancing rules) y de comprobación de estado de salud de los nodos.
 
Por último, mencionar la creación de los componentes de networking necesarios para hospedar la infraestructura anterior y gestionar el tráfico de red:
 
  • Virtual Network aks-vnet-10285740 con rango 10.0.0.0/8. Tenlo en cuenta si vas a desplegar otras virtual networks para no solapar espacios de direcciones. Muy importante para evitar conflictos si vas a comunicar esta red con otras vía network peering, etc. En mi caso, lo haré para verificar algunos accesos a los servicios expuestos por kubernetes usando la opción nodeport.
  • Subnet aks-subnet con rango 10.240.0.0/16 y Network Security Group aks-agentpool-10285740-nsg. Los nodos o máquinas virtuales tomarán una dirección IP interna en la red en este rango.
  • Tabla de rutas aks-agentpool-10285740-routetable asociada a la subnet aks-subnet con las rutas mostradas más abajo para gestión interna de kubernetes. Los pods de kubernetes reciben direcciones IP fuera del rango de direcciones asignado a la subred de Azure. Solo los nodos reciben una dirección IP perteneciente a la subred. Por tanto, el tráfico sobre pods es redirigido a los nodos o máquinas virtuales usando esta tabla de rutas. Las direcciones IP asignadas a los pods solo tienen sentido en el interior del cluster AKS. Esta es la configuración de red establecida por defecto en la creación del cluster AKS, en concreto de tipo kubenet:

With kubenet, only the nodes receive an IP address in the virtual network subnet. Pods can't communicate directly with each other. Instead, User Defined Routing (UDR) and IP forwarding is used for connectivity between pods across nodes. By default, UDRs and IP forwarding configuration is created and maintained by the AKS service, but you have to the option to bring your own route table for custom route management. You could also deploy pods behind a service that receives an assigned IP address and load balances traffic for the application.

 

Este sería el esquema de la red y sus diferentes componentes hasta el momento:

Una vez hemos visto la infraestructura creada en Azure podemos "escalar" de 2 a 3 nodos nuestro cluster AKS con el siguiente comando:

az aks scale --resource-group $rg --name $aksName --node-count 3

Un nuevo nodo es creado en el cluster AKS, lo cual se traduce en una nueva máquina virtual añadida al virtual machine scale set, nueva ruta en la tabla de rutas, etc.

5. Fichero de Configuración de Despliegue YAML

Una vez creado el cluster de AKS y antes de desplegar nuestra aplicación multi-container creada con docker-compose, vamos a comentar el fichero yaml usado para desplegar la aplicación en el cluster. Se añaden los comentarios y enlaces oportunos sobre cada una de las configuraciones:

# Deployment de kubernetes para el Backend de la aplicación
apiVersion: apps/v1
# Definición de deployment
kind: Deployment
metadata:
  # Nombre del deployment
  name: jm-inn-azure-vote-back-deployment
spec:
  # Número de réplicas o pods a crear en el despliegue
  replicas: 1
  # Selector de pods usados para crear las réplicas
  selector:
    matchLabels:
      # Selecciona pods con la etiqueta app:jm-inn-azure-vote-back
      app: jm-inn-azure-vote-back
  # Plantilla que define los pods.
  template:
    metadata:
      labels:
        # Fija etiquetas para los pods (key: value)
        # Son referenciadas desde los objetos deployment para crear réplicas
        app: jm-inn-azure-vote-back
    spec:
      nodeSelector:
        # Fija selector de nodo sobre el que se ejecuta el pod
        "beta.kubernetes.io/os": linux
      containers:
        # Establece nombre del container en el pod
      - name: jm-inn-azure-vote-back-container
        # Extrae la imagen redis del repositorio por defecto, es decir, Docker Hub.
        image: redis
        ports:
          # Expone el puerto en el que el container escucha peticiones
          # Debe ser el puerto asociado a la redis cache (6379)
        - containerPort: 6379
           name: redis # Nombre asignado al puerto
 
# Servicio de kubernetes para exponer el Backend de forma interna al Cluster
# Un servicio en kubernetes expone un grupo de pods con la misma funcionalidad para servir peticiones. Los pods se ejecutan en cualquiera de los nodos del cluster. El servicio es una abstracción que permite añadir un nivel de desacoplamiento entre las peticiones entrantes del exterior y los pods.
apiVersion: v1
kind: Service
metadata:
 # Nombre del Servicio
  name: jm-inn-azure-vote-back-service
spec:
  ports:
    # Puerto en el que escucha el servicio
  - port: 6379
  selector:
    # Selector de pods basado en etiquetas
    app: jm-inn-azure-vote-back
 
# Deployment de kubernetes para el Frontend de la aplicación
apiVersion: apps/v1
kind: Deployment
metadata:
  # Nombre del despliegue o deployment
  name: jm-inn-azure-vote-front-deployment
spec:
  # Número inicial de réplicas o pods a crear en el despliegue
  replicas: 2
  # Selector de Pods para crear las réplicas
  selector:
    matchLabels:
      # Selecciona pods a incluir en el despliegue como replicas
    # Los pods deben incluir la etiqueta app:jm-inn-azure-vote-front
      app: jm-inn-azure-vote-front
  # Método de despliegue para reemplazar réplicas
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  minReadySeconds: 5 
  template:
    metadata:
      labels:
        # Define etiquetas para los pods creados a partir de la plantilla
        app: jm-inn-azure-vote-front
    spec:
      nodeSelector:
        # Fija selector de nodo sobre el que se ejecuta el pod
        "beta.kubernetes.io/os": linux
      containers:
        # Nombre asignado al contenedor
      - name: jm-inn-azure-vote-front-container
        # Imagen a extraer para crear el contenedor
        # La imagen se extrae desde nuestro Azure Container Registry
        image: jminnacr.azurecr.io/jm-inn-azure-vote-front-image:v1
        ports:
          # Puerto en el que escucha el contenedor
        - containerPort: 80
        resources:
          requests:
            cpu: 250m
          limits:
            cpu: 500m
        # Fija variables de entorno para el container
        env:
          # Nombre de la variable de entorno
        - name: REDIS
          # Valor de la variable de entorno
          # Se establece el nombre del servicio del backend
          value: "jm-inn-azure-vote-back-service"
 
# Servicio de kubernetes para exponer el Frontend de forma pública
# Expone un grupo de pods con la misma funcionalidad para servir peticiones. Los pods se ejecutan en cualquiera de los nodos del cluster. El servicio es una abstracción que permite añadir un nivel de desacoplamiento entre las peticiones entrantes del exterior y los pods.
apiVersion: v1
kind: Service
metadata:
  # Nombre del servicio
  name: jm-inn-azure-vote-front-service
spec:
  # Fija tipo de servicio
  # Posteriormente se explicará más en detalle esta asignación
  type: LoadBalancer
  ports:
    # Puerto en el que escucha el servicio
  - port: 80
    # Puerto en el que escuchan los pods expuestos por el servicio
    # TargetPort recibe el mismo valor que port si no se fija de forma explicita
    # - targetPort: 80
 
  selector:
    # Selecciona pods que expone el servicio
    app: jm-inn-azure-vote-front

 

6. Despliegue de la Aplicación en AKS

En el capítulo 4 se vió cómo desplegar el cluster AKS. Ahora vamos a ver cómo desplegar nuestras aplicaciones. Estos son los pasos a seguir para desplegar en el cluster AKS existente:

# Consulta la dirección del registro ACR donde tenemos las imágenes de nuestra aplicación.
# Usa el valor devuelto para modificar el fichero YAML de despliegue en AKS.
# Sustituye nombre del grupo de recursos por el tuyo propio.
$rg = "jm-inn-acr-aks-intro-rg"
az acr list --resource-group $rg --query "[].{acrLoginServer:loginServer}" --output table
 
# Establece nombre del cluster AKS.
# Sustituye nombre por el tuyo propio.
$aksName = "jm-inn-aks"
 
# Configura cliente de kubernetes (kubectl) para conectar al cluster AKS.
az aks get-credentials --resource-group $rg --name $aksName --overwrite-existing
 
# En el directorio donde está el fichero de despliegue YAML ejecuta apply.
# Sustituye nombre del fichero por el tuyo propio
kubectl apply -f aks-deployment-app1.yaml
 
 
# Consulta los pods desplegados en el cluster AKS.
kubectl get pods
 
 
# Consulta la lista de servicios desplegados en el cluster AKS.
kubectl get services
 
  
# Escala las replicas de 2 a 3 en el frontend y consulta la nueva lista de pods.
kubectl scale --replicas=3 deployment/jm-inn-azure-vote-front-deployment
kubectl get pods

  

Utiliza la dirección IP pública externa asignada al servicio de frontend (51.138.83.42) para acceder a la aplicación vía browser. Deberías acceder sin problemas y obtener acceso a la aplicación. También puedes usar curl 51.138.83.42 para verificarlo. Esta es la respuesta Ok obtenida en mi caso:

7. Infraestructura Generada en Azure con el Despliegue de la Aplicación

Llegados a este punto nos podemos preguntar, ¿cómo ha afectado el despliegue de la aplicación a la infraestructura creada previamente en Azure? Veamos:

  • Una nueva dirección IP Pública ha sido creada para dar acceso a nuestra aplicación, en este caso, 51.138.83.42. Esta es la dirección IP con la que hemos verificado el acceso a nuestra aplicación.
  • Una nueva configuración IP de frontend ha sido creada en el load balancer kubernetes referenciando a la dirección IP descrita en el punto anterior.
  • Una nueva regla de balanceo ha sido creada en el load balancer kubernetes para posibilitar el flujo de tráfico desde el frontend anterior (puerto 80) al backend pool kubernetes (puerto 80), donde se encuentran las máquinas virtuales (nodos) y nuestra aplicación desplegada. Esta regla tiene activado el check de Floating IP (Direct Server Return) y este pequeño detalle merece comentarlo:

Al activar este check, para las peticiones entrantes que procesa el load balancer una vez van a ser distribuidas en los nodos, la dirección IP destino no es sustituida por la dirección IP de la máquina virtual asociada a su NIC en la red de Azure (DIP: Destination IP) como sería el comportamiento por defecto:

El tráfico que el load balancer redirige a las máquinas virtuales mantiene la dirección IP pública del frontend y el puerto como destino. La dirección IP destino "flota" o "fluye" desde el frontend hasta el backend y de ahí el nombre:

 

  • Por tanto, a nivel de máquinas virtuales o nodos, cada uno de ellos expone hasta el momento al menos dos interfaces de red, uno asociado a la NIC de la red de Azure a la que pertenece y otro de tipo loopback, a nivel de sistema operativo, asociado a la dirección IP del frontend. Este último interface será utilizada por cada nodo para establecer comunicaciones a nivel interno "consigo mismo", en otras palabras, identificar y redirigir tráfico a servicios y pods asociados a nuestra aplicación. De todo esto se encargan componentes internos de kubernetes desplegados en cada uno de los nodos (kubelet, kube-proxy, etc.).

Kubernetes, por medio de estos componentes, es capaz de asociar una dirección IP virtual (p.e. 10.0.118.108) y un puerto (p.e. 80) al servicio sobre el que se expone nuestro frontend (configurado con type:load-balancer) y redirigir las peticiones entrantes en el frontend del load balancer asociado (peticiones a 51.138.83.42:80) a dicho servicio de kubernetes. Una vez la petición llega al servicio, ésta es balanceada a los diferentes pods (endpoints con dirección IP propia y puerto fijado en atributo TargetPort hospedando una réplica de nuestra aplicación), los cuales procesan y responden a la petición inicial.

  • Asociada a la regla de balanceo anterior se crea una health probe para evaluar el estado de salud de los nodos en el cluster. Se usa un puerto aleatorio dentro de un rango fijo que en mi caso resulta ser el 31987. Este puerto (nodeport) tiene implicaciones ya que permite identificar a nuestro servicio de kubernetes en los diferentes nodos del cluster y comunicarnos con el servicio vía direcciones tipo ip_nodo:nodeport. En este caso, el puerto 31987 está identificando a nuestro servicio de frontend. El load balancer envía peticiones a cada nodo usando la dirección IP del nodo en la subred de Azure y este puerto, el nodo mapea esta petición usando este puerto a nuestro servicio y si obtiene respuesta marca el nodo como "saludable". De lo contrario lo marca como "no saludable" y lo elimina de la lista de nodos a los que es posible balancear el tráfico para nuestra aplicación.
  • El uso del atributo externalTrafficPolicy en los ficheros de despliegue con posibles valores local o cluster, está relacionado con el modo de verificar el estado de salud de los nodos. No obstante cae fuera del alcance de este artículo. De momento únicamente comentar que el valor creado por defecto es cluster y que dicha selección establece que el nodo es "saludable" si el load balancer recibe respuesta independientemente de si el pod que responde está fisicamente en el nodo consultado o en otro diferente dentro del cluster. Si se modifica el valor a local se establece que el nodo solo es saludable si el pod que responde está fisicamente en el nodo consultado, de modo que no hay "saltos" entre nodos para interactuar con el load balancer. Esto tiene implicaciones en el tipo de regla creada en Azure para establecer el estado de salud de los nodos.
  • Respecto al Network Security Group existente, una nueva regla de entrada es creada para permitir tráfico TCP en el puerto 80 con la dirección IP pública de nuestro nuevo frontend en el load balancer 51.138.83.42. Ten en cuenta que, el tráfico exterior llega a los nodos con dirección IP destino igual a la IP pública del frontend utilizado en el load balancer:

  • Cada vez que despleguemos una nueva aplicación en Azure, si ésta está configurada en kubernetes como un servicio con el tipo load balancer, se crearán de forma similar a lo ya explicado los siguientes componentes:
    • Nuevo frontend en el load balancer con nueva dirección IP pública asociada al nuevo servicio.
    • Nueva entrada en el Network Security Group con la nueva dirección IP pública y puerto configurados en el frontend.
    • Nuevas reglas en el firewall de cada nodo para posibilitar las comunicaciones vía nodeport.
    • Nuevas configuraciones a nivel interno (kube-proxy, etc.) del cluster AKS para dar soporte a los nuevos servicios y permitir redireccionar el tráfico a los correspondientes pods.

Respecto a la creación de despliegues, servicios, pods, etc. puedes ver toda la información a través del portal de Azure accediendo al cluster AKS:

- Kubernetes Resources -> Workloads -> Deployments

- Kubernetes Resources -> Workloads -> Pods

- Kubernetes Resources -> Workloads -> Replica Sets

- Kubernetes Resources -> Services and Ingresses -> Services

- Accediendo al servicio jm-inn-azure-front-service podemos ver la información de detalle:

Nuestro servicio expone tres pods asociados a cada uno de los valores del campo Endpoints, recibe peticiones en el puerto 80 (Port) vía TCP (Protocol) y las redirige a los pods en el mismo puerto 80 (Target Port).

A su vez el servicio puede ser accedido de tres formas diferentes:

  • Acceso externo vía dirección IP pública y puerto 80, 51.138.83.42:80.
  • Acceso interno, a nivel nodo del cluster, vía dirección IP privada asociada al servicio (llamada Cluster IP) y puerto 80, 10.0.118.108:80.
  • Acceso mediante nodeport:
    • Desde el exterior en caso de asignar nuevas direcciones IP públicas especificas a cada nodo y el puerto 31987. No tiene mucho sentido en nuestro caso al tener ya disponible la comunicación vía load balancer.
    • Desde dentro de la red donde se encuentra el cluster AKS o desde otra red comunicada vía Network Peering (testeado este caso en mi entorno de Azure funciona perfectamente, ver imagen posterior) o similar mediante las direcciones IP de los nodos en la red y el puerto 31987. Por ejemplo, 10.240.0.4:31987 o 10.240.0.5:31987, donde 10.240.0.410.240.0.5 son las direcciones IP privadas de las máquinas virtuales:

Asociado al servicio de backend tenemos:

El servicio de backend es compartido por todos los frontends y no tiene sentido replicarlo. Tampoco exponerlo de forma externa por lo que no requiere de comentarios adicionales.

8. Versionado y Actualización de la Aplicación en AKS

Sólo nos queda por ver en este artículo cómo crear nuevas versiones de nuestra aplicación y desplegarlas en el cluster AKS. Estos serían los pasos a seguir:

- Modificar nuestra aplicación con los cambios requeridos y ejecutar de nuevo: 

docker-compose up --build -d

- Etiquetar la imagen del frontend con un nuevo valor, por ejemplo v2 (la imagen original fue etiquetada con v1) y referenciar en la variable $acrName el nombre del registro ACR donde subiremos (push) la imagen:

docker tag jm-inn-azure-vote-front-image "$acrName.azurecr.io/jm-inn-azure-vote-front-image:v2"

- Respecto al backend, ya que solo usamos una Redis Cache extraída de Docker Hub, podemos usar exactamente la misma versión.

- Nos autenticamos en Azure si no lo hemos ya:

az login

- Nos autenticamos en el registro ACR:

az acr login --name $acrName

- Subimos la imagen al registro ACR:

docker push "$acrName.azurecr.io/jm-inn-azure-vote-front-image:v2"

- Listamos etiquetas de nuestro repositorio en ACR. Podemos comprobar que realmente existen las etiquetas v1 y v2:
az acr repository show-tags --name $acrName --repository jm-inn-azure-vote-front-image
 
- Aumentamos el número de replicas de la aplicación original mientras hacemos la actualización:
kubectl scale --replicas=5 deployment/jm-inn-azure-vote-front-deployment
 
- Actualizamos el frontend de nuestra aplicación con la nueva imagen creada etiquetada con v2:
kubectl set image deployment jm-inn-azure-vote-front-deployment jm-inn-azure-vote-front-container="$acrName.azurecr.io/jm-inn-azure-vote-front-image:v2"
 
- Listamos pods y verificamos su estado:
kubectl get pods
 
- Listamos replica sets y verificamos su estado:
kubectl get replicasets 
 
Vemos como se generan cinco nuevos pods con la versión v2 (pods incluidos en replica set 77959ccd9b) mientras se destruyen los anteriores procedentes de la versión v1 (pods incluidos en replica set 5cbc8bf9f). El comando no muestra los pods que ya han sido terminados, sólo aquellos que todavía no han concluido dicho proceso.
 
- Por último, reducimos el número de réplicas al valor original antes del despliegue:
kubectl scale --replicas=3 deployment/jm-inn-azure-vote-front-deployment
 
- Podemos comprobar que nuestra nueva versión de la aplicación funciona correctamente vía browser o curl (reemplaza el valor de la IP pública por el obtenido en tu cluster AKS):
curl 51.138.83.42
 
Antes de acabar vamos a utilizar el portal de Azure para verificar desde allí que todo está correcto y familiarizarnos con dicho entorno:
 
- Accedemos a nuestro cluster AKS, en mi caso jm-inn-aks y a continuación seleccionamos kubernetes resources - Workloads:
 
 
- En la lista que aparece podemos comprobar la existencia de nuestros deployments correspondientes al backend y al frontend:
 
 
- Si accedemos a cualquier deployment podemos ver datos generales junto a los pods y replica sets asociados. Por ejemplo, para el frontend:
 
 
- Suponiendo que accedemos al deployment asociado al frontend y pulsamos en cualquiera de los pods que se están ejecutando, obtenemos de nuevo información general junto a detalles de cada pod incluidos los containers (con la imagen) sobre los que se está ejecutando:
 
 
Y esto es todo!! Espero que este artículo te haya sido útil.
 

Referencias

Add comment