Taller: Tddeando microservicios a kubenertes

Ayer completé el dictado de la primera edición de mi taller «TDD your Microservice from Git to Kubernetes«. El título está en inglés porque efectivamente fue en inglés. Asimismo, si bien en el título dice TDD, el taller es mucho más amplio. Incluye también varias prácticas relacionadas como Configuration Management, Continuous Integration, Design Patterns, Architecture guidance, etc.

Hace un tiempo decidí no dictar más cursos de TDD porque la experiencia me demostró que luego del curso, el salto que debían hacer los participantes entre la «simpleza didáctica» de los ejercicios del curso y su código de trabajo cotidiano era muy difícil de realizar. Luego de analizar el origen de esas dificultades decidí armar este curso que apunta precisamente a trabajar con ejercicios más «de mundo real», lo cual implica lidiar con un proceso de desarrollo en equipo, versionado, integración con otros sistemas e infraestructura, entre otras cuestiones.

Obviamente cubrir todas estas cuestiones en un solo taller resulta muy desafiante, es por ello que el taller está estructurado en varios encuentros. Al mismo tiempo es un taller «avanzado», en el sentido de que requiere que los participantes tengan:

  • experiencia en desarrollo de software en un contexto de industria
  • conocimiento de TDD (al menos conceptualmente)
  • práctica en la automatización de pruebas (al menos de tipo unitario)

Al mismo tiempo, para achicar más el salto entre el taller y los proyectos diarios de los participantes, este taller está basado en tecnologías concretas incorporando también patrones de uso común en dichas tecnologías. Esta versión en particular la hice utilizando C# (netCore),NUnit, Moq, Gitlab y Kubernetes.

En los próximos meses estaré haciendo una edición en castellano. Los interesandos pueden contactarme aquí.

De Gitlab a Azure Kubernetes Service

IMPORTANTE: escribo este post principalmente como una nota personal para futura referencia. El procedimiento que describo aquí es el que seguimos para hacer el setup de la infraestructura que utilizamos para el trabajo final de memo2@fiuba. En este contexto de cara a no tener dependencia fuerte con ningún proveedor hemos decidido armar nuestra infraestructura sin hacer uso de ninguna característica particular de las herramientas de ningún vendor. Es por eso que este procedimiento podría utilizarse con mínimos cambios para conectar con cualquier otro proveedor de Kubernetes y al mismo tiempo también podrían utilizarse con otra herramienta de CI/CD que no sea GitLab. En este caso estamos utilizando las suscripciones educativas tanto de Azure como de GitLab.

Creación de cluster

Al crear el cluster simplemente elegimos el tamaño de nodo, en nuestro caso B2S y especificamos 2 nodos. Adicionalmente debemos especificar un grupo para los recursos que se crearán como parte del cluster, en nuestro caso pusimos «memo2» y obviamente necesitamos un nombre para cluster, en nuestro caso «cluster-memo2-prod». Finalmente desactivamos la funcionalidad de monitoreo porque está fuera del scope de nuestra suscripción. Esto representa un costo mensual aproximado de ~ us$ 73, lo cual está bien ya que la suscripción nos ofrece 100 dólares de crédito y nosotros solo necesitamos el cluster 1 mes.

Una vez creado el cluster, el siguiente paso es descargar la configuración de conexión para kubectl (el cliente kubernetes). Para esto es necesario en primera instancia utilizar el azure-cli. La opción obvia es instalar el azure-cli, pero también está la opción de usar un «cloud shell» de azure que nos abre un shell en la ventana del navegador y que tiene el azure-cli instalado. Una vez que tenemos el azure-cli a mano (ya sea instalado en nuestra máquina o usando el cloud shell) debemos ejecutar los siguientes dos comandos:

az account set --subscription <subscription id>
az aks get-credentials --resource-group <resource group> --name <cluster name>

El segundo comando «instala» la configuración para conectarnos al cluster, lo cual significa que tenemos un archivo en ~/.kube/config con todos los parametros de configuración de conexión. Ejecutando «kubectl version» deberíamos ver la versión de nuestro kubectl y la versión de kubernetes que corre el cluster.

Con esto ya estamos en condiciones de conectar nuestro GitLab con el cluster creado.

Conexión Gitlab > Kubernetes

El primer paso, es crear una cuenta de servicio para que gitlab se conecte al cluster. Esto lo hacemos con este manifiesto.

Una vez creada la cuenta de servicio necesitamos obtener su token para lo cual ejecutamos los siguientes comandos:

# primero creamos la cuenta de servicio
kubectl apply -f gitlab-service-account.yaml

# luego buscamos entre los secrets el correspondiente a la cuenta creada
kubectl get secrets

# finalmente hacemos un describe del secret para poder obtener su token
kubectl describe secret <nombre del secret>

Ya con todo esto podemos proceder la configuración del cluster en GitLab

En el formulario de configuración del cluster completamos los campos de la siguiente forma:

  • Kubernetes cluster name: el nombre con el cual queremos identificar el cluster, en mi caso «cluster-memo-prod»
  • Environment scope: el ambiente que este cluster representará, en mi caso será «prod». Este ambiente luego será referenciado dentro del pipeline de CI/CD
  • API URL: la sacamos de la configuración de kubectl, es el campus server. Lo podemos obtener haciendo «cat ~/.kube/config | grep server«
  • CA Certificate: también lo obtenemos de la configuración de kubectl haciendo «cat ~/.kube/config | grep certificate-authority-data«. Pero, adicionalmente hay que desencodearlo, entonces podemos poner el valor en una variable y ejecutar: «echo $CERT | base64 -d«
  • Service token: aquí utilizamos el token de la cuenta de servicio que creamos previamente
  • RBAC-enabled cluster, GitLab-managed cluster, Namespace per environment: en el caso de MeMo2 no hacemos uso de ninguna de estas funcionalidades con los cual dejamos las 3 opciones como unchecked
  • Project namespace prefix (optional, unique): esto tampoco lo utilizamos con lo cual no dejamos en blanco

Kubernetes: logs y sidecar containers

Al trabajar con Kubernetes es posible acceder a los logs de nuestras aplicaciones/contenedores utilizando la herramienta kubectl. Para la etapa de desarrollo (por ejemplo cuando estamos trabajando con Minikube) esto puede estar bien, pero para un ambiente de test/producción esta solución se queda corta por múltiples motivos. Principalmente no resulta seguro ni cómodo andar conectandose con kubectl a un cluster productivo. Una solución bastante habitual para esta problemática es utilizar alguna solución de agregación de logs. Estas soluciones consisten básicamente en concentrar todos los mensajes de log en un almacenamiento centralizado y explotarlo con alguna de visualización. Para concentrar los mensajes de logs se suele hacer lo siguiente: junto con el contenedor de nuestra aplicación desplegamos desplegamos en el mismo pod un contenedor sidecar. Este contenedor sidecar colecta los mensaje de logs generados por nuestra aplicación y los envía un concentrador. El siguiente gráfico muestra un esquema de esta solución

Existen varias herramientas para implementar esta estrategia. En el contexto de la arquitectura de referencia que estamos armando para el trabajo práctico final de MeMo2@fiuba vamos a utilizar la propuesta de Sumologic. Para esto utilizamos un container de Sumologic, desplegado como sidecar, que recolecta los logs de nuestra aplicación y los envía a Sumologic que almacena los mensajes, los procesa y los pone disponibles via una interface web.

El siguiente fragmento de código muestra un posible descriptor de deployment para implementar esta solución.

De acuerdo a esta configuración, tenemos los dos contenedores compartiendo un volumen (logs-data). El bot (la aplicación en cuestión) escribe los mensajes de log en ese volumen de donde son leídos por el colector de Sumologic. Adicionalmente el colector de Sumologic tiene un segundo volumen (config-data) de donde lee su configuración. Al mismo tiempo ambos contenedores reciben como variables de ambiente algunos secrets (el telegram token, la key de sumologic, etc) y demás parámetros de configuración (el log level por ejemplo).

Nota 1: el uso de sidecar containers es un patrón muy popular que se utiliza para algunas otras cuestiones más allá de la recolección de logs.
Nota 2: por cuestiones de foco hay fragmentos de código del deployment que fueron removidos para dejar solamente el código relevante para este artículo

Infra definida para el TP2 de MeMo2 @ fiuba

Después de varias averiguaciones y algunas pruebas de concepto ya tenemos bastante encaminado el diseño del pipeline e infraestructura del TP2. El sistema a construir consta de dos aplicaciones/artefactos: un bot de telegram y una web-api.

El bot de telegram lo vamos a correr en kubernetes, más precisamente en el servicio de Kubernetes de Azure utilizando la opción Azure for Students ofrecida por Microsoft, la cual incluye 100 dólares de crédito y no requiere de tarjeta de crédito.

Las web-api la vamos a correr en Heroku pero en lugar de usar el modelo de runtime tradicional de Heroku, vamos a correr la aplicación en un contenedor. Esto es: en lugar de hacer push del código fuente directo a Heroku, lo que hacemos es construir una imagen Docker y luego indicar a Heroku que corra un contenedor basado en esa imagen.

Si bien, en términos de infraestructura a bajo nivel, el bot y la api van a correr en distintos runtimes, a nivel proceso ambas aplicaciones correran como un contenedor Docker. Al mismo tiempo el proceso de build y deploy va a ser el mismo para ambas aplicaciones, ofreciendo al equipo de desarrollo una experiencia de trabajo uniforme. En un escenario real es poco probable utilizar una estrategia de este estilo, porque tener dos plataformas de runtime implica un mayor costo operacional pero en nuestro contexto creemos que puede resultar interesante para mostrar explícitamente a los estudiantes como, a partir de ciertas técnicas, es posible lograr un buen nivel abstracción de la infraestructura.

El pipeline de CI/CD lo implementaremos con GitLab utilizando la suscripción Gold que GitLab ofrece para contextos educativos.

Un detalle que me parece relevante mencionar es que, si bien vamos a utilizar productos/servicios de determinados vendors, tenemos la intención de mantener la menor dependencia posible con caraterísticas específicas/propietarias de cada vendor.

En siguientes artículos explicaré como será el modelo de ambientes y pipelines que armaremos tomando esta infraestructura de base.

Preparando la infra para el TP de MeMo2 @fiuba

A partir de la pandemia el segundo cuatrimestre de 2020 en FIUBA quedó partido: 12 semanas en 2020 y 4 semanas en 2021 con un receso entre 21 de diciembre y 8 de febrero. Este receso nos dio la posibilidad de intentar innovar en ciertos aspectos del trabajo práctico final de la materia. El objetivo de este trabajo es poner en práctica de forma integral todo lo visto en la materia con un importante foco en cuestiones de proceso. En este sentido hay una parte del proceso (principalmente relacionada a configuration management) que históricamente hemos dejado un poco marginada principalmente por restricciones de infraestructura.

Típicamente el trabajo final consiste en el desarrollo y despliegue de una aplicación que comprende una API Rest y un bot de Telegram. Todo esto trabajando en una dinámica de Extreme Programming lo cual implica: BDD, TDD, Integración continua, despliegue continuo, automatización de pruebas, trabajando muy de cerca con el usuario, armando criterios de aceptación, etc, etc.

Hasta el momento venimos trabajando con Ruby + PostgreSQL, desplegando a cuentas gratuitas de Heroku y utilizando GitLab como plataforma de desarrollo (gestión de backlog, repositorio, CI/CD, etc). Debo agradecir aquí a Jetbrains (que provee gratuitamente sus herramientas a nuestros alumnos) y a GitLab (que no dio una licencia gold de su plataforma).

El servicio de Heroku está muy bien, pero su modelo de plataforma como servicio nos abstrae de ciertas cuestiones que nos gustaría que los alumnos vieran más de cerca, principalmente en lo que tiene que ver con manejo de la infraestructura de como código. En este sentido, estamos considerando ir hacía Kubernetes, eso implicaría mínimamente escribir los descriptores de pods, deployments, configmaps, etc, etc. No le vamos a pedir a los alumnos que hagan todo esto por su cuenta (pues implicaría que se ponga a aprender kubernetes lo cual excede por mucho el alcance de la materia), sino que lo haremos en forma conjunta (equipo docente y alumnos). Ahora bien, para dimensionar los recursos tenemos que considerar los siguientes puntos:

  • Son 7 grupos
  • Cada grupo necesita al menos 2 ambientes (test y prod)
  • Cada ambiente requiere al menos un pod para la api, un pod para bot y una base de datos (en principio de tipo relacional)
  • Nos gustaría contar también con alguna solución de logging centralizado tipo ELK pero no es algo imprescindible

Toda la infra de deployment ya la tenemos resuelta con GitLab.

La intención inicial es usar algún servicio cloud que nos provea Kubernetes y base de datos «as a Service». La idea es no tener que pagar por esto, ya que al ser una universidad pública no podemos pretender que los alumnos pagen por esto y mucho menos vamos a pedirle a la universidad pagar por esto. Obviamente que una opción es que lo paguemos los docentes (opción que no descarto) pero me parece que puede ser una buena oportunidad algún cloud provider de colaborar con la formación de potenciales futuros empleados/clientes y de paso hacer un poco de marketing.

En próximos post iré compartiendo a medida que vayamos avanzando en el armado de todo esto.

¡LLegamos a producción!

Hace unos días comenté que teníamos el desafió de llegar a producción en 8 días con una aplicación construida desde cero.

Ayer cumplimos el objetivo.

En el camino nos encontramos con varios imprevistos relacionados principalmente con las aplicaciones existentes con las que teníamos que interactuar. Cuestiones principalmente de networking, seguridad y accesos. Todas cuestiones que intentaremos ir puliendo en las próximas iteraciones.

El siguiente gráfico resume la arquitectura productiva de nuestra aplicación:

Nuestra aplicación consiste en un frontend construido con Angular (servido por Nginx) y un backend construido con Net Core (aspnet/kestrel) que consume servicios WFC/SOAP que proveen acceso al core de la organización. Tanto front como back son empaquedados en imágenes docker que luego corren en Kubernetes. Dentro de Kubernetes tenemos pods de front y pods de back que en ambos casos corren en un esquema de sidecars con filebeat. Esto es: cada pod corre dos contenedores, uno con nuestra aplicación (front o back) y uno con filebeat que se encarga de leer los logs escritos por nuestra aplicación y mandarlos a Elastic/Kibana para tener así un acceso centralizado al log. Por otro lado, por fuera del cluster Kubernetes hay un conjunto de dispositivos de red (routes, balancers, firewalls, etc) y servidores de distintos tipo donde corren los servicios con los que interactua nuestra aplicación.

En próximos post compartiré algunos detalles de nuestra forma de trabajo y nuestro pipeline de delivery.

Taller Online de Docker & Kubernetes: segunda edición completa

La semana pasada completamos la segunda edición de este taller. A diferencia de la primera edición, el flujo de los encuentros fue un poco más «trabado», pues hubo mucha charla. O sea, hubo un par de participantes muy entusiastas con muchas inquietudes que generaron preguntas, idas y vueltas. Esto esto estuvo muy bueno en cierto sentido pero al mismo tiempo generó que algunas de las explicaciones tuvieran menos profundidad o que incluso no llegaramos a hacer algún ejercicio. Al mismo tiempo hubo otros participantes que apenas hablaron. No se si una dinámica así (de mucha idea y vuelta) es mejor o no, pero definitivamente es algo a repensar y moderar para una siguiente edición.

Más allá de este detalle, el resultado del taller fue muy positivo. Estoy completamente convencido de este formato de curso y seguramente lo estaré utilizando en futuros cursos sobre nuevas temáticas.

Nueva edición del Taller online de Docker & Kubernetes

Nueva edición del Taller online de Docker & Kubernetes

En la última semana estuve trabajando en preparar una nueva edición del taller. El temario será el mismo pero estuve ajustando algunos de los ejercicios y los materiales de estudio:

  • Introducción a Docker
  • Consideraciones para la elección de imágenes base
  • Recomendaciones para la creación de imágenes
  • El ecosistema de herramientas Docker
  • Tecnologías de contenedores más allá de Docker
  • Introducción a Kubernetes
  • Recomendaciones para el diseño de aplicaciones Kubernetes
  • Manejo de configuración con Secrets y ConfigMaps
  • El ecosistema de herramientas Kubernetes
  • Deploy y monitoreo
  • Distribución de aplicaciones Kubernetes con Helm

El taller será los días miércoles a las 20 hs. (hora Argentina, UTC-3). Serán 5 encuentros cada uno de ~90 minutos. La fecha de inicio será el miércoles 20 de marzo. Los interesados pueden preinscribirse aquí (si ya se habían preinscripto para la edición no hace falta que vuelvan a hacerlo, pues ya tengo sus datos y lo contactaré en forma privada).

Taller Online de Docker & Kubernetes: resultado de la primera edición

La semana pasada completé la primera edición de este taller. Participaron 8 personas, porque si bien hubo alrededor de 30 interesados, decidí limitar la cantidad de participantes pues no estaba seguro de como funcionaría la herramienta de conferencia. Por suerte funcionó bien.

El taller consistió en 4 sesiones online de entre 1 y 2 horas cada una. Estimar la duración de la sesiones es lo que más me costó, en parte por ser un contenido nuevo y en parte por ser una dinámica nueva.

La evaluación de los participantes fue muy positiva:

  • Evaluación general del taller: muy bueno 50% , excelente 50%
  • Evaluación de los encuentros online: muy bueno 66%, excelente 30%
  • ¿Recomendarías este taller a un colega? Definitivamente si 100%

Por otro lado las respuestas de feedback libre fueron también muy positivas. A partir de estos resultados y dado el interés que hay en la temática, en breve estaré anunciado la fecha de la próxima edición. Los interesados pueden pre-registrarse aquí y los contactaré cuando tenga los detalles de la nueva siguiente edición.

Les comparto una foto de mi «estudio de transmisión». Al centro mi computadora primaria con una segunda pantalla conectada a la izquierda. La pantalla de la computadora la utilizo para pasar las diapositivas y mostrar las herramienta mientras que la pantalla extendida la utilizo para la conferencia y el chat con los participantes. Del lado derecho, mi computadora secundaria como plan B en caso de que por algún motivo mi computadora primaria deje de funcionar. Junto al teclado mi cuaderno de anotaciones. Finalmente en el banquito de madera, un infaltable: el mate.