Alternativa a Heroku: fly.io

Hace un tiempo escribí sobre Render como alternativa a Heroku. Luego de eso mi colega LucasM me recomendó probar fly.io y así lo hice.

Me gustó. Aún no termino de entender completamente cómo funcionan algunas cuestiones, lo pude hacer andar. No es que me funciona de casualidad, lo hice andar tal como indica la documentación, pero por esa «manía de control», hay algunas cuestiones «internas y/o de bajo nivel» que quisiera entender mejor.

Una condición importante que teníamos al buscar alternativas a Heroku era que la plataforma ofreciera una opción gratuita sin necesidad de poner una tarjeta de crédito. Fly.oi cumple con esto, pero hay una pequeña «trampita»: hay que crear la cuenta de fly.io asociándola a GitHub. Según entiendo esto es porque fly.io busca verificar la identidad del usuario y eso lo hace a partir de la tarjeta de crédito o bien confiando en Github. Así que si no quieren poner una tarjeta de crédito, asegurense de crear su cuenta de fly.io a partir de su cuenta de GitHub (ver imagen adjunta).

La experiencia de usuario que provee fly.io es muy similar a la de Heroku: se crea una aplicación, se la conecta con un repo y listo. No exploré si es posible disparar automáticamente un deploy ante cada commit porque no es nuestro caso de uso. Lo que hacemos es disparamos los deploy explícitamente usando la herramienta de línea de comando de fly.

Hasta donde investigué la plataforma termina corriendo un contenedor docker: si el repositorio de código fuente es de algunos de los frameworks soportados (rails, django, etc), fly genera un Dockerfile automáticamente y buildea la imagen al momento del deploy. También es posible proveer un Dockerfile propio que fly se encargará de builder, lo cual da la posibilidad de ir más allá de los frameworks/lenguajes soportados nativamente. Finalmente también es posible proveer una imagen ya buildeada.

La plataforma también provee servicio storage (basado en PostgreSQL y Redis entre otros) y la posibilidad de usar custom domains incluso en la modalidad gratuita.

A probarlo.

Alternativa a Heroku: Render

A fines de 2022 Heroku cambió su modelo de suscripciones y descontinuó su oferta gratuita que muchos veníamos utilizando. Yo tenia alguna que otra aplicación de juguete pero principalmente venia utilizando Heroku en mis materias para que los alumnos puedan desplegar las aplicaciones que construyen durante la cursada. Si bien es cierto que con estos planes Heroku incluye una oferta para estudiantes la misma no se ajusta a nuestras restricciones pues exige una tarjeta de crédito para poder acceder a la oferta.

Este cambio de Heroku nos obligó a buscar alternativas considerando nuestras restricciones:

  • La plataforma/servicio debe ser gratuito y adicionalmente no debe pedir tarjeta de crédito (hay varias plataformas que a pesar de ofrecer opciones gratuitas piden igualmente una tarjeta de crédito para hacer una validación del usuario)
  • Debe soportar nuestro stack tecnológico, básicamente necesitamos poder correr una aplicación web construida en Ruby y con una base de datos PostgreSQL.

Estas restricciones nos obligaron a descartar algunas opciones interesantes como Vercel (no soporta nuestro stack).

Finalmente hemos decido utilizar Render que cumple con nuestras restricciones y que de acuerdo a la pruebas que hicimos parece que se ajusta bien a nuestras necesidades funcionales.

Mi colega Hérnan hizo un video orientativo para nuestros alumnos mostrando como desplegar en Render una aplicación web Ruby+PostgreSQL.

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.

From Heroku to Rackspace

It is the third time I am involved in the moving an application from Heroku to a cloud server. The time the server is running Ubuntu and it is hosted on Rackspace. It was not my decision, I was contacted once the the decision was already made, but in this particular case I think it is a good idea.

The requirement was simple: move the application to a Cloud Server running Ubuntu 14. The application should continue using the same infrastructure services it was using on Heroku, that is: Puma, PostgreSQL and Memcached.

Just like the previous cases I was involved, the setup of the infrastructure is really easy, you can do almost everything with apt-get command.

The «not-so-easy» part is when you have to replace some of the services provided by Heroku. No matter how simple your application is, for sure you will have to deal with application deployment and database backups.

In the next days I will post detailed articles to explain how to implemented this concerns.

Desafio: de Heroku a Linode

Hace un tiempo comenté que estaba trabajando en un prueba de concepto para migrar una aplicación de Heroku a Linode.  Ahora parece que efectivamente tendremos que mover nuestra aplicación de Heroku a Linode.

Personalmente lo que más me inquieta es el monitoreo de la aplicación, ya que la misma se ejecutará en más de un server. No es que no sepa como implementarlo, sino que hacerlo requerirá un trabajo interesante de setup y tal vez algún cambio en la aplicación.

Continuará….

Sobre el hosteo de aplicaciones en Heroku

Luego de estar trabajando con Heroku por un par de semanas, hoy voy a compartir algunos algunos consejos útiles.

Suele ser una buena práctica al desarrollar una aplicación, manejar distintos ambientes. En general suelen manejarse al menos 4 ambientes, puede que los nombres varíen, pero en líneas generales podríamos decir:

  1. Desarrollo, donde se desarrolla aplicación
  2. Test/integración, ambiente similar de desarrollo donde se ejecutan la pruebas
  3. Staging, ambiente de prueba lo más parecido posible al de producción donde se realizan las pruebas de aceptación (UAT)
  4. Producción, ambiente final donde correr la aplicación

Al trabajar con Heroku tendremos

  1. Desarrollo es la maquina del desarrollador
  2. Test/integración, es el build server
  3. Producción ya dijimos que seria heroku, por lo cual
  4. Staging también debería ser heroku.

Si uno está dispuesto a pagar, heroku nos permite manejar más de un ambiente en la misma aplicación, pero si pretendemos un enfoque gasolero al máximo, entonces tendremos que generar 2 aplicaciones: una representará nuestro ambiente productivo y la otra a nuestro ambiente de staging. Dado que el comportamiento de ciertos componentes puede varias dependiendo de ambiente en que se encuentre, para que nuestra aplicación Heroku de staging se comporte como tal, tendremos que setear la correspondiente variable de entorno utilizando el siguiente comando

heroku config:add RACK_ENV=staging

Esta variable tiene como valor por defecto production y por eso es que no la modificaremos para nuestra aplicación de producción.

Utilizando esta variable podremos definir distintos parametros de configuración para cada uno de nuestros ambientes.

configure :production do
  DataMapper::setup(:default, ENV['DATABASE_URL'])
  DataMapper.auto_upgrade!
end

configure :staging do
  DataMapper::setup(:default, ENV['DATABASE_URL'])
  DataMapper.auto_upgrade!
end

configure :development do
  DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/mydata.db")
  DataMapper::Model.raise_on_save_failure = true
  DataMapper.auto_upgrade!
end

configure :test do
  DataMapper.setup(:default, "sqlite::memory:")
end

Para poder desplegar nuestra aplicación a los correspondientes ambientes, tendremos que agregar los correspondientes repositorios git remotos. En general uno ya lo tendremos seguramente bajo el nombre heroku, pero para evitar confusiones lo mejor seria removerlo y volver a agregarlo con un nombre mas representativo. Para ello podemos hacer

git remote add production <git-de-la-app-heroku-de-production>
git remote add staging <git-de-la-app-heroku-de-staging>

El hecho de que el despligue a Heroku este basado en git, hace muy simple el versionado de la aplicación y la vuelta atras a una versión anterior. Pero más allá de esto hay un plugin que estoy utilizando llamado Releases. Este plugin ofrece cierta funcionalidad básica en su versión gratuita (como agregar un número amigable de versión a cada despliegue y la posibilidad de hacer un rollback del último despliegue).

Continuará…