Skip to content

Commit

Permalink
Merge pull request #398 from open-source-uc/production-files
Browse files Browse the repository at this point in the history
Production files
  • Loading branch information
fagiannoni authored Dec 26, 2023
2 parents 232d550 + 68fd537 commit e427241
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
49 changes: 49 additions & 0 deletions infra/productive-deploy/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Configuración de la máquina para producción

Estas instrucciones están pensadas para configurar por primera vez la máquina productiva. Solo debería ser necesario seguir estas instrucciones para configurar una máquina nueva.

## Instrucciones iniciales

### General

1. Actualizar paquetes de la máquina (`dnf update`).
2. Instalar git.
3. Clonar el **repositorio de producción** del proyecto nuevo planner (`git clone`).
4. Generar los archivos `.env` en las carpetas backend, frontend y database a partir de los templates.
5. Agregar a la máquina el archivo `update.sh`, dar permisos de ejecución con el comando `chmod` y crear _cronjob_ que lo ejecute recurrentemente.

### Detalles

1. Actualizar paquetes de la máquina. Para el caso de Rocky Linux se puede usar `sudo dnf check-update` y `sudo dnf update`.
2. Instalar git. En la siguiente sección [Informacion de los archivos](informacion-de-los-archivos) se muestra como _ansible_ instalará el resto de dependencias necesarias, tales como Docker.
3. Clonar el **repositorio de producción** del proyecto nuevo planner usando `git clone`. Este repositorio se encontrará en Github controlado exclusivamente por la **Subdirección de Desarrollo** (más detalles en la sección [Flujo 2: Actualizaciones recurrentes](flujo-2:-actualizaciones-recurrentes)). El comando debería quedar como: `git clone https://github.com/<nombre organizacion>/planner`.
4. Para generar los archivos `.env` en las carpetas backend, frontend y database a partir de los templates, se deben copiar los archivos `.env.production.template` en todos los servicios y rellenar a mano para generar los archivos `.env`.
En particular,
- Generar `backend/.env` a partir de `backend/.env.production.template`.
- Generar `frontend/.env` a partir de `frontend/.env.production.template`.
- Generar `database/.env` a partir de `database/.env.production.template`.
5. Para permitir las actualizaciones recurrentes del proyecto, es necesario agregar a la maquina el archivo `update.sh`, luego darle permisos de ejecución con el comando `chmod +x update.sh`, y luego crear el _cronjob_ que lo ejecute recurrentemente con el comando `crontab -e`. Se recomienda una frecuencia no tan baja, para que las actualizaciones ocurran de forma más inmediata.

Es importante mencionar que la ejecución de este archivo no será demandante computacionalmente, ya que solamente tomará acciones si es que hubo algún cambio en el **repositorio de producción**. O sea, si el archivo se ejecuta cada 3 horas, pero el código del proyecto no cambia en 5 días, cada una de las ejecuciones del archivo no tendrá impacto debido a que el código no tuvo cambios.

## Información de los archivos

- `install.md`: este archivo entrega las instrucciones necesarias para configurar por primera vez la máquina que será utilizada para correr el proyecto nuevo planner.
- `update.sh`: este archivo será ejecutado automáticamente, con un _cronjob_, para actualizar el código y desplegar los nuevos cambios. En particular, ejecuta el comando `git pull` para obtener los últimos cambios del repositorio de producción del proyecto nuevo planner, y luego corre el archivo `run_deploy.sh` solamente si git registró algún cambio nuevo en el repositorio.
- `run_deploy.sh`: finalmente, este archivo es ejecutado automáticamente por `update.sh` y lo que hace es levantar la última versión del proyecto. En particular, instala _ansible_ si no está instalado, y luego corre el playbook de _ansible_. En este caso, _ansible_ actúa como una interfaz para generar la instancia de deploy. Actualmente usamos _ansible_, pero en el futuro se puede ver la posibilidad de usar otro servicio.

## Flujos de despliegue a producción explicados en detalle

### Flujo 1: Despliegue inicial

1. El **Equipo de Plataformas** levanta una nueva máquina vacía para producción.
2. El **Equipo de Desarrollo del Nuevo Planner** le entrega los archivos `install.md` y `update.sh` a la **Subdirección de Desarrollo**. Estos archivos también se encontrarán en el repositorio del proyecto, bajo la ubicación `infra/productive-deploy`.
3. La **Subdirección de Desarrollo** accede a la máquina y sigue las instrucciones del archivo `install.md`.

### Flujo 2: Actualizaciones recurrentes

1. El **Equipo de Desarrollo** del Nuevo Planner y la comunidad UC generan solicitudes de cambios al código (_Pull Requests_) en el **repositorio de desarrollo** del proyecto Nuevo Planner. Este repositorio es público y se ubica en Github bajo la organización Open Source UC ([github.com/open-source-uc/planner](https://github.com/open-source-uc/planner/tree/main)).
2. El **Equipo de Desarrollo** del Nuevo Planner acepta una solicitud de cambio al código y agrega estos cambios a la rama principal (_Main_) del **repositorio de desarrollo**.
3. Luego, el **Equipo de Desarrollo** del Nuevo Planner genera una solicitud para agregar los cambios a la rama principal (_Main_) del **repositorio de producción**, desde la rama principal del **repositorio de desarrollo**. El **repositorio de producción** también es público en Github, pero se ubica bajo el control exclusivo de la **Subdirección de Desarrollo**. O sea, solamente la **Subdirección de Desarrollo** puede aprobar y realizar cambios al código del proyecto.
4. La **Subdirección de Desarrollo** revisa la solicitud, y puede aceptarla o solicitar cambios. Si solicita cambios, el **Equipo de Desarrollo** del Nuevo Planner deberá arreglar lo solicitado y volver a generar una solicitud para agregar los cambios.
5. Si la solicitud fue aceptada, los nuevos cambios de la rama principal del **repositorio de producción** se van a actualizar automáticamente en la máquina de producción. Esta actualización se genera a través del archivo `update.sh` que se ejecuta recurrentemente en la máquina de producción con un _cronjob_.
132 changes: 132 additions & 0 deletions infra/productive-deploy/operations-manual.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Manual de Operaciones para el Planner

Este manual tiene como objetivo proporcionar una guía detallada para la gestión y mantenimiento del Planner. Se explican procedimientos para cambios de código, administración de contenedores Docker, respaldo de base de datos, y manejo de incidencias.

## Cambios de Código a través de GitHub

En las operaciones de la máquina productiva, existirán varias tareas que requieran modificar parte del código fuente del proyecto. Pero el código de la máquina se actualizará automáticamente con la última versión publicada en Github del proyecto Nuevo Planner, por lo que **es necesario hacer los cambios directamente en el repositorio de producción** y luego actualizar la máquina manualmente para **asegurarse de no perder ningún cambio**. Esto incluye cualquier cambio al código, tales como versión de paquetes utilizados, configuración de Docker, configuración del web server (Caddy), etc.

El flujo debe ser el siguiente:

1. Identificar el cambio que se quiere hacer (e.g. modificar la versión que se usa de una librería en el `package.json` del backend).
2. Ir al **repositorio de producción** ubicado en Github, hacer el cambio en una nueva rama de este, y generar la solicitud hacia la rama principal `main`.
3. Un vez que el cambio fue aprobado por la **Subdirección de Desarrollo** (la entidad de la universidad que está a cargo del código), la máquina será automáticamente actualizada luego de un plazo definido. Esta actualización ocurre de forma recurrente, a través de un _cronjob_ definido por la **Subdirección de Desarrollo** al levantar el proyecto por primera vez en la máquina.
4. (Opcional) Si es que el cambio es urgente, se puede forzar la actualización manual de la máquina ejecutando el archivo `update.sh`. De esta forma, no será necesario esperar al _cronjob_ recurrente para hacer efectivos los cambios. Más información en la sección [Forzar Actualizaciones Manualmente](#forzar-actualizaciones-manualmente).

⚠️ Advertencia: es muy importante seguir este flujo al querer hacer cambios en el código, ya que de lo contrario los cambios no "commiteados" en el repositorio de Github se van a borrar de la máquina durante la actualización recurrente.

❓ Aclaración: el "**repositorio de producción**" se refiere al repositorio ubicado en Github bajo el control exclusivo de la **Subdirección de Desarrollo**. No confundir con el repositorio **de desarrollo** controlado por la organización Open Source UC.

## Notas sobre el comportamiento de los contenedores

- Al reiniciar la máquina, los contenedores Docker se levantan automáticamente. Si ocurrió un problema, seguirán intentando levantarse hasta llegar a un limite de muchos intentos.

## Respaldo de Base de Datos

Para la base de datos, se utiliza un contenedor de Docker llamado "planner-db" que utiliza PostgreSQL. Actualmente, estamos usando la **versión 15** de la [imagen oficial de postgres](https://hub.docker.com/_/postgres) en Docker Hub.

Se puede ingresar a este contenedor con el comando `docker exec -it planner-db ash`. Desde aquí, existe acceso a herramientas pre-instaladas en la imagen de PostgreSQL, tales como `psql` y `pg_dump`.

Para generar y restaurar respaldos de la base de datos, se pueden utilizar ambos comandos de la siguiente manera:

1. Generar respaldo: `docker exec planner-db pg_dump -U [nombre_usuario] [nombre_base_de_datos] > [ruta_archivo_sql_output]`.

Por ejemplo,

> `docker exec planner-db pg_dump -U postgres postgres > /ruta/para/guardar/el/backup.sql`
2. Restaurar respaldo: `docker exec -i planner-db psql -U [nombre_usuario] -d [nombre_base_de_datos] < [ruta_archivo_sql_input]`.

Por ejemplo,

> `docker exec -i planner-db psql -U postgres -d postgres < /ruta/para/guardar/el/backup.sql`
## Algunos Comandos Útiles

- Acceso a un contenedor (_backend_, _frontend_, _bbdd_ y _redis_ respectivamente):

> docker exec -it [planner-api | planner-web | planner-db | planner-redis] ash
- Revisar el estado de los contenedores

> docker ps
- Detener todos los contenedores:

> docker compose down
💠 Nota: los comandos podrían variar ligeramente dependiendo del sistema operativo y versión de _Docker Compose_. En particular, podría ser necesario utilizar `docker-compose` en vez de `docker compose` y `sudo docker compose` en vez de `docker compose`.

- Levantar todos los contenedores de producción:

> docker compose up planner -d --build
💠 Nota: `planner` es el nombre del servicio web, del cual dependen los demás, por lo que se encienden automáticamente al encender este servicio.

- Reiniciar todos los contenedores:

> docker compose restart
- Obtener logs de un contenedor:

> docker logs [planner-api | planner-web | planner-db | planner-redis]
- Variaciones útiles para gestionar logs

- Ver los últimos N líneas de logs de un contenedor:

> docker logs --tail N [planner-api | planner-web | planner-db | planner-redis]
- Seguir los logs de un contenedor (streaming en tiempo real):

> docker logs -f [planner-api | planner-web | planner-db | planner-redis]
- Ver logs de un contenedor desde una fecha y hora específica:

> docker logs --since YYYY-MM-DDTHH:MM:SS [planner-api | planner-web | planner-db | planner-redis]
- Ver logs de un contenedor de los últimos X minutos:

> docker logs --since Xm [planner-api | planner-web | planner-db | planner-redis]
- Guardar los logs de un contenedor en un archivo:

> docker logs [planner-api | planner-web | planner-db | planner-redis] > /ruta/al/archivo.log
## Actualización de la Plataforma

Para actualizar el servicio expuesto a internet y aplicar parches de seguridad.

### Actualización de Backend y Frontend

- **Backend (Python):**
El archivo `pyproject.toml` contiene las versiones compatibles con el proyecto. Si es necesario instalar una versión específica de un paquete, se debe modificar la versión en este archivo.

💠 Nota: Considera eliminar el archivo `poetry.lock` para actualizar automáticamente a las nuevas versiones.

- **Frontend (Node.js):**
Se usa NPM para manejar dependencias. Si es necesario instalar una versión específica de un paquete, se debe modificar la versión en el archivo `package.json`.

💠 Nota: Considera eliminar el archivo `package-lock.json` para actualizar automáticamente a las nuevas versiones.

⚠️ Advertencia: ambas modificaciones presentadas aquí significan cambios al código, por lo que deben ser "commiteadas" al **repositorio de producción** tal como se muestra en la primera sección de este documento.

### Renovación de Certificados

- La renovación de certificados es automática con el servidor web [Caddy](https://caddyserver.com/).
- En caso de problemas, primero revisar si es posible solucionarlo modificando la configuración de Caddy en el archivo `Caddyfile` ubicado en `frontend/conf/Caddyfile`.
- En emergencias, si lo anterior no funcionó entonces se puede revisar la carpeta que contiene los certificados para una probar un renovación manual. Estos se encuentran en un volumen Docker llamado `caddy_data`. Una forma de acceder a esta ubicación para encontrar los certificados almacenados es generar un contenedor temporal con el siguiente comando:
> docker run --rm -it -v caddy_data:/data alpine
### Forzar Actualizaciones Manualmente

Tal como se mencionó al comienzo, hay un archivo llamado `update.sh` que está programado para ejecutarse recurrentemente con un _cronjob_ en la máquina. En el flujo normal de actualizaciones, solamente debería ser necesario modificar el código de la rama principal _main_ en el **repositorio de producción** para hacer cambios al proyecto. Pero en el caso de una emergencia, es posible ejecutar manualmente el archivo `update.sh` para forzar una actualización ahora, sin tener que esperar al _cronjob_. La ejecución de este archivo debería ser suficiente.

En caso de tener problemas con las actualizaciones recurrentes, se puede revisar el _cronjob_ usando el siguiente comando:

> crontab -e
## Nuevas Incidencias

- Cualquier incidencia crítica que surja durante la puesta en marcha, y no se encuentre documentada en este manual, debe ser comunicada al **Equipo de Desarrollo** del proyecto Nuevo Planner.
- Para incidencias no críticas, siempre está la opción de generar un _issue_ en el [repositorio de desarrollo](https://github.com/open-source-uc/planner/issues) del proyecto.
1 change: 1 addition & 0 deletions infra/productive-deploy/update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# falta implementar
1 change: 1 addition & 0 deletions run_deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# falta implementar

0 comments on commit e427241

Please sign in to comment.