Cómo funciona la infraestructura definida por el framework

TENDENCIAS ALTO NIVEL, DESARROLLO WEB.
[IMG]Framework 1

La infraestructura definida por el framework (FdI) es una evolución de IaC (Infrastructure as Code), donde el entorno de implementación aprovisiona automáticamente la infraestructura derivada y las aplicaciones escritas. 

De esta manera, un programa de tiempo de compilación analiza el código fuente, comprende la intención detrás y luego genera automáticamente la configuración de IaC necesaria para ejecutar el software. Esto significa DevOps más predecible, de menor costo y riesgo, a través de una arquitectura sin servidor. 

En este artículo, explicaremos cómo la infraestructura definida por el framework encaja en las vistas modernas de la definición y automatización y mostraremos ejemplos de cómo se mejora la experiencia de desarrollo de código abierto.

Contextualización de la infraestructura como código (IaC)

Al inicio de los servidores y del Internet los desarrollos se realizaban en máquinas individuales, ejecutando scripts de instalación o incluso configurando software de pr

oducción a través de interfaces gráficas de usuario para aprovisionar la infraestructura. 

A medida que escalaba la Web, rápidamente quedó claro que este enfoque no escalaría con ella y, junto con el movimiento DevOps, IaC se convirtió en la mejor práctica para aprovisionar infraestructura de manera repetible y confiable.

El código en IaC representa una versión (descripción controlada del estado deseado de la infraestructura) que, cuando se ejecuta, creará el estado del sistema descrito. En este escenar

io, la infraestructura puede referirse a:

  • Equipos y configuraciones de red

  • Servidores web y de aplicaciones

  • Bases de datos y colas de mensajes

¿Qué es la infraestructura definida por el framework?

La infraestructura definida por el framework se abstrae de las primitivas de la nube, como los servidores, colas de mensajes y funciones sin servidor (Serverless functions), lo que las convierte en detalles de implementación con las siguientes ventajas:

  • Proporcionar portabilidad entre diferentes proveedores de infraestructura de destino. 

  • Eliminar la necesidad de configurar manualmente la infraestructura para ejecutar una aplicación en producción. 

  • Aumentar el tiempo dedicado a escribir el código del producto sobre la gestión del sistema.

  • Permitir el uso sin cambios de las herramientas de desarrollo locales nativas del framework. 

  • Estandarizar  los servicios seguros revisados previamente. 

Los frameworks utilizan patrones bien establecidos para proporcionar estructura y abstracción a las aplicaciones, haciéndolas más fáciles de escribir y de comprender. Así, administran el flujo de una aplicación de alto nivel, mientras el desarrollador escribe el código dentro de los  ganchos proporcionados. 

La infraestructura definida por el framework aprovecha tanto esta inversión de control como la estructura predecible de las aplicaciones para mapear automáticamente los conceptos del framework en la infraestructura adecuada sin necesidad de una configuración explícita. 

Este artículo proporciona ejemplos basados en la oferta de plataforma como servicio de Vercel. Sin embargo, el concepto se puede aplicar más ampliamente, ya que la idea básica de comprender un framework y generar la configuración de IaC también se puede usar para implementaciones de infraestructura más tradicionales.

Aplicación de la infraestructura definida por el framework

Estos son ejemplos de cómo los frameworks asignan automáticamente sus conceptos a la infraestructura de Vercel. Aunque aquí usaremos Next.js para la demostración, la implementación de Vercel admite una multitud de frameworks basados en el mismo mecanismo subyacente.

[img]Framework 2

* Diagrama de flujo que muestra el proceso desde el código de usuario hasta la infraestructura inferida automáticamente.

Next.js utiliza un enrutador basado en archivos que los asigna en una estructura de directorio a direcciones URL en una aplicación web. Por ejemplo, el archivo pages/blog/index.ts crea una ruta URL que asigna la URL /blog al código definido en ese archivo.

La infraestructura definida por el framework comienza elevando esta comprensión de la tabla de rutas de una aplicación web desde un detalle de implementación del framework hasta algo que la infraestructura entiende. 

En el caso de Vercel, la tabla de rutas generada a partir de un framework eventualmente se implementaría en el servicio de puerta de enlace, que luego sabe cómo invocar la infraestructura correcta para cualquier ruta determinada.

El contenido de pages/blog/index.tsx podría verse así:

export default function BlogPosts({ posts }) {   return posts.map(post => <BlogPost key={post.id} post={post} />) } export async function getServerSideProps() {   const posts = await getBlogPosts();   return {     props: { posts }   } }

*Ejemplo de una página renderizada dinámicamente en Next.js.

En este ejemplo el código define una función getServerSideProps que obtiene las publicaciones de blog en el sitio. Next.js invoca esta función y pasa el resultado a la función de exportación predeterminada de BlogPosts que genera una lista de publicaciones.

Las páginas de Next.js con una función getServerSideProps se representan dinámicamente en cada vista de página. Eso significa que una configuración de producción necesita un servicio informático (como un servidor de aplicaciones o una función sin servidor) para realizar esta operación de obtención y representación de datos.

Con la infraestructura definida por el framework las páginas con getServerSideProps requieren un recurso informático para realizar la operación de representación que se utiliza,  infieren automáticamente y aprovisionan la infraestructura informática para realizar la operación de representación. 

En el caso de Vercel, esto significa que se crea e implementa una función sin servidor basada en AWS Lambda con el código necesario para renderizar la página. El conocimiento de cómo invocar esta función se implementa luego en el servicio de puerta de enlace como parte de la tabla de enrutamiento de la aplicación.

Ahora, modifiquemos ligeramente el ejemplo de código de arriba, para cambiar

getServerSideProps a getStaticProps: export default function BlogPosts({ posts }) {   return posts.map(post => <BlogPost key={post.id} post={post} />) } export async function getStaticProps() {   const posts = await getBlogPosts();   return {     props: {posts}   } }

*El cambio de getServerSideProps a getStaticProps ahora genera el HTML en el momento de la compilación.

En Next.js, getStaticProps implica que, en lugar de representar la página en cada vista, la función se puede invocar en el momento de la compilación para generar una página HTML estática que luego se puede entregar al usuario. 

Nuevamente, con la infraestructura definida por el framework, se puede inferir que no se necesita más infraestructura informática de producción para servir esta página web en particular. En cambio, los artefactos generados en el momento de la compilación se pueden implementar en una infraestructura de servicio web estática y de menor costo. 

En el caso de Vercel esto significa que no se implementa ninguna función sin servidor para esta página y, en cambio, la tabla de enrutamiento de la aplicación se actualiza para apuntar al servicio de archivos estáticos respectivo.

Si bien este es solo un ejemplo de cómo los cambios en el código dentro de un archivo determinado pueden desencadenar la implementación de varias piezas de infraestructura, el concepto se puede expandir a una multitud de recursos de infraestructura. 

Estos son algunos ejemplos: 

  • Gatsby tiene un concepto llamado generación estática diferida. Cuando se usa se implementa una función sin servidor para realizar la generación diferida a pedido del usuario, similar a la representación del lado del servidor. Sin embargo, la salida de la función luego se almacena en AWS S3 y se empuja globalmente para que se pueda servir desde el borde de Vercel sin otra invocación de función.

  • Svelte Kit tiene el concepto de acciones de forma. Cuando se usa se crea automáticamente una función sin servidor para realizar la acción. Lo mismo sucede cuando se utiliza Remix.

  • Next.js admite el concepto de middleware que activa el aprovisionamiento automático de recursos informáticos de borde que ejecutan el código durante la fase de procesamiento de la solicitud.

  • El uso del componente para la optimización de imágenes activa automáticamente la configuración de este sistema de alto rendimiento que adapta la imagen al dispositivo del usuario visitante.

Internamente, las primitivas del framework se compilan en la API de salida de compilación de Vercel, que es una API de configuración de IaC declarativa más tradicional que consume la plataforma para aprovisionar la infraestructura de producción.

Serverless en un mundo IaC

La IaC utiliza archivos legibles que los desarrolladores pueden versionar de manera similar al software, para aprovisionar infraestructura como servidores físicos, máquinas virtuales y servicios de nivel superior como bases de datos o aplicaciones. La arquitectura sin servidor, que a pesar de su nombre, aún utiliza servidores, elimina la necesidad de que los desarrolladores administren servidores físicos o virtuales específicos.

Los productos sin servidor aún requieren que los desarrolladores definan e implementen sus primitivas serverless respectivas, de manera similar a la infraestructura más tradicional. Por ejemplo, en el arquetipo de productos sin servidor, AWS Lambda, los desarrolladores deben crear una función lambda e implementar el código en ella.

En otras palabras, el proceso para crear una función lambda, aunque un poco menos involucrado, es similar al proceso para crear un nuevo servicio con servidor. 

Aquí hay un ejemplo de cómo crear una función lambda usando Terraform de HashiCorp, una de las herramientas de configuración de IaC más populares. Como se puede ver, la función lambda es solo otro recurso:

resource "aws_lambda_function" "my_lambda" {   filename      = "lambda_function_payload.zip"   function_name = "lambda_function_name"   role          = aws_iam_role.iam_for_lambda.arn   handler       = "index.test"   source_code_hash = filebase64sha256("lambda_function_payload.zip")   runtime = "nodejs16.x"   environment {     variables = {       foo = "bar"     }   } }

*Creación de una función Lambda utilizando HashiCorp Terraform

Resolviendo el problema de desarrollo local para serverless

Si bien la arquitectura sin servidor simplifica enormemente la gestión de la infraestructura de producción, los sistemas que ejecutan código sin servidor a menudo son complejos, lo que puede causar problemas con el desarrollo local. 

En el peor de los casos, el desarrollo local no es posible y los desarrolladores deben probar los cambios locales haciendo implementaciones comparativamente lentas en la infraestructura de producción. 

En el mejor de los casos, los desarrolladores deben crear una simulación local del complejo stack sin servidor, que luego debe mantenerse actualizada con el entorno de producción.

[IMG]Framework img2

*Comparación del ambiente de desarrollo local con y sin infraestructura definida por el framework. 

La infraestructura definida por el framework elimina por completo este problema, ya que permite que el mismo dicte el comportamiento de producción. El desarrollo local solo puede usar las herramientas propias del framework, mientras que la infraestructura de producción se configura automáticamente para hacer una representación escalada y optimizada del mismo comportamiento subyacente.

Esto significa que, al usar la infraestructura definida por el framework, los desarrolladores pueden confiar en que la aplicación funcionará de la misma manera tanto en el entorno de desarrollo local como en el de producción. 

Además, esto también puede reducir la cantidad de errores que se producen durante el proceso de implementación, lo que puede llevar a una aplicación más confiable y estable en producción. En resumen, la infraestructura definida por el framework puede hacer que el proceso de desarrollo sea más eficiente, rápido y confiable.

La infraestructura definida por el framework y las implementaciones inmutables

En la actualidad el código de la aplicación se desarrolla casi exclusivamente dentro de sistemas de control de versiones como Git. La infraestructura definida por código mantiene la definición en el mismo sistema de control de versiones o en un sistema de control de versiones hermano. 

Sin embargo, a menudo, la infraestructura de producción en sí misma solo puede representar puntos limitados en el tiempo de la historia de versiones de la infraestructura. Esto es fundamentalmente incompatible con la infraestructura definida por el framework, que espera que la infraestructura de producción se mapee directamente al código en el mismo hash de confirmación.

Las implementaciones inmutables resuelven esta incompatibilidad entre la historia de versiones de la aplicación y la infraestructura. En lugar de implementar en un número limitado de infraestructuras como "producción" y "preproducción", las implementaciones inmutables crean una completamente nueva para cada implementación que se realiza, de manera que es inmutable.

[IMG]Framework 3

*Cada commit obtiene una implementación inmutable y genera una infraestructura virtual.

Naturalmente, las implementaciones inmutables son imposibles en un mundo en el que la infraestructura se asigna a recursos físicos finitos, que se consumirían a medida que se realizan nuevas implementaciones. 

Sin embargo, en un mundo serverless, donde la infraestructura no utilizada puede escalar a cero, las implementaciones inmutables se vuelven posibles, ya que las implementaciones no utilizadas no ocupan recursos informáticos físicos más allá del almacenamiento básico necesario para sus contenidos. 

Por ejemplo, la plataforma de Vercel crea una implementación inmutable para cada hash de git que se envía a un repositorio, que luego se asigna a una infraestructura completamente nueva y serverless.

Reconocimientos 

La idea de las infraestructuras definidas por frameworks se apoya en los hombros de gigantes. Se basa en la IaC como la interfaz de infraestructura definitiva y, por lo tanto, no podría funcionar sin el  trabajo de su comunidad. 

Además, se basa en abstracciones de infraestructura como Kubernetes para que sea factible dada la cantidad relativamente baja de detalles que se pueden extraer del código fuente original, y el enfoque es particularmente adecuado para apuntar a ofertas de PaaS como la plataforma original de Google AppEngine.

Frameworks, no primitivas 

Aquí hemos discutido cómo la infraestructura definida por el framework se basa en IaC al comprender cómo los patrones de un framework se mapean a primitivas de infraestructura necesarias para ejecutar código en un sistema de producción escalable, lo que simplifica enormemente el desarrollo local.

Los despliegues inmutables basados en la arquitectura sin servidor permiten que la infraestructura de producción se mapee perfectamente a la versión del código que se ejecuta, al mismo tiempo que es excepcionalmente escalable y rentable. 

Vercel implementa infraestructura definida por el framework para DevOps más predecible, de menor costo y menor riesgo a través de una arquitectura sin servidor. 

Contáctenos 

Si su organización tiene interés en implementar proyectos de desarrollo de aplicaciones de la mano de expertos, lo invitamos a contactarnos. 

*Artículo basado en: https://vercel.com/blog/framework-defined-infrastructure 

También te puede interesar:También te puede interesar: