Diversos temas de networking y almacenamiento requieren una integración estrecha con el entorno en el que estamos implementando nuestro cluster de Kubernetes. En pro de mantener Kubernetes independiente de la plataforma sobre la que corre -ya sea cloud u on-premises-, este implementa un modelo de clases y objetos que puede ser extendido mediante plugins sin cambiar su operativa.

En Azure Container Service (AKS) algunas de estas integraciones ya están habilitadas por defecto y os quería hablar de dos de ellas: StorageClass para almacenamiento persistente y load balancer.

Almacenamiento persistente en AKS

Ya sabemos que los pods se crean y se destruyen dinámicamente por diversas razones, por lo que es muy posible que ciertas aplicaciones que necesitan conservar los datos deban disponer de un espacio de almacenamiento persistente.

Kubernetes para estos casos implementa las StorageClasses donde encontramos diversas maneras de proveer de almacenamiento a nuestros pods. Aquí podemos encontrar desde los más inespecíficos, como por ejemplo montaje de una carpeta compartida por el nodo, hasta los más concertos como el soporte de discos de Azure.

Precisamente en materia de Azure encontramos dos:

  • Azure Disk, donde podemos crear discos no-gestionados (VHD en Storage Account) o gestionados y adjuntarlos a un pod. Hay que tener en cuenta que si bien es espacio de almacenamiento persistente, este no es compartido, por lo que sólo podrá conectarse a él un único pod. Esta característica lo hace muy apto para bases de datos.
  • Azure File, que utiliza justamente Azure Files para proporcionar un acceso compartido SMB a nuestro contenedor.

AKS soporta por defecto soporta Azure Disk... ¡y lo hace realmente bien! Una pequeña consulta de kubectl a las StorageClass disponibles nos muestra lo siguiente:

C:\>kubectl get sc
NAME                PROVISIONER                AGE
default (default)   kubernetes.io/azure-disk   35m
managed-premium     kubernetes.io/azure-disk   35m

¡Wow! No solo podemos hacer un VolumeClaim para un Managed Disk sino que además podemos elegir si queremos que sea Standard o Premium (SSD).

Solicitarlo en nuestro Kubernetes es tan simple como:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  annotations:
    volume.beta.kubernetes.io/storage-class: managed-premium
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Cuando lanzamos este YAML a nuestro master, veremos en un par de escasos minutos tenemos nuestro almacenamiento persistente creado y listo para ser adjuntado al pod que queramos:

C:\>kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                            STORAGECLASS      REASON    AGE
pvc-c3df91ea-2aec-11e8-a3d4-0a58ac1f057f   5Gi        RWO            Delete           Bound     default/pv-claim   managed-premium             37s

Y si nos vamos a nuestro portal de Azure, veremos como un nuevo Managed Disk ha sido creado para dar soporte a tal disco.

Atención especial a la RECLAIM POLICY que al ser delete significa que cuando el recurso deje de utilizarse será eliminado.

Acceso a nuestros Services mediante Load Balancer

Simple y directo: en el momento de escribir estas líneas AKS no soporta NodePort y la solución del proxy to service que comentaba en el artículo anterior no es una gran idea en entornos productivos. Pero nada de qué alarmarse porque tenemos una mejor alternativa: el Azure Load Balancer.

AKS viene perfectamente preparado para soportar la especificación de loadBalancer en nuestra definición de servicio. ¿Cómo lo hacemos? Antes tenemos que decidir entre dos opciones:

  • Crear previamente la Public IP que vamos a asignar a nuestro servicio, de forma que la especifiquemos en el YAML y tengamos certeza de que esta es la que se asigna. Aquí es importante tener en cuenta dos cosas:
    • Debe crearse como static para garantizar que no cambie.
    • Debe crearse en el mismo grupo de recursos que el cluster.
  • Dejar que Kubernetes cree la Public IP en cuyo caso obtendremos una aleatoria.

¿Qué aspecto tiene un Service que usa el Load Balancer de Azure? El siguiente:

apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql-server
spec:
  ports:
    - protocol: TCP
      port: 3306
      name: mysql
  selector:
    app: mysql
  clusterIP: 10.0.0.2 # Default range: 10.0.0.0/16
  loadBalancerIP: 13.95.156.212
  type: LoadBalancer

Lo único que cambia respecto a una implementación estandar son las líneas 15 y 16, donde especificamos la dirección IP (si hemos creado previamente la Public IP) y que el tipo del servicio es Load Balancer. En caso de no haber creado la Public IP, podemos no escribir la línea 15.

Con esto Azure nos crea automáticamente el balanceador de carga y el enrutado hasta nuestro servicio de Kubernetes.

Podemos ver el estado de su aprovisionamiento así:

C:\>kubectl get service
NAME            TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP      10.0.0.1     <none>        443/TCP          57m
mysql           LoadBalancer   10.0.0.2     <pending>     3306:30222/TCP   15m

Happy AKSing!