Migra rápidamente a contenedores separados para web y datos

:warning: Advertencia: Si no te sientes cómodo trabajando como administrador de sistemas Linux y no tienes experiencia con contenedores Docker, pasar a una implementación de múltiples contenedores te causará dificultades. Tanto el personal como los voluntarios aquí te pedirán apropiadamente que regreses a una implementación independiente de un solo contenedor gestionada completamente por el script launcher.

Si pasas a una implementación de múltiples contenedores y tu sistema se rompe como resultado, es probable que te encuentres con la oportunidad de quedarte con ambas partes rotas. Si lees las instrucciones a continuación y te parecen magia, en lugar de aclarar cómo funcionan realmente las cosas dentro de los contenedores, corre, no camines, hacia tu implementación independiente predeterminada más cercana y te harás un favor.

El método recomendado para migrar de una implementación de un solo contenedor a una de múltiples contenedores es esencialmente:

  • Haz una copia de seguridad de tu Discourse
  • Tira todo a la basura
  • Comienza de cero con una implementación de múltiples contenedores
  • Restaura tu copia de seguridad

Si, como yo, tienes un sitio grande que tarda horas en restaurarse, quizás te preguntes si hay una forma más rápida. ¡No te preguntes más! Migré de una implementación independiente a una implementación de tres contenedores (web, datos y Redis) en menos tiempo del que normalmente tarda ./launcher rebuild app para ese sitio. (12 minutos de tiempo de inactividad total, cuando reconstruir la aplicación a veces ha tomado más de 30 minutos.) Basado en mi experiencia, en el futuro mantendría Redis junto con Postgres en un solo contenedor data.

Si haces esto, asumes la responsabilidad de saber cuándo necesitas reconstruir tus otros contenedores (datos y, si eres tan imprudente como yo y separas Redis, también Redis). Ya no obtendrás actualizaciones gratuitas de todo con ./launcher rebuild app. Si no tienes los recursos para gestionar este proceso, utiliza una implementación independiente o compra Discourse alojado.

Prueba

No utilices este proceso para migrar a múltiples contenedores a menos que, después de leerlo, ahora entiendas también cómo te indicaría cómo migrar rápidamente de múltiples contenedores a uno solo. Si esto no es obvio para ti después de leer esto, entonces esta publicación es una tecnología suficientemente avanzada (es decir, indistinguible de la magia), y es posible que tampoco reconozcas si este proceso se rompe a mitad de camino, por lo que podrías terminar con un Discourse roto que no reconocerás hasta mucho después. Si eso sucede, te quedarás con ambas partes rotas. Si lo rompes, lo pagas, como dicen.

Copia de seguridad

Haz una copia de seguridad primero y activa las copias de seguridad de miniaturas primero para que no tengas que reconstruirlas todas al restaurar. Si cometes un error aquí, fácilmente entrarás en una situación donde la forma más fácil, segura y rápida de recuperarte es cambiar al método normal. Prepárate para volver al método recomendado si algo sale mal.

Descarga tu copia de seguridad. Los comandos a continuación implican mover archivos dentro de los datos de Discourse, y si cometes un error, quizás hayas eliminado tu copia de seguridad. Así que descárgala. Además, si tu copia de seguridad no incluye las subidas, respáldalas también. También se encuentran en el lugar donde moverás archivos.

En serio, haz una copia de seguridad.

Cuando hice esto, primero hice una copia de seguridad y luego una copia de seguridad remota del sistema antes de continuar.

Configurar nueva configuración de múltiples contenedores

Necesitarás al menos containers/web_only.yml y containers/data.yml, y si también quieres separar Redis, también containers/redis.yml. Comienza copiando samples/data.yml (y opcionalmente samples/redis.yml) al directorio containers/.

Si estás desplegando Redis por separado, elimina la plantilla de Redis de la parte superior del archivo containers/data.yml. (Pero no hagas eso sin una buena razón; es solo trabajo extra.)

Tienes dos formas de crear web_only.yml:

  1. Copia samples/web_only.yml a containers/; luego compara ambos con containers/app.yml, preservando cualquier configuración de Postgres en params: en tu nuevo containers/data.yml
    • Copia cualquier params: para Postgres de containers/app.yml a containers/data.yml
    • Crea una contraseña única para reemplazar SOME_SECRET
  2. Alternativamente, copia containers/app.yml a containers/web_only.yml y compáralo con samples/web_only.yml:
    • Elimina cualquier referencia a las plantillas de Postgres y Redis
    • Elimina toda la sección params: que solo tenía configuraciones de Postgres
    • Agrega una sección links: tal cual de samples/web_only.yml o modificada (ver abajo) si estás desplegando Redis en un contenedor separado
    • Agrega una sección de base de datos de samples/web_only.yml y crea una contraseña única para reemplazar SOME_SECRET
    • Cambia las definiciones de volúmenes de standalone a web_only

Aquí está la sección links: que debes usar si estás separando Redis en su propio contenedor en lugar de usar la opción razonable por defecto de agruparlo con Postgres en el contenedor de datos:

# Usa la clave 'links' para vincular contenedores, es decir, usa la bandera --link de Docker.
links:
  - link:
      name: data
      alias: data
  - link:
      name: redis
      alias: redis

El enlace redis no es necesario si estás combinando los contenedores de Redis y Postgres en un único contenedor de datos; esto es para mostrar lo que harías.

Aquí hay una copia de la configuración actual de Postgres en env en samples/data.yml que necesitarás cambiar SOME_SECRET en:

  ## TODO: configurar la conectividad a las bases de datos
  DISCOURSE_DB_SOCKET: ''
  #DISCOURSE_DB_USERNAME: discourse
  DISCOURSE_DB_PASSWORD: SOME_SECRET
  DISCOURSE_DB_HOST: data
  ## Si usas un único contenedor de datos+Redis, lo siguiente será "data"
  DISCOURSE_REDIS_HOST: redis

Ten en cuenta que para una implementación normal (no multisitio) no necesitarás modificar ninguna otra línea. DISCOURSE_DB_SOCKET es para un socket de dominio Unix para Postgres, no es un número de puerto.

Aquí hay un ejemplo del cambio en la definición de volúmenes al final de web_only.yml que necesitarás usar si lo copias de app.yml en lugar de de samples/web_only.yml:

@@ -75,10 +80,10 @@
 ## El contenedor Docker es sin estado; todos los datos se almacenan en /shared
 volumes:
   - volume:
-      host: /var/discourse/shared/standalone
+      host: /var/discourse/shared/web_only
       guest: /shared
   - volume:
-      host: /var/discourse/shared/standalone/log/var-log
+      host: /var/discourse/shared/web_only/log/var-log
       guest: /var/log

Ahora establece la misma contraseña secreta que usaste en containers/web_only.yml en containers/data.yml en lugar de SOME_SECRET.

Ahora estás listo para la migración.

Ahora es cuando tomas y descargas tu copia de seguridad final antes de intentar la migración rápida. Recuerda, si algo sale mal aquí, inmediatamente ve al método recomendado. No puedo enfatizarlo lo suficiente.

Contenedores de datos (Postgres) y Redis separados:

cd /var/discourse

./launcher stop app
cd  shared
mkdir data
mkdir redis
mv standalone/postgres_* data/
mv standalone/redis_data/ redis/
mv standalone web_only
mkdir -p data/log/var-log
mkdir -p redis/log/var-log

cd ..

./launcher destroy app

./launcher bootstrap data
./launcher bootstrap redis
./launcher start redis
./launcher start data

./launcher bootstrap web_only
./launcher start web_only

Contenedor de datos combinado Postgres+Redis:

cd /var/discourse

./launcher stop app
cd  shared
mkdir data
mv standalone/postgres_* data/
mv standalone/redis_data/ data/
mv standalone web_only
mkdir -p data/log/var-log

cd ..

./launcher destroy app

./launcher bootstrap data
./launcher start data

./launcher bootstrap web_only
./launcher start web_only

También ten en cuenta que si anteriormente configuraste nginx externo, necesitarás cambiar la ruta proxy_pass para que coincida con la nueva ubicación del socket web_only; por ejemplo, de http://unix:/var/discourse/shared/standalone/nginx.http.sock: a http://unix:/var/discourse/shared/web_only/nginx.http.sock:.

Para mí, en una VM de 2 núcleos con 4 GB de RAM y un sitio con copias de seguridad de 600 MB sin descargas, este proceso resultó en 12 minutos de tiempo de inactividad. Tus resultados pueden variar.

Ten en cuenta que nada de esto hasta ahora actualiza el launcher. Es posible que no estés actualizado. (Por ejemplo, ejecuté esto después de que estuviera disponible la actualización de Postgres 12, pero antes de haberla aplicado. Este proceso me dejó con Postgres 10. Luego, lo siguiente que hice fue reconstruir la aplicación de datos, lo que actualizó el launcher y me llevó exitosamente a través del proceso de actualización de Postgres 12.)

Qué hacer en futuras actualizaciones

Después de esta migración, si necesitas actualizar Redis o datos, primero debes detener la aplicación web. Esto se vería algo así:

./launcher stop web_only
./launcher rebuild data # y/o redis
./launcher rebuild web_only

Ten en cuenta que si reconstruyes el contenedor data (o postgres, o redis) necesitarás crear un nuevo contenedor web para volver a conectarlo con el nuevo contenedor de datos. Puedes hacerlo ya sea reconstruyendo web_only o, si no crees que necesitas reconstruirlo, un ./launcher destroy web_only; ./launcher start web_only hará el trabajo (y si obtienes un error sobre «falta el contenedor de datos» o similar, esto es lo que necesitas hacer).

Sin embargo, cuando ni Postgres ni Redis necesitan una actualización, es mucho más rápido no tener que reconstruir esos contenedores, y la mayoría de las reconstrucciones de aplicaciones son simplemente ./launcher rebuild web_only.

Alternativamente, para aún menos tiempo de inactividad (reportado variadamente entre 15 segundos y 2 minutos):

./launcher bootstrap web_only
./launcher destroy web_only && ./launcher start web_only

Nuevamente, al pasar a una implementación de múltiples contenedores, el seguimiento de cuándo es apropiado es ahora tu trabajo. Recibirás notificaciones en la consola de Administración sobre actualizaciones, pero solo se aplicarán al contenedor web_only. Nada te dirá cuándo necesitas actualizar Postgres o Redis. Si haces esto, lee la categoría de Anuncios antes de cada actualización de versión que realices, y lee las notas de la versión para cada nueva versión a la que estás actualizando o a través de la cual pasas. Es decir, si saltas una actualización de versión, no te saltes la lectura de las notas de la versión de la versión a la que saltaste la actualización. (Considera configurar una vigilancia en las notas de la versión o suscribir tu lector de feeds a https://meta.discourse.org/tag/release-notes.rss para mantenerte actualizado.)

Ten en cuenta que reconstruir el contenedor web_only requiere que la base de datos esté en ejecución, por lo que no puedes acelerar las cosas reconstruyendo los dos o tres contenedores en paralelo. Si vas a reconstruirlos todos cada vez, quédate con la implementación independiente estándar recomendada; será más rápida que manejar múltiples contenedores.

Revisión de la copia de seguridad

Si haces copias de seguridad de las subidas por separado de la base de datos, espero que tengas un régimen de copias de seguridad remotas basado en archivos para las subidas para que estén respaldadas para restaurar en caso de desastre.

Revisa tu implementación de copias de seguridad remotas para asegurarte de que hará copias de seguridad de las subidas en /var/discourse/shared/web_only en lugar de en /var/discourse/shared/standalone para que mantengas tus copias de seguridad actualizadas en tu nueva implementación de múltiples contenedores.

22 Me gusta

¡Hola, mcdanlj! Soy nuevo aquí. Encuentro que Discourse tiene dos métodos de implementación, uno es el modo independiente de app.yml, el otro es tu método que es dividir la base de datos y la caché de Redis en el modo multicontenedor de solo web.yml, data.yml, redis.yml. Pero al mismo tiempo, también encuentro que app.yml también puede conectarse a Redis y a la base de datos modificando los parámetros DISCOURSE_DB_HOST y DISCOURSE_REDIS_HOST, entonces, ¿por qué necesitamos dividir app.yml en web-only.yml, data.yml y redis.yml?

Si ya tienes una base de datos y Redis (por ejemplo, RDS y Elasticache, o creados por ti mismo de otra manera), entonces no necesitas tener los tuyos propios.

Ten en cuenta que cada Discourse necesita su propio Redis.

1 me gusta

¡Gracias Jay por tu amable explicación! Pero todavía estoy confundido. Por el Tutorial de Falco noto que es fácil usar rds y elasticache de aws sin necesidad de configurar web-only.yml, data.yml y redis.yml. El Tutorial de Falco solo edita los parámetros en app.yml. Pero el Tutorial de mcdanlj es diferente. ¿Es porque su foro es demasiado grande? ¿Por lo tanto, no puede usar la forma simple que proporciona Falco?

Usar rds y ejecutar tu propio servidor de bases de datos son dos cosas diferentes. Si tienes mucho dinero y experiencia, rds es genial. Si no sabes nada, una instalación en un solo contenedor es asombrosa. Si tienes poco dinero y quieres reducir el tiempo de inactividad, el enfoque de dos contenedores es bueno.

Principalmente, deberías usar el que tenga más sentido para ti.

1 me gusta

¡Muchas gracias! Quizás un solo contenedor sea la mejor manera para mí :rofl: No me di cuenta de la diferencia entre rds y mi propio servidor de base de datos antes de que me lo dijeras :joy:

1 me gusta

@ShawnLi Si el sistema de dos contenedores parece complicado, es una buena señal de que la opción predeterminada de un contenedor es una buena elección para ti. El despliegue de dos contenedores ahorra unos minutos de inactividad aproximadamente una vez al mes durante las actualizaciones, pero requiere más comprensión y que sigas manualmente los detalles de los anuncios en cada nueva versión.

Por eso empecé diciendo:

:grinning:

2 Me gusta

¡Gracias mcdanlj! Tu tutorial es genial y realmente aprendí mucho de él. Decido elegir la configuración predeterminada simple de un contenedor. Sí, corro :rofl:

2 Me gusta