diff --git a/content/tutorials/es/dashboard-loki-not-responding.mdx b/content/tutorials/es/dashboard-loki-not-responding.mdx new file mode 100644 index 00000000..6f507912 --- /dev/null +++ b/content/tutorials/es/dashboard-loki-not-responding.mdx @@ -0,0 +1,89 @@ +--- +sidebar_label: Dashboard Loki not responding +sidebar_position: 5 +title: "Dashboard Loki not responding" +description: "Dashboard Loki not responding" +tags: + - addons + - loki + - troubleshooting + - monitoring + - grafana + - logs +image: /img/tutorial-img.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; + +# Dashboard de Loki no responde + +:::success SOLUCION RAPIDA +Eliminar el pod 'loki-read'. Tras 60 segundos este vuelve a funcionar, y con este también el DataSource Loki y sus dashboards relacionados. +::: + +:::info +Este error es más recurrente en cluster con baja disponibilidad puesto que generan más rotación de nodos y de pods. Se puede disminuir la recurrencia de este error aumentando la cantidad de Pods loki-read desde la configuración del Addon Loki. +::: + +Loki puede estar andando, tal como en la siguiente imagen: + + + loki + + +- Si por alguna rotación en Kubernetes se resetea el pod de loki-backend SIN resetearse el de loki-read comienza a fallar, tal como fuerzo reiniciando el StatefulSet de loki-backend lo que concluye en la siguiente situación: + + + loki-2 + + +Puede verse que el '_Age_' de loki-backend es menor que el '_Age_' de loki-read, en estos casos ocurre este error que provoca que el DataSource de Loki no funcione y por ende tampoco los dashboards que lo utilizan. El error surge porque los pods de 'loki-read' no intentan reconectarse a 'loki-backend' y quedan en este estado donde no responden a las requests que les hace 'loki-backend'. + +- Puede verse que el error se forzó correctamente y ahora el dashboard no responde: + + + loki-3 + + +- La forma para fixearlo es reiniciando el Deployment de 'loki-read' o bien eliminando el Pod que esté corriendo. + + + loki-4 + + +- Una vez hecho eso volvemos a la situación deseada que es la siguiente: + + + loki-5 + + +Como puede verse ahora el _Age_ de loki-read es menor que el _Age_ de loki-backend con lo que nos aseguramos que loki-read está conectado y el Dashboard vuelve a funcionar correctamente como se ve en la siguiente imagen: + + + loki-6 + + +Se puede disminuir la recurrencia de este error si se incrementa la cantidad de pods 'loki-read' activos. Lo cual puede realizarse desde la configuración del Addon Loki. + + + loki-7 + diff --git a/content/tutorials/es/django-celery.mdx b/content/tutorials/es/django-celery.mdx new file mode 100644 index 00000000..cc5e6866 --- /dev/null +++ b/content/tutorials/es/django-celery.mdx @@ -0,0 +1,478 @@ +--- +sidebar_label: Django + Celery +sidebar_position: 10 +title: "Django + Celery" +description: "Aprende cómo desplegar tu proyecto Django + Celery con modo worker distribuido y escalable en Kubernetes usando Sleakops" +tags: + - django + - celery + - deploy + - python + - background-jobs + - kubernetes + - scaling +image: /img/tutorials/django-celery/django-celery.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; +import { FiExternalLink } from "react-icons/fi"; + +Aprende cómo desplegar tu proyecto Django + Celery usando Sleakops. + +## Prerrequisitos + +- Cuenta en Sleakops +- Un Clúster en esta cuenta. Si no lo tienes, [aquí está la documentación sobre cómo hacerlo](/docs/cluster). +- Un Ambiente configurado. Si no lo tienes, [aquí está la documentación sobre cómo hacerlo](/docs/environment). +- Proyecto Django configurado con celery (Este proyecto necesita tener docker). + +## Empecemos + +Para este ejemplo, vamos a usar [este proyecto ](https://github.com/sleakops/example-django-celery). Es un proyecto Django con Celery que ya tiene Docker configurado para funcionar. También vamos a configurar una base de datos Postgresql, bucket S3 y Rabbitmq necesarios para este proyecto. + +### Crear un proyecto + +Para empezar, vamos a crear un nuevo proyecto. Para hacer esto, hacemos clic en el botón "Projects" en el panel izquierdo: + + + click-project-reference + + +Dentro del panel de Proyectos podrás ver todos los proyectos que tienes y gestionarlos desde aquí. Queremos crear uno nuevo así que hagamos clic en el botón "create" en la parte superior derecha: + + + click-create-project-reference + + +En la pantalla de creación de proyecto tenemos los siguientes campos: +| **Configuración** | **Descripción** | +| --- | --- | +| **Environment** | Tenemos que seleccionar el ambiente creado previamente. | +| Nodepool| Dejaremos el predeterminado. | +| **Repositories** | Seleccionaremos nuestro repositorio que queremos desplegar. En nuestro caso example-django-celery. | +| Project Name | Podemos definir un nombre de proyecto. Para el ejemplo dejaremos el predeterminado. | +| **Branch** | Tiene que coincidir con el que tenemos en nuestro proyecto. En nuestro caso es "Main". | +| Dockerfile path | Es la ruta relativa al dockerfile en tu proyecto. | + +Una vez configurado todo eso, creamos el proyecto con el botón "Submit" en la parte inferior derecha: + + + create-project-reference + + +Con eso, el proyecto comienza a crearse. Mientras tanto vamos a las cargas de trabajo con el botón "Workloads" en el panel izquierdo: + + + click-workloads-reference + + +### Crear un Servicio Web + +Aquí lo que vamos a hacer es crear un servicio web, así que vamos a la sección de servicio web y creamos uno: + + + click-create-web-service-reference + + +En esta página vamos a completar el primer formulario con los siguientes campos: +| **Configuración** | **Descripción** | +| --- | --- | +| **Project** | Seleccionamos el proyecto que creamos previamente, en nuestro caso "example-django-celery". | +| Name | Definimos un nombre para el servicio web. | +| **Command** | Por defecto esto tomará el valor que está en el dockerfile, en nuestro caso esto está bien. | +| Port | Lo mismo que el command. | + +Luego continuamos haciendo clic en el botón "Next" hasta el paso 3: + + + create-web-service-reference + + +En el paso 3 tenemos que editar el campo path y poner el endpoint de healthcheck que en nuestro caso es "/healthcheck/". Luego hacemos clic en el botón "Next" hasta que se cree el servicio web: + + + create-web-service-2-reference + + +### Desplegar celery worker + +Bueno, con esto podemos ver nuestro servicio web desplegándose. Ahora vamos a desplegar el celery. Para esto tenemos que ir a la sección workers dentro de la misma pantalla de workloads: + + + click-worker-reference + + +Y hacemos clic en el botón "Create" para crear uno nuevo: + + + click-create-worker-reference + + +En la pantalla de creación de workers tendremos que completar los siguientes campos: +| **Configuración** | **Descripción** | +| --- | --- | +| **Project** | Seleccionar el proyecto creado previamente. En nuestro caso "example-django-celery". | +| Name | Definimos el nombre que le vamos a dar al worker. En nuestro caso "celery". | +| **Command** | Aquí establecemos el comando para ejecutar celery, en nuestro caso es: `bash celery -A core.celery_app worker -l INFO --concurrency 1 --max-tasks-per-child 1 --prefetch-multiplier 1 -n celery@%h --queues default,build,deployment,cluster,canvas,billing`| + +Con estos campos completados haremos clic en el botón "Next" en la parte inferior derecha y luego "Submit" ya que no necesitamos editar nada más: + + + create-worker-reference + + +Con esto veremos nuestro celery publicado. Ahora tenemos que configurar los hooks. Para esto vamos a la sección hooks: + + + click-hook-reference + + +### Crear un hook de migración + +En la pantalla de creación de hook tendremos los siguientes campos: +| **Configuración** | **Descripción** | +| --- | --- | +| **Project** | Seleccionar el proyecto creado previamente. En nuestro caso "example-django-celery". | +| **Name** | Definimos el nombre que le vamos a dar al worker. En nuestro caso "migrations". | +| **Command** | Aquí establecemos el comando para ejecutar celery, en nuestro caso es: `bash python manage.py migrate --no-input ` | + +Con estos campos completados haremos clic en el botón "Next" en la parte inferior derecha y luego "Submit" ya que no necesitamos editar nada más: + + + create-hook-reference + + +### Crear un hook de collect static + +Ahora procedemos a crear otro hook que necesitamos para los estáticos: + + + click-create-collectstatic-hook-reference + + +En este formulario vamos a hacer lo mismo que el anterior pero modificando el comando. Hacemos clic en next hasta crear el hook (sin modificar nada más): + + + create-collectstatic-hook-reference + + +El comando que usamos es el siguiente: + +```bash +python manage.py collectstatic --no-input +``` + +### Crear una Base de Datos Postgresql + +Una vez que hemos creado los hooks tenemos que ir a crear nuestra base de datos. Para hacer esto vamos a la sección "Dependencies": + + + click-dependencies-reference + + +Dentro de esta sección hacemos clic en el botón "Create" en la parte superior derecha y luego seleccionamos "Postgresql": + + + click-create-dependencies-reference + + + click-postgresql-reference + + +En el 1er formulario de creación de postgresql tendremos que seleccionar nuestro proyecto creado previamente y definir un nombre para él, luego hacemos clic en el botón "Next" en la parte inferior derecha: + + + create-postgresql-reference + + +En el 2do formulario vamos a tener muchos campos, los únicos que nos importan son los siguientes: +| **Configuración** | **Descripción** | +| --- | --- | +| **Database Master Username** | Aquí asignamos un nombre de usuario root a nuestra base de datos. | +| **Database Master Password** | Una contraseña para este usuario root. | + +Una vez rellenados estos campos, estamos listos para continuar. Haga clic en el botón «Siguiente» situado en la parte inferior derecha para pasar al tercer formulario: + + + create-postgresql-2-reference + + +En este último formulario, vamos a ajustar las variables de entorno que tenemos en nuestro proyecto con respecto a la base de datos. Para ello, debemos cambiar las siguientes variables por las nuestras propias: +| **Antes** | **Despues** | +| --- | --- | +| \*\_POSTGRESQL_NAME | DB_NAME | +| \*\_POSTGRESQL_USERNAME | DB_USER | +| \*\_POSTGRESQL_PASSWORD | DB_PASSWORD | +| \*\_POSTGRESQL_ADDRESS | DB_HOST | +| \*\_POSTGRESQL_PORT | DB_PORT | + +Debería verse similar a la imagen de abajo. A continuación, haga clic en el botón «Enviar» y se creará su base de datos: + + + create-postgresql-3-reference + + +### Crear Bucket S3 + +En la misma página de dependencias tenemos que crear nuestro bucket s3, para ello vamos a ir al botón "Create" nuevamente: + + + click-create-s3-dependencies-reference + + +Y seleccionamos S3 Bucket: + + + click-create-s3-dependencies-2-reference + + +En el primer formulario tenemos que seleccionar nuestro proyecto creado previamente y definir un nombre para el bucket, tenemos que tomar en cuenta que el nombre del bucket es global así que tiene que ser único. Ahora hacemos clic en el botón "Next" y vamos al paso 3: + + + create-s3-dependencies-reference + + +Aquí vamos a ver algunas variables de entorno definidas para el bucket. Vamos a editar la que dice **COLLECTSTATICEXAMPLEDJANGOCELERY_BUCKET_NAME** y la vamos a llamar **DJANGO_AWS_STORAGE_BUCKET_NAME**. Con este simple cambio hacemos clic en el botón "Submit" en la parte inferior derecha para terminar de crear el bucket: + + + create-s3-dependencies-3-reference + + +### Crear Rabbitmq + +Ahora necesitamos una dependencia más. Nuestro Rabbitmq para encolar las tareas de celery, así que vamos a ello: + + + click-create-rabbitmq-dependencies-reference + + +Y seleccionamos Rabbitmq: + + + click-select-rabbitmq-reference + + +En el primer formulario tendremos que seleccionar nuestro proyecto y definir un nombre para él. Luego hacemos clic en el botón "Next" en la parte inferior derecha: + + + create-rabbitmq-reference + + +En el siguiente formulario tenemos varios campos pero los únicos que nos importan para este ejemplo son el username y password, podemos definir lo que queramos. Para este ejemplo elegí admin como username y para la contraseña la generé aleatoriamente con el botón de dado. Luego hacemos clic en el botón "Next" para ir al siguiente formulario: + + + create-rabbitmq-2-reference + + +En este último formulario tenemos que cambiar el nombre de la variable que termina en \*\_BROKER_AUTH_URL a CELERY_BROKER_URL (como se muestra en la imagen). Luego hacemos clic en el botón "Submit" en la parte inferior derecha para terminar de crear rabbitmq: + + + create-rabbitmq-3-reference + + +### Crear tus variables de entorno + +Una vez que las dependencias están desplegadas tenemos que configurar nuestras variables de entorno. Vamos a ir a la sección **Vargroups**: + + + click-vargroups-reference + + +Aquí verás todas tus variables de entorno que creaste agrupadas en grupos, por ejemplo deberías haber creado una con los datos para la base de datos (que es la que ves en la imagen). Ahora vamos a crear otra para nuestras variables de entorno de django, para esto hacemos clic en el botón "Create" en la parte superior derecha: + + + click-create-vargroups-reference + + +En este formulario tenemos los siguientes campos: + +- Project: seleccionamos el proyecto que creamos previamente. +- Workload: Seleccionamos "global" que hace referencia a ser usado por todos nuestros workloads. +- Name: Definimos un nombre para este grupo de variables. +- Type: Si queremos cargarlo por archivo o por variable. +- Vars: Aquí habilitamos el textmode y copiamos las siguientes variables de entorno: + +```bash +CELERY_RESULT_BACKEND=django-db +DJANGO_ADMIN_URL=admin/ +DJANGO_DEBUG=False +DJANGO_SECRET_KEY=secret_key +DJANGO_SETTINGS_MODULE=core.settings.production +DJANGO_STATIC_STORAGE=storages.backends.s3boto3.S3StaticStorage +DB_ENGINE=django.db.backends.postgresql_psycopg2 +ENVIRONMENT=production +LOGS_LEVEL=INFO +PYTHONPATH=. +``` + +Estas variables de entorno son requeridas para nuestro proyecto de ejemplo. Finalmente hacemos clic en el botón "Submit" en la parte inferior derecha para crear el grupo de variables. + + + create-vargroup-reference + + +### Despliegues + +Como último paso vamos a ver nuestro proyecto desplegado, para esto vamos a la sección "Deployments" del panel izquierdo: + + + click-deployments-reference + + +Aquí vamos a ver todos los despliegues que hacemos. En nuestro caso es el primero y podemos ver que se ha creado correctamente, en caso de que veas algún error si haces clic en "error" puedes ver una descripción del mismo. +Si no vemos ningún error entonces significa que el proyecto ya está desplegado, podríamos comenzar a usarlo desde la url que nos proporcionó el servicio web. + + + deployments-reference + + +Esto concluye nuestro proceso de despliegue de proyecto. Te dejamos un paso opcional que es configurar el ci con github. + +## Opcional + +### CI con Github + +Cada vez que hagas un cambio en tu código y quieras desplegarlo tendrás que hacer un build y un deploy, esto eventualmente se vuelve tedioso. Por eso para evitar esto tenemos que implementar ci en github. + +Para esto vamos a ir a "Projects" en el panel izquierdo: + + + click-project-2-reference + + +Ubiquemos nuestro proyecto y hagamos clic en el engranaje para acceder a la configuración del proyecto: + + + click-settings-project-reference + + +En la configuración del proyecto ubicamos el que dice "Git pipelines" y hacemos clic en él: + + + click-git-pipelines-reference + + +Aquí vamos a encontrar lo que necesitamos para hacer esto. Básicamente necesitamos configurar un archivo en la raíz de nuestro proyecto .github/workflows/ llamado ci_sleakops_demo.yml y en ese archivo vamos a pegar el contenido que aparece en esta página. + + + git-pipelines-reference + + +Esto necesita tener una variable de entorno SLEAKOPS_KEY, si no la tienes tienes que ir al enlace que aparece ahí **Settings -> CLI**, obtenerla y guardarla como una variable de entorno. + +Con esto configurado y desplegado cada vez que hagas un push a tu rama "main" se lanzará automáticamente una nueva versión de tu aplicación. diff --git a/content/tutorials/es/install-keda.mdx b/content/tutorials/es/install-keda.mdx new file mode 100644 index 00000000..a02471e5 --- /dev/null +++ b/content/tutorials/es/install-keda.mdx @@ -0,0 +1,112 @@ +--- +sidebar_label: "Instalar KEDA" +sidebar_position: 6 +title: "Instalar KEDA" +description: "Tutorial: instalar KEDA" +tags: + - tutorial + - install + - keda + - autoscaling + - kubernetes + - event-driven + - scaling +image: /img/tutorials/install-keda/install-keda.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; +import { FiExternalLink } from "react-icons/fi"; + +Aprende cómo instalar KEDA (Kubernetes Event-Driven Autoscaling) en tu clúster usando diferentes métodos. KEDA permite escalar automáticamente tus aplicaciones basándote en eventos y métricas personalizadas. + +## Métodos de Instalación + +### Usando la interfaz de Lens (opción 1) + +1. En el menú de Lens o el IDE de kubernetes que uses, ve a **Helm > Charts**. +2. En el buscador, escribe **keda**. Debería aparecerte el chart oficial de Bitnami: + - `bitnami/keda` +3. Selecciona la versión que desees (por ejemplo, la más reciente disponible). +4. Haz clic en **Install** y en la siguiente ventana revisa los valores (YAML) para la instalación si deseas personalizar algo (por defecto, suele ser suficiente). +5. Confirma la instalación presionando **Install** nuevamente. + +### Usando Helm por terminal (opción 2) + +Si prefieres la línea de comandos o no dispones de la sección de Helm en Lens, puedes instalarlo así: + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo update + +# Creamos un namespace (opcional) +kubectl create namespace keda + +# Instalamos KEDA +helm install keda bitnami/keda --namespace keda +``` + +## Verificación de la Instalación + +Después de la instalación, deberías ver que los recursos de KEDA se han creado: + +### En Lens + +- Selecciona el namespace donde instalaste KEDA (por defecto, `keda` si lo creaste manualmente). +- Verás un **Deployment** llamado `keda-operator`, uno o más **Pods**, y otros recursos de tipo CRD (Custom Resource Definitions) como `ScaledObjects` y `TriggerAuthentications`. + +### Por terminal (opcional) + +```bash +kubectl get all -n keda +``` + +Deberías ver el operador corriendo, por ejemplo: + +``` +NAME READY STATUS RESTARTS AGE +pod/keda-operator-xxxxx-xxxxx 1/1 Running 0 1m +``` + +Si todo está en orden, ya puedes usar KEDA para tu primer autoscaling basado en eventos o métricas personalizadas. + +## Configuración del ScaledObject + +### ¿Qué es un ScaledObject? + +Ahora crearemos un `ScaledObject`. Este recurso es el que indica a KEDA cómo y cuándo escalar el despliegue. En este ejemplo, usaremos un trigger de **CPU**, aunque KEDA lo maneja internamente vía `HorizontalPodAutoscaler` (HPA), pero la lógica se integra con la CRD de KEDA. + +Puedes revisar todos los posibles triggers que ofrece KEDA en la documentación oficial [aquí](https://keda.sh/docs/2.16/scalers/). + +### Creación del ScaledObject + +Para crear este objeto vamos a usar la función de extend-charts en Sleakops. Para llegar desde el listado de proyectos en Sleakops vamos a **Settings > Chart Configuration**. + +Una vez estés en la pantalla de Chart Configuration puedes agregar tu `ScaledObjects`. + +Para poder completar los valores del ScaledObject vas a necesitar algunos valores como el namespace y el nombre del objeto deployment (generado por Sleakops) en el cluster. + +- El namespace podrías usar la siguiente anotación, como en el siguiente ejemplo: `{{ .Values.global.namespace }}` para sacarlo de los values que ya genera Sleakops +- El nombre del deployment, por el momento no lo disponibilizamos. Para obtenerlo puedes entrar a Lens o tu IDE de kubernetes dirigirte a la sección de **Workloads > Deployments** + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: http-echo-scaledobject + namespace: { { .Values.global.namespace } } +spec: + scaleTargetRef: + # Debe coincidir con el nombre del Deployment + name: http-echo-deployment + # minReplicaCount y maxReplicaCount determinan los límites de escalado + minReplicaCount: 1 + maxReplicaCount: 5 + + # Trigger que define la condición de escalado (en este caso CPU) + triggers: + - type: cpu + metadata: + type: Utilization # o AverageValue + value: "50" # por encima de 50% de CPU se escala +``` diff --git a/content/tutorials/es/make-rds-public.mdx b/content/tutorials/es/make-rds-public.mdx new file mode 100644 index 00000000..bbafff96 --- /dev/null +++ b/content/tutorials/es/make-rds-public.mdx @@ -0,0 +1,152 @@ +--- +sidebar_label: "Hacer pública base de datos RDS" +sidebar_position: 4 +title: "Hacer pública base de datos RDS" +description: "Aprende cómo hacer una base de datos RDS públicamente accesible usando un método workaround" +tags: + - rds + - database + - aws + - security + - networking + - vpc + - postgresql +image: /img/tutorials/make-rds-public/make-rds-public.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; + +:::warning +**Trata de evitar este método que expone tu fuente de datos.** +::: + +## Introducción y Caso Actual + +Actualmente todas las bases de datos levantadas con SleakOps tienen la misma configuración de accesos: + +- Publicly Accessible ❌ +- Alocada en SubnetGroup conformado por subnets "de Persistencia" creadas en la VPC de SleakOps. + +Bajo esta configuración no existe forma directa de transformar a la DB a acceso público por lo que hay que realizar un pequeño workaround. + +**¿Por qué no se puede hacer pública una base de datos de forma directa?** + +- No se puede editar un SubnetGroup de RDS. +- AWS no permite editar el SubnetGroup asociado a una RDS sin que exista cambio de VPC. Por ende, nos obliga a hacerlo usando una VPC externa. + +--- + +## Solución con Workaround + +### Pre-requisitos: + +1. 30 mins aproximadamente. +2. Tener creada la VPC default con Subnets en la cual situar la DB. De no tenerse, habrá que crear una nueva de 0 por nuestra cuenta así como subnets dentro de ella que se usaran para este cambio. Llamémosla "transitoria". +3. Crear el SubnetGroup que utilice Subnets de la VPC transitoria, es indistinto las subnets que use. Se utiliza para migrar hacia la otra VPC. + + En mi caso yo creé la siguiente, nótese que tanto la VPC como las Subnets son de la VPC Default. + + + rds-db-public-1 + + +4. Crear el SubnetGroup que utilice las Subnet Públicas de la VPC desplegada por SleakOps. Esta es la que usará la DB al final del flujo. + + + rds-db-public-2 + + +5. Crear un SecurityGroup que permita el acceso público, o bien editar el existente. Para ambos casos debe pertenecer a la VPC donde está la Base de Datos. + + En mi caso creé el siguiente. + + + rds-db-public-3 + + +### Paso a Paso: + +Con los pre-requisitos cumplidos solo realizar las modificaciones a las configuraciones. + +1. Cambiar el SubnetGroup al correspondiente a la VPC Transitoria y eliminar el SG actual. + + + rds-db-public-4 + + +2. Tocar next y hacer la revisión de los cambios, tener en cuenta seleccionar **'Apply Immediately'**. + + + rds-db-public-5 + + + Una vez hecho esto hay que esperar que se aplique el cambio para luego seguir con los pasos siguientes donde se vuelve a la VPC inicial que es la creada por SleakOps. + +3. Finalizado el cambio de VPC. Cambiar el SubnetGroup al público que fue creado, el cual se conformó con las Subnet Públicas de la VPC de SleakOps. Nuevamente, eliminar el SG default que se liga automáticamente. + + + rds-db-public-6 + + +4. Hacer la DB **`Publicly Accessible`**. + + + rds-db-public-7 + + +5. Revisar los cambios, deberían ser los siguientes. Dar next y **Apply Immediately**. + + + rds-db-public-8 + + + Nuevamente esperar a que se termine de realizar el cambio para el último paso: + +6. Agregar el SecurityGroup creado en los pre-requisitos. + + + rds-db-public-9 + + +7. Revisar el cambio. Dar next y **Apply Immediately** nuevamente. + + + rds-db-public-10 + + +--- + +## Conclusión + +Con esto nuestra DB queda completamente pública para todas las request en el puerto que use la DB, para el caso de Postgres, **5432**. diff --git a/content/tutorials/es/n8n-worker.mdx b/content/tutorials/es/n8n-worker.mdx new file mode 100644 index 00000000..cd73da65 --- /dev/null +++ b/content/tutorials/es/n8n-worker.mdx @@ -0,0 +1,241 @@ +--- +sidebar_label: "n8n + Worker Mode" +sidebar_position: 2 +title: "n8n + Worker Mode" +description: "Aprende cómo desplegar tu proyecto n8n con modo worker distribuido y escalable en Kubernetes usando Sleakops" +tags: + - n8n + - kubernetes + - worker + - scaling + - automation + - background-jobs + - deployment +image: /img/tutorials/n8n-worker/n8n-worker.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; +import { FiExternalLink } from "react-icons/fi"; + +Aprende cómo desplegar tu proyecto n8n con modo worker distribuido y escalable en Kubernetes usando Sleakops. + +## Prerrequisitos + +- Cuenta en Sleakops +- Un Clúster en esta cuenta. Si no lo tienes, [aquí está la documentación sobre cómo hacerlo](/docs/cluster). +- Un Ambiente configurado. Si no lo tienes, [aquí está la documentación sobre cómo hacerlo](/docs/environment). +- Proyecto n8n configurado con Docker. + +## Empecemos + +Para este ejemplo, vamos a desplegar un proyecto n8n en modo distribuido con procesos worker. Esta configuración incluye el servicio principal de n8n (interfaz web) y procesos worker para ejecutar workflows. También vamos a configurar una base de datos PostgreSQL y Redis para la gestión de colas, que son necesarios para este proyecto. + +### Crear un proyecto + +Los proyectos son nuestros repositorios de código. Todo lo que Sleakops necesita para ejecutar comandos es un Dockerfile. + +Para más información, consulta nuestra documentación de proyectos. + +Para comenzar, vamos a crear un nuevo proyecto: + +En la pantalla de creación de proyecto tenemos los siguientes campos: + +| Configuración | Descripción | +| --------------- | -------------------------------------------------------------------------- | +| Environment | Necesitamos seleccionar el ambiente creado previamente. | +| Nodepool | Dejaremos el predeterminado. | +| Repositories | Seleccionaremos nuestro repositorio que contiene el proyecto n8n. | +| Project Name | Podemos definir un nombre de proyecto. Por ejemplo, "n8n-server". | +| Branch | Debe coincidir con la rama en nuestro proyecto. En nuestro caso es "main". | +| Dockerfile path | Esta es la ruta relativa al Dockerfile en tu proyecto. | + +Una vez configurado todo eso, creamos el proyecto con el botón "Submit" en la parte inferior derecha. + +### Crear un Servicio Web + +En esta página vamos a completar el primer formulario con los siguientes campos: + +| Configuración | Descripción | +| ------------- | -------------------------------------------------------------------------------- | +| Project | Seleccionamos el proyecto que creamos previamente, en nuestro caso "n8n-server". | +| Name | Definimos un nombre para el servicio web, por ejemplo "n8n-main". | +| Command | Comando por defecto del Dockerfile (usualmente n8n start). | +| Port | Puerto 5678 (puerto por defecto de n8n). | + +En el segundo paso, configuraremos el servicio web como **privado**. + +### Crear un Worker + +En la pantalla de creación de workers tendremos que completar los siguientes campos: + +| Configuración | Descripción | +| ------------- | ------------------------------------------------------------------------------- | +| Project | Seleccionar el proyecto creado previamente. En nuestro caso "n8n-server". | +| Name | Definimos el nombre que le vamos a dar al worker. En nuestro caso "n8n-worker". | +| Command | Aquí establecemos el comando para ejecutar el worker de n8n: `worker` | + +Con estos campos completados haremos clic en el botón "Next" en la parte inferior derecha y luego "Submit" ya que no necesitamos editar nada más. + +## Configurar Dependencias + +Primero, necesitamos crear una dependencia de Redis para la cola de tareas. En la pantalla de creación de dependencias, selecciona Redis y verás los siguientes campos: + +| Configuración | Descripción | +| --------------- | ------------------------------------------------------------------------- | +| Dependency Type | Seleccionar "Redis" de las opciones disponibles. | +| Project | Seleccionar el proyecto creado previamente. En nuestro caso "n8n-server". | +| Name | Definir el nombre para Redis. En nuestro caso "n8n-redis". | + +Con estos campos completados, haremos clic en el botón "Next" en la parte inferior derecha. En el último paso, antes de hacer clic en "Submit", cambiaremos los nombres de las variables de entorno para que coincidan con lo que n8n espera. + +Necesitamos configurar las variables de conexión de Redis para que coincidan con lo que n8n espera: + +| Variable | Valor | +| --------------------- | ------------------------------ | +| QUEUE_BULL_REDIS_HOST | (Host de la dependencia Redis) | +| QUEUE_BULL_REDIS_PORT | 6379 | + +Al igual que con Redis, necesitamos configurar los nombres de las variables de entorno según lo que n8n espera. Ve al último paso y antes de hacer clic en submit, cambia los nombres a los siguientes: + +| Antes | Después | +| ----------------------- | ---------------------- | +| \*\_POSTGRESQL_NAME | DB_POSTGRESDB_DATABASE | +| \*\_POSTGRESQL_USERNAME | DB_POSTGRESDB_USER | +| \*\_POSTGRESQL_PASSWORD | DB_POSTGRESDB_PASSWORD | +| \*\_POSTGRESQL_ADDRESS | DB_POSTGRESDB_HOST | +| \*\_POSTGRESQL_PORT | DB_POSTGRESDB_PORT | + +Debería verse similar a la imagen de abajo. Luego haz clic en el botón "Submit" y se creará tu base de datos. + +## Despliegues + +Como último paso vamos a ver nuestro proyecto desplegado. Para esto vamos a la sección "Deployments" del panel izquierdo. + +Aquí vamos a ver todos los despliegues que hacemos. En nuestro caso es el primero y podemos ver que se ha creado correctamente. En caso de que veas algún error si haces clic en "error" puedes ver una descripción del mismo. +Si no vemos ningún error entonces significa que el proyecto ya está desplegado. + +Esto concluye nuestro proceso de despliegue de proyecto n8n con modo worker. + +## Configuración CI/CD (Opcional pero Recomendado) + +### ¿Por qué configurar CI/CD? + +Sin CI/CD, cada cambio en tu código requiere: + +1. Build manual desde SleakOps +2. Despliegue manual +3. Verificación manual + +Con CI/CD configurado: + +- ✅ Push a `main` → Despliegue automático +- ✅ Rollback automático en caso de error +- ✅ Notificaciones de estado de despliegue + +### Pasos de configuración: + +1. Ve a tu proyecto en SleakOps +2. Haz clic en ⚙️ (configuración) +3. Selecciona "Git pipelines" +4. Copia el archivo YAML proporcionado +5. Agrega `SLEAKOPS_KEY` a tus secrets de GitHub + + + click-settings-project-reference + + + + click-git-pipelines-reference + + +Esto requiere una variable de entorno llamada SLEAKOPS_KEY. Si no la tienes, ve al enlace proporcionado en **Settings -> CLI**, obténla y guárdala como una variable de entorno. + +Con esto configurado y desplegado, cada vez que hagas push a tu rama "main", se lanzará automáticamente una nueva versión de tu aplicación. + +## 🎯 Próximos Pasos + +Una vez completada la instalación: + +### Configuración Inicial de n8n + +1. **Primer Acceso**: Usa la URL de tu servicio web +2. **Crear Usuario Administrador**: n8n te pedirá crear el primer usuario +3. **Configurar Webhooks**: Si es necesario, configura las URLs públicas + +### Monitoreo y Optimización + +1. **Revisar Métricas**: Usa el dashboard integrado de Grafana +2. **Ajustar Recursos**: Modifica CPU/memoria basado en el uso real +3. **Configurar Alertas**: Define umbrales de rendimiento + +### Backup y Seguridad + +1. **Backups Automáticos**: Configura backups de PostgreSQL +2. **Gestión de Secretos**: Revisa la gestión de credenciales +3. **Actualizaciones**: Programa actualizaciones regulares + +## Actualizar y Extender n8n + +Ahora tenemos nuestro propio n8n instalado y ejecutándose en el clúster. Tenemos nuestra definición de n8n en un Dockerfile. + +#### Para actualizar la versión + +Este proceso es muy simple. Modificaremos el Dockerfile y cambiaremos el tag de la imagen. Puedes ver las imágenes disponibles en el repositorio oficial de n8n en Docker Hub. + +Nota: Lee el changelog por si hay cambios disruptivos o algo que pueda romperse entre versiones. Haz backups de la base de datos antes, por si acaso. + +#### Para agregar nuevas dependencias a tus nodos + +Como hicimos para actualizar la versión, en este caso aprovecharemos tener nuestro Dockerfile e instalaremos lo que queramos dentro de él. Esto estará disponible para usar en nuestros nodos de n8n. + +Puedes ver ejemplos de esto en el README del repositorio. + +## Mejores Prácticas de Escalado (Bonus) + +Una vez que tu despliegue de n8n esté funcionando, considera estas estrategias de escalado: + +### 🎯 **Optimización de Workers** + +- **Monitoreo de Cola**: Monitoriza la profundidad de la cola de Redis para determinar cuándo escalar workers. +- **Asignación de Recursos**: Asigna suficiente CPU y memoria basado en la complejidad del workflow. +- **Ajuste de Concurrencia**: Ajusta la concurrencia de workers basado en tipos de workflow (intensivo en CPU vs. I/O). +- **Workers Dedicados**: Crea pools de workers especializados para diferentes categorías de workflow. + +### 📈 **Monitoreo de Rendimiento** + +Ajusta la memoria y CPU de tus workloads a lo que tus procesos realmente necesitan. + +Esto es útil para evitar infraestructura sobredimensionada y también para tomar decisiones al escalar horizontalmente basado en memoria o CPU. + +#### ¿Cómo lo hacemos desde Sleakops? + +Simple, ve a los detalles de tu worker o servicio web que creamos anteriormente y haz clic en el ícono "Grafana". Esto abrirá un dashboard dentro de Grafana mostrando el consumo histórico de tu proceso. Asegúrate de ver un rango de tiempo largo para cubrir todos tus escenarios. + + + click-deployments-reference + + +### 🔧 **Optimización de Base de Datos** + +- **Connection Pooling**: Configura pools de conexiones PostgreSQL para alta concurrencia. + +- **Read Replicas**: Usa read replicas para consultas de reporting y analytics. (Esto se puede hacer desde Sleakops en la configuración de [Postgres](/project/dependency/postgresql-aws).) +- **Indexing**: Optimiza índices de base de datos para consultas de ejecución de workflow. +- **Backup Strategies**: Implementa backups automatizados con recuperación en un punto específico del tiempo. (Esto se puede hacer desde Sleakops en la configuración de [Postgres](/project/dependency/postgresql-aws).) + +### 🚀 **Configuraciones Avanzadas** + +- **Node Affinity**: Programa workers en tipos de nodos apropiados (optimizados para CPU vs. memoria). (Puedes hacer esto desde Sleakops usando [Nodepools](/cluster/nodepools)) +- **Pod Disruption Budgets**: Garantiza disponibilidad mínima durante mantenimiento del clúster. (Sleakops ya maneja esto) +- **Resource Quotas**: Establece límites apropiados para prevenir agotamiento de recursos. (Puedes hacer esto desde Sleakops definiendo límites en tus Workloads y Nodepools) +- **Network Policies**: Garantiza comunicación entre pods. (Sleakops ya maneja esto) diff --git a/content/tutorials/es/s3-batch.mdx b/content/tutorials/es/s3-batch.mdx new file mode 100644 index 00000000..badece92 --- /dev/null +++ b/content/tutorials/es/s3-batch.mdx @@ -0,0 +1,95 @@ +--- +sidebar_label: "S3 Batch" +sidebar_position: 7 +title: "S3 Batch" +description: "S3 Batch" +tags: + - S3 + - batch-operations + - data-migration + - cross-account + - aws + - storage +image: /img/tutorials/s3-batch/s3-batch.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; +import { FiExternalLink } from "react-icons/fi"; + +Aprende cómo usar S3 Batch Operations para copiar grandes volúmenes de objetos entre buckets S3, incluyendo configuraciones cross-account. Esta guía te ayudará a migrar datos de manera eficiente y escalable. + +## 1. Habilitar y configurar un inventario o manifest (lista de objetos) + +### Crear un inventario S3 (opcional, pero recomendado) + +- En la consola de **Amazon S3**, selecciona el bucket de origen. +- En la sección "Management" (o "Administración"), crea un **S3 Inventory** que genere un reporte periódico (CSV o Parquet) de todos los objetos. +- Verifica que el inventario incluya la información de "Object version" (si corresponde) y "ETag". + +### O usar un manifest propio (CSV personalizado) + +- Alternativamente, puedes crear tu propio archivo CSV con la siguiente estructura en cada línea: + +```csv +s3://NOMBRE_BUCKET_ORIGEN/objeto1.txt +s3://NOMBRE_BUCKET_ORIGEN/objeto2.txt +... +``` + +- Sube este archivo CSV (manifest) a un bucket S3 al que tengas acceso. + +:::info Nota +Este inventario o CSV es el "manifest" que utilizará S3 Batch para saber qué objetos copiar. +::: + +## 2. Configurar permisos y roles en la cuenta de origen y destino + +### Rol de ejecución del S3 Batch + +- En la cuenta **de origen**, crea un IAM Role que permita a S3 Batch Operations (servicio `batchoperations.s3.amazonaws.com`) leer el bucket de origen y, a la vez, escribir en el bucket de destino. +- Asegúrate de que en la política esté incluida la **acción `s3:GetObject`** para el bucket de origen y **`s3:PutObject`** para el bucket de destino. + +### Política en el bucket de destino (cross-account) + +- Si el bucket de destino está en otra cuenta, agrega una política de bucket que permita la acción `s3:PutObject` para el ARN del rol IAM del paso anterior. + +## 3. Crear la tarea (Job) de S3 Batch Operations + +### Configuración básica del Job + +1. **Ingresar a la consola S3** y seleccionar **Batch Operations** en el menú lateral. +2. **Crear un nuevo Job** con la siguiente configuración básica: + - **Manifest**: Indica dónde está el inventario o CSV (manifest) que contiene la lista de objetos. + - **Operation**: Selecciona **Copy**. + - **Destination Bucket**: Elige el bucket de destino (en la otra cuenta). + - **IAM Role**: Selecciona el rol creado para este propósito (paso 2.1). + +### Opciones adicionales (opcional) + +- **Storage Class**: Selecciona la clase de almacenamiento que desees en el bucket de destino (Standard, IA, etc.). +- **Object Tags**: Si quieres replicar o modificar etiquetas en el proceso. +- **Retention/Legal Hold**: Si aplica compliance. + +### Revisar y crear Job + +- Verifica que los ajustes sean correctos y lanza el Job. + +## 4. Monitorear el proceso + +1. En la consola de **S3 Batch Operations**, ubica tu Job y revisa el estado. +2. Según el volumen de objetos, la copia puede demorar desde minutos hasta varias horas/días (para millones de archivos). +3. Revisa los reportes de progreso y posibles errores (por ejemplo, objetos con acceso denegado). + +## 5. Validar la transferencia + +1. **Conteo de objetos**: Verifica que el número total de archivos en el bucket de destino coincide con lo esperado. +2. **Logs de errores**: Consulta la salida de errores o revisa CloudTrail/S3 Logs para objetos que no se hayan copiado correctamente. +3. **Reejecutar para objetos fallidos**: Puedes generar un nuevo manifest con solo los objetos fallidos y lanzar otro Job. + +## Resumen de puntos clave + +- **Manifest**: Preparar correctamente el inventario o lista de objetos. +- **Permisos**: Asegurarse de tener un rol IAM con políticas que permitan `GetObject` en origen y `PutObject` en destino (cross-account). +- **Batch Job**: Configurar la operación de "Copy" con el rol correcto. +- **Monitoreo**: Revisar logs y reportes de S3 Batch y, si es necesario, reintentar objetos fallidos. diff --git a/content/tutorials/es/s3-replication.mdx b/content/tutorials/es/s3-replication.mdx new file mode 100644 index 00000000..dbf39779 --- /dev/null +++ b/content/tutorials/es/s3-replication.mdx @@ -0,0 +1,165 @@ +--- +sidebar_label: "Replicación S3" +sidebar_position: 9 +title: "Replicación S3" +description: "Configuración de replicación S3 entre cuentas" +tags: + - S3 + - replication + - AWS + - cross-account + - data-sync + - backup + - storage +image: /img/tutorial-img.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; +import { FiExternalLink } from "react-icons/fi"; + +Pasos para configurar el servicio de S3 replication para replicar archivos de un bucket a otro en diferentes cuentas. + +Como requisito es necesario tener en ambos buckets el versionado activo. + +## 1. Crear IAM Role en la cuenta donde está el bucket de origen + +### Trust Policy + +Necesitas una política de confianza que permita al servicio S3 asumir el rol: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "s3.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} +``` + +### Permissions Policy + +Una política de permisos que permita: + +- Leer objetos y metadatos del bucket de origen (Cuenta A). +- Poner (put) objetos en el bucket de destino (Cuenta B). + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ReadSourceBucket", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectAcl", + "s3:GetObjectVersion", + "s3:GetObjectVersionAcl" + ], + "Resource": "arn:aws:s3:::/*" + }, + { + "Sid": "WriteDestBucket", + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:PutObjectAcl", + "s3:ReplicateObject", + "s3:ReplicateDelete", + "s3:ReplicateTags", + "s3:GetObjectVersionTagging", + "s3:PutObjectVersionTagging" + ], + "Resource": "arn:aws:s3:::/*" + } + ] +} +``` + +## 2. Agregar política al bucket de destino + +Dentro del detalle del bucket de destino, ir a la pestaña de permisos y agregar la siguiente política: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AllowReplicationFromAccountA", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::role/" + }, + "Action": [ + "s3:PutObject", + "s3:PutObjectAcl", + "s3:ReplicateObject", + "s3:ReplicateDelete", + "s3:ReplicateTags" + ], + "Resource": ["arn:aws:s3:::/*"] + } + ] +} +``` + +## 3. Configurar la regla de replicación en el bucket de origen + +- En el detalle del bucket de origen, ir a la pestaña "Management" (o "Properties" según versión de la consola) y buscar la sección de **Replication**. +- Crear una nueva regla de replicación y definir: + - **Rule name**: Un nombre descriptivo. + - **Status**: Enabled (habilitada). + - **Source bucket**: El bucket actual (ya está seleccionado). + - **Prefix/Filter**: Puedes elegir replicar todo el bucket o solo un prefijo en particular. + - **Destination**: + - **Bucket**: especificar el **ARN** del bucket de destino en la Cuenta B. + - **IAM role**: elegir el rol que creaste en el primer paso, que permite la replicación. + +## Opcionales + +- Si se activa la opción de "Transfer to destination bucket owner" debe agregarse, tanto en AllowReplicationFromAccountA (política del bucket destino) como en WriteDestBucket (IAM role), la action: + `"s3:ObjectOwnerOverrideToBucketOwner"` + +## Formas de copiar archivos ya existentes + +Existen 3 maneras diferentes de copiar los archivos ya existentes del bucket: + +### 1. Hacerlo junto con la replicación + +Al activar la replicación, te da una opción para copiar todos los archivos existentes. + +### 2. Usar la opción de migración S3 que brinda Sleakops + +En el detalle de la dependencia de tipo S3, se puede encontrar esta función donde te guía paso a paso lo que se tiene que hacer. + +### 3. Usar el servicio de Batch Operation + +Una vez creada la regla de replicación, siguiendo estas guías: + +- [Batch Operations IAM role + policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/batch-ops-iam-role-policies.html) +- [Replication metrics and + events](https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication-metrics-events.html) + +Agregar a la política S3ReplicationRolePolicy las siguientes acciones: + +- `"s3:PutObjectTagging"` al `"Sid": "WriteDestBucket"` +- `"s3:GetObjectTagging"` y `"s3:ListBucket"` al `"Sid": "ReadSourceBucket"` + +```json +{ + "Sid": "ReadReportBucket", + "Effect": "Allow", + "Action": ["s3:GetObject", "s3:GetObjectVersion"], + "Resource": ["arn:aws:s3:::bucket-reports/*"] +} +``` + +Y agregar tanto a WriteDestBucket como SourceBucket el permiso `"s3:InitiateReplication"`. diff --git a/content/tutorials/es/third-party-integration-vpn.mdx b/content/tutorials/es/third-party-integration-vpn.mdx new file mode 100644 index 00000000..4a66abc3 --- /dev/null +++ b/content/tutorials/es/third-party-integration-vpn.mdx @@ -0,0 +1,190 @@ +--- +sidebar_label: "Integración VPN de Terceros" +sidebar_position: 8 +title: "Integración VPN de Terceros" +description: "Comparación de alternativas VPN en AWS" +tags: + - VPN + - AWS + - third-party + - networking + - connectivity + - cost-analysis + - transit-gateway +image: /img/tutorials/third-party-integration-vpn/third-party-integration-vpn.png +--- + +import Zoom from "react-medium-image-zoom"; +import "react-medium-image-zoom/dist/styles.css"; +import { FiExternalLink } from "react-icons/fi"; + +La elección entre estas tres alternativas se basa en el equilibrio entre **costos**, **escalabilidad** y **complejidad de gestión**: + +### Transit Gateway (~197 USD/mes en el escenario descrito) + +- Mayor costo fijo por attachment. +- Excelente opción para topologías más grandes, múltiples VPCs y escalabilidad con mínima complejidad de routing. + +### Site-to-Site VPN + EC2 (~80 USD/mes estimados) + +- Facilidad de configuración (solución nativa de AWS). +- Adecuada para un número moderado de túneles, aunque menos flexible que TGW para grandes topologías. + +### VPN on EC2 (StrongSwan + Nginx) (~20–21 USD/mes con 1 instancia, o ~40–42 USD/mes para HA) + +- Coste significativamente más bajo. +- Mayor complejidad de administración y mantenimiento (gestión de instancia, parches, failover manual). +- Adecuada si el tráfico total es bajo y si se cuenta con personal para operar/monitorizar la instancia. + +## Transit Gateway + +Actúa como un enrutador centralizado que permite la interconexión entre múltiples VPCs, redes on-premises y redes de terceros. + +Las conexiones VPN se establecen a través de túneles IPsec, que pueden configurarse para ofrecer alta disponibilidad y redundancia (generalmente se configuran dos túneles por conexión VPN para lograr failover automático). + + + vpn + + +### Análisis de costos + +**Hipótesis:** + +- **3 attachments** en el Transit Gateway, que corresponden por ejemplo a: + 1. VPC (Dev) + 2. VPN (Prod) + 3. VPN (Contingency) +- **730 horas** de uso mensuales (24/7). +- **2 GB de transferencia mensual** por cada attachment, totalizando **6 GB mensuales**. +- Tarifas de AWS (en la mayoría de las regiones): + - **0.09 USD/hora/attachment**. + - **0.002 USD/GB** de transferencia de datos. + +**Costos:** + +- **Costo attachments**: ~197.10 USD/mes +- **Costo data transfer**: ~0.01 USD/mes + +**Suma total**: ~197.11 USD/mes (se redondea a ~197.22 USD/mes en el ejemplo original). + +## VPN Site-to-Site + +Una conexión de Site-to-Site VPN ofrece dos túneles de VPN entre una virtual **private gateway** o una **transit gateway** del lado de AWS y una **customer gateway** en el lado remoto (on-premise). + +Dos túneles para automatic failover o mantenimientos que suele hacer AWS que podrían deshabilitar brevemente uno de los túneles —> [Site-to-Site VPN tunnel endpoint replacement](https://docs.aws.amazon.com/vpn/latest/s2svpn/endpoint-replacements.html) + + + vpn-2 + + + + vpn-3 + + +### Análisis de costos + +**Hipótesis:** + +- **3 conexiones (VPN)** (equivalentes a los 3 "attachments" que mencionaste: Dev, Main, Contingencia). +- Cada VPN es un túnel Site-to-Site gestionado por AWS. +- **Costo de Site-to-Site VPN**: 0.05 USD por hora por VPN +- **730 horas** mensuales (24/7). +- **2 GB de transferencia mensual** por cada VPN. + +**Costos:** + +- **VPN** (3 conexiones): ~109.50 USD +- **Transferencia de datos** (6 GB total): ~0.54 USD +- **Network Load Balancer**: ~20–25 USD + +**Suma total**: ~130–135 USD mensuales. + +## VPN on EC2 + +En esta solución, se levanta una instancia EC2 sobre la que se instala **StrongSwan** para establecer túneles IPsec y **Nginx** como proxy (normalmente para enrutar tráfico en la capa de aplicación hacia un Application Load Balancer u otros recursos de la VPC). + + + vpn-4 + + +### Análisis de costos + +**Hipótesis:** + +- **3 túneles (VPN)** configurados en la misma instancia (o en dos instancias para redundancia). +- **Instancia EC2** de tamaño pequeño, por ejemplo, **t3.small** (con costo aprox. 0.02–0.023 USD/h). + +**Costos:** + +- **EC2 + EBS**: ~18–20 USD/mes (1 instancia) +- **Transferencia de datos**: ~0.54 USD/mes + +**Suma total**: ~20–21 USD/mes (En caso de 2 instancias para HA => ~40–42 USD/mes.) + +Configuración de nginx y ipsec para lograr armar la conexión. + +**nginx.conf** + +```nginx +load_module /usr/lib/nginx/modules/ngx_stream_module.so; +worker_processes 1; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + keepalive_timeout 65; + server_tokens off; +} + +stream { + server { + listen 8180; + proxy_pass ****; + } +} +``` + +**iptables.conf** + +```bash +*mangle +:PREROUTING ACCEPT [8165:7991805] +:INPUT ACCEPT [7883:7958068] +:FORWARD ACCEPT [282:33737] +:OUTPUT ACCEPT [5933:572312] +:POSTROUTING ACCEPT [6215:606049] +COMMIT + +*nat +:PREROUTING ACCEPT [159:9540] +:INPUT ACCEPT [159:9540] +:OUTPUT ACCEPT [168:10720] +:POSTROUTING ACCEPT [168:10720] +-A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination :22 +-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination :443 +-A POSTROUTING -p tcp -m tcp --dport 22 -j SNAT --to-source +-A POSTROUTING -p tcp -m tcp --dport 443 -j SNAT --to-source +COMMIT + +*filter +:INPUT ACCEPT [6016:538920] +:FORWARD ACCEPT [123:22565] +:OUTPUT ACCEPT [4614:432344] +-A FORWARD -d /32 -p tcp -m tcp --dport 443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -d /32 -p tcp -m tcp --dport 22 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -d /32 -p tcp -m tcp --dport 44301 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -d /32 -p tcp -m tcp --dport 22 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -d /32 -p tcp -m tcp --dport 8180 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +COMMIT +``` diff --git a/src/components/Homepage/RecentChangelog.jsx b/src/components/Homepage/RecentChangelog.jsx index eb6dd93a..26c2309d 100644 --- a/src/components/Homepage/RecentChangelog.jsx +++ b/src/components/Homepage/RecentChangelog.jsx @@ -20,7 +20,7 @@ const changelogData = [ version: "2.3.2", date: "2025-12-19", type: "feature", - title: "SleakOps CLI & Multi-cloud", + title: "SleakOps CLI", description: "New CLI features for local workload shell, S3 with CloudFront improvements, and API performance optimizations.", slug: "v2-3-2", diff --git a/src/data/tutorials-generated.json b/src/data/tutorials-generated.json index 526efa7a..71a81af0 100644 --- a/src/data/tutorials-generated.json +++ b/src/data/tutorials-generated.json @@ -144,6 +144,22 @@ } ], "es": [ + { + "id": "n8n-worker", + "title": "n8n + Worker Mode", + "description": "Aprende cómo desplegar tu proyecto n8n con modo worker distribuido y escalable en Kubernetes usando Sleakops", + "tags": [ + "n8n", + "kubernetes", + "worker", + "scaling", + "automation", + "background-jobs", + "deployment" + ], + "image": "/img/tutorials/n8n-worker/n8n-worker.png", + "sidebar_position": 2 + }, { "id": "config-aws-waf", "title": "Configurar AWS WAF", @@ -159,6 +175,116 @@ ], "image": "/img/tutorials/config-aws-waf/config-aws-waf.png", "sidebar_position": 3 + }, + { + "id": "make-rds-public", + "title": "Hacer pública base de datos RDS", + "description": "Aprende cómo hacer una base de datos RDS públicamente accesible usando un método workaround", + "tags": [ + "rds", + "database", + "aws", + "security", + "networking", + "vpc", + "postgresql" + ], + "image": "/img/tutorials/make-rds-public/make-rds-public.png", + "sidebar_position": 4 + }, + { + "id": "dashboard-loki-not-responding", + "title": "Dashboard Loki not responding", + "description": "Dashboard Loki not responding", + "tags": [ + "addons", + "loki", + "troubleshooting", + "monitoring", + "grafana", + "logs" + ], + "image": "/img/tutorial-img.png", + "sidebar_position": 5 + }, + { + "id": "install-keda", + "title": "Instalar KEDA", + "description": "Tutorial: instalar KEDA", + "tags": [ + "tutorial", + "install", + "keda", + "autoscaling", + "kubernetes", + "event-driven", + "scaling" + ], + "image": "/img/tutorials/install-keda/install-keda.png", + "sidebar_position": 6 + }, + { + "id": "s3-batch", + "title": "S3 Batch", + "description": "S3 Batch", + "tags": [ + "S3", + "batch-operations", + "data-migration", + "cross-account", + "aws", + "storage" + ], + "image": "/img/tutorials/s3-batch/s3-batch.png", + "sidebar_position": 7 + }, + { + "id": "third-party-integration-vpn", + "title": "Integración VPN de Terceros", + "description": "Comparación de alternativas VPN en AWS", + "tags": [ + "VPN", + "AWS", + "third-party", + "networking", + "connectivity", + "cost-analysis", + "transit-gateway" + ], + "image": "/img/tutorials/third-party-integration-vpn/third-party-integration-vpn.png", + "sidebar_position": 8 + }, + { + "id": "s3-replication", + "title": "Replicación S3", + "description": "Configuración de replicación S3 entre cuentas", + "tags": [ + "S3", + "replication", + "AWS", + "cross-account", + "data-sync", + "backup", + "storage" + ], + "image": "/img/tutorial-img.png", + "sidebar_position": 9 + }, + { + "id": "django-celery", + "title": "Django + Celery", + "description": "Aprende cómo desplegar tu proyecto Django + Celery con modo worker distribuido y escalable en Kubernetes usando Sleakops", + "tags": [ + "django", + "celery", + "deploy", + "python", + "background-jobs", + "kubernetes", + "scaling" + ], + "image": "/img/tutorials/django-celery/django-celery.png", + "sidebar_position": 10 } ] } \ No newline at end of file