Despliega tu aplicación Node.js
Requisitos previos
- Completa todas las secciones anteriores de esta guía, comenzando con Contenerizar una aplicación Node.js.
- Activa Kubernetes en Docker Desktop.
Descripción general
En esta sección, aprenderás cómo desplegar tu aplicación Node.js contenerizada en Kubernetes usando Docker Desktop. Este despliegue utiliza configuraciones listas para producción que incluyen endurecimiento de seguridad, autoescalado, almacenamiento persistente y características de alta disponibilidad.
Desplegarás una pila (stack) completa que incluye:
- Aplicación de tareas (Todo) en Node.js con 3 réplicas.
- Base de datos PostgreSQL con almacenamiento persistente.
- Autoescalado basado en el uso de CPU y memoria.
- Configuración de Ingress para el acceso externo.
- Ajustes de seguridad.
Crea un archivo de despliegue de Kubernetes
Crea un nuevo archivo llamado nodejs-sample-kubernetes.yaml en la raíz de tu proyecto:
# ========================================
# Aplicación de tareas (Todo) en Node.js - Despliegue de Kubernetes
# ========================================
apiVersion: v1
kind: Namespace
metadata:
name: todoapp
labels:
app: todoapp
---
# ========================================
# ConfigMap para la configuración de la aplicación
# ========================================
apiVersion: v1
kind: ConfigMap
metadata:
name: todoapp-config
namespace: todoapp
data:
NODE_ENV: 'production'
ALLOWED_ORIGINS: 'https://tudominio.com'
POSTGRES_HOST: 'todoapp-postgres'
POSTGRES_PORT: '5432'
POSTGRES_DB: 'todoapp'
POSTGRES_USER: 'todoapp'
---
# ========================================
# Secret para las credenciales de la base de datos
# ========================================
apiVersion: v1
kind: Secret
metadata:
name: todoapp-secrets
namespace: todoapp
type: Opaque
data:
postgres-password: dG9kb2FwcF9wYXNzd29yZA== # "todoapp_password" codificado en base64
---
# ========================================
# PersistentVolumeClaim de PostgreSQL
# ========================================
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: todoapp
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
---
# ========================================
# Despliegue de PostgreSQL (Deployment)
# ========================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: todoapp-postgres
namespace: todoapp
labels:
app: todoapp-postgres
spec:
replicas: 1
selector:
matchLabels:
app: todoapp-postgres
template:
metadata:
labels:
app: todoapp-postgres
spec:
containers:
- name: postgres
image: postgres:18-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: todoapp-config
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: todoapp-config
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: todoapp-secrets
key: postgres-password
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql
livenessProbe:
exec:
command:
- pg_isready
- -U
- todoapp
- -d
- todoapp
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- todoapp
- -d
- todoapp
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
---
# ========================================
# Servicio de PostgreSQL (Service)
# ========================================
apiVersion: v1
kind: Service
metadata:
name: todoapp-postgres
namespace: todoapp
labels:
app: todoapp-postgres
spec:
type: ClusterIP
ports:
- port: 5432
targetPort: 5432
protocol: TCP
name: postgres
selector:
app: todoapp-postgres
---
# ========================================
# Despliegue de la aplicación (Deployment)
# ========================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: todoapp-deployment
namespace: todoapp
labels:
app: todoapp
spec:
replicas: 3
selector:
matchLabels:
app: todoapp
template:
metadata:
labels:
app: todoapp
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 1001
containers:
- name: todoapp
image: ghcr.io/tu-nombre-de-usuario/docker-nodejs-sample:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
name: http
protocol: TCP
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: todoapp-config
key: NODE_ENV
- name: ALLOWED_ORIGINS
valueFrom:
configMapKeyRef:
name: todoapp-config
key: ALLOWED_ORIGINS
- name: POSTGRES_HOST
valueFrom:
configMapKeyRef:
name: todoapp-config
key: POSTGRES_HOST
- name: POSTGRES_PORT
valueFrom:
configMapKeyRef:
name: todoapp-config
key: POSTGRES_PORT
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: todoapp-config
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: todoapp-config
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: todoapp-secrets
key: postgres-password
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: '256Mi'
cpu: '250m'
limits:
memory: '512Mi'
cpu: '500m'
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
---
# ========================================
# Servicio de la aplicación (Service)
# ========================================
apiVersion: v1
kind: Service
metadata:
name: todoapp-service
namespace: todoapp
labels:
app: todoapp
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 3000
protocol: TCP
selector:
app: todoapp
---
# ========================================
# Ingress para acceso externo
# ========================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: todoapp-ingress
namespace: todoapp
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: 'letsencrypt-prod'
spec:
tls:
- hosts:
- tudominio.com
secretName: todoapp-tls
rules:
- host: tudominio.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: todoapp-service
port:
number: 80
---
# ========================================
# HorizontalPodAutoscaler
# ========================================
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: todoapp-hpa
namespace: todoapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: todoapp-deployment
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
---
# ========================================
# PodDisruptionBudget
# ========================================
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: todoapp-pdb
namespace: todoapp
spec:
minAvailable: 1
selector:
matchLabels:
app: todoappConfigura el despliegue
Antes de realizar el despliegue, debes personalizar el archivo de despliegue para tu entorno:
Referencia de la imagen: Reemplaza
tu-nombre-de-usuariocon tu nombre de usuario de GitHub o Docker Hub:image: ghcr.io/tu-nombre-de-usuario/docker-nodejs-sample:latestNombre de dominio: Reemplaza
tudominio.compor tu dominio real en dos lugares:# En el ConfigMap ALLOWED_ORIGINS: "https://tudominio.com" # En el Ingress - host: tudominio.comContraseña de la base de datos (opcional): La contraseña predeterminada ya está codificada en base64. Para cambiarla:
$ echo -n "tu-nueva-contraseña" | base64Luego actualiza el Secret:
data: postgres-password: <tu-contraseña-codificada-en-base64>Clase de almacenamiento (Storage class): Ajústala según tu clúster (actualmente:
standard).
Entiende el despliegue
El archivo de despliegue crea una pila de aplicación completa con múltiples componentes trabajando en conjunto.
Arquitectura
El despliegue incluye:
- Aplicación Node.js: Ejecuta 3 réplicas de tu aplicación de tareas contenerizada.
- Base de datos PostgreSQL: Instancia única con 10Gi de almacenamiento persistente.
- Servicios (Services): Los servicios de Kubernetes gestionan el balanceo de carga entre las réplicas de la aplicación.
- Ingress: Acceso externo a través de un controlador de Ingress con soporte SSL/TLS.
Seguridad
El despliegue utiliza varias características de seguridad:
- Los contenedores se ejecutan como un usuario no root (UID 1001).
- El sistema de archivos raíz de solo lectura (read-only root filesystem) evita escrituras no autorizadas.
- Se eliminan las capacidades de Linux para minimizar la superficie de ataque.
- Los datos confidenciales, como las contraseñas de la base de datos, se almacenan en Kubernetes Secrets.
Alta disponibilidad
Para mantener tu aplicación ejecutándose de forma confiable:
- Tres réplicas de la aplicación garantizan la continuidad del servicio si falla un pod.
- El presupuesto de interrupción de pods (Pod disruption budget) mantiene al menos un pod disponible durante las actualizaciones.
- Las actualizaciones progresivas (rolling updates) permiten despliegues sin tiempo de inactividad.
- Las comprobaciones de estado (health checks) en el endpoint
/healthaseguran que solo los pods saludables reciban tráfico.
Autoescalado
El Horizontal Pod Autoscaler escala tu aplicación basándose en el uso de recursos:
- Escala de manera automática entre 1 y 5 réplicas.
- Activa el escalado cuando el uso de CPU supera el 70%.
- Activa el escalado cuando el uso de memoria supera el 80%.
- Límites de recursos: 256Mi-512Mi de memoria, 250m-500m de CPU por pod.
Persistencia de datos
Los datos de PostgreSQL se almacenan de manera persistente:
- Un volumen persistente de 10Gi almacena los archivos de la base de datos.
- La base de datos se inicializa automáticamente en el primer arranque.
- Los datos persisten a través de reinicios y actualizaciones de los pods.
Despliega tu aplicación
Paso 1: Despliega en Kubernetes
Despliega tu aplicación en el clúster local de Kubernetes:
$ kubectl apply -f nodejs-sample-kubernetes.yaml
Deberías ver una salida que confirme que se han creado todos los recursos:
namespace/todoapp created
secret/todoapp-secrets created
configmap/todoapp-config created
persistentvolumeclaim/postgres-pvc created
deployment.apps/todoapp-postgres created
service/todoapp-postgres created
deployment.apps/todoapp-deployment created
service/todoapp-service created
ingress.networking.k8s.io/todoapp-ingress created
poddisruptionbudget.policy/todoapp-pdb created
horizontalpodautoscaler.autoscaling/todoapp-hpa createdPaso 2: Verifica el despliegue
Comprueba que tus despliegues se estén ejecutando:
$ kubectl get deployments -n todoapp
Salida esperada:
NAME READY UP-TO-DATE AVAILABLE AGE
todoapp-deployment 3/3 3 3 30s
todoapp-postgres 1/1 1 1 30sVerifica que se hayan creado tus servicios:
$ kubectl get services -n todoapp
Salida esperada:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
todoapp-service ClusterIP 10.111.101.229 <none> 80/TCP 45s
todoapp-postgres ClusterIP 10.111.102.130 <none> 5432/TCP 45sComprueba que el almacenamiento persistente esté funcionando:
$ kubectl get pvc -n todoapp
Salida esperada:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
postgres-pvc Bound pvc-12345678-1234-1234-1234-123456789012 10Gi RWO standard 1mPaso 3: Accede a tu aplicación
Para realizar pruebas locales, utiliza el reenvío de puertos (port forwarding) para acceder a tu aplicación:
$ kubectl port-forward -n todoapp service/todoapp-service 8080:80
Abre tu navegador y visita http://localhost:8080 para ver tu aplicación de tareas ejecutándose en Kubernetes.
Paso 4: Prueba el despliegue
Prueba que tu aplicación esté funcionando correctamente:
Agrega algunas tareas a través de la interfaz web.
Comprueba los pods de la aplicación:
$ kubectl get pods -n todoapp -l app=todoappVisualiza los logs de la aplicación:
$ kubectl logs -f deployment/todoapp-deployment -n todoappComprueba la conectividad de la base de datos:
$ kubectl get pods -n todoapp -l app=todoapp-postgresMonitorea el autoescalado:
$ kubectl describe hpa todoapp-hpa -n todoapp
Paso 5: Limpieza
Cuando hayas terminado con las pruebas, elimina el despliegue:
$ kubectl delete -f nodejs-sample-kubernetes.yaml
Resumen
Has desplegado tu aplicación Node.js contenerizada en Kubernetes. Aprendiste a:
- Crear un archivo de despliegue de Kubernetes completo con endurecimiento de seguridad.
- Desplegar una aplicación de múltiples niveles (Node.js + PostgreSQL) con almacenamiento persistente.
- Configurar autoescalado, comprobaciones de estado y características de alta disponibilidad.
- Probar y monitorear tu despliegue localmente utilizando el Kubernetes integrado en Docker Desktop.
Tu aplicación ahora se está ejecutando en un entorno similar al de producción con características de nivel empresarial, incluidos contextos de seguridad, gestión de recursos y escalado automático.
Recursos relacionados
Explora referencias oficiales y mejores prácticas para perfeccionar tu flujo de trabajo de despliegue en Kubernetes:
- Documentación de Kubernetes – Conoce los conceptos clave, cargas de trabajo, servicios y más.
- Despliegue en Kubernetes con Docker Desktop – Utiliza el soporte integrado de Kubernetes de Docker Desktop para pruebas y desarrollo locales.
- Referencia de CLI de
kubectl– Gestiona clústeres de Kubernetes desde la línea de comandos. - Recurso Deployment de Kubernetes – Comprende cómo gestionar y escalar aplicaciones usando Deployments.
- Recurso Service de Kubernetes – Aprende cómo exponer tu aplicación al tráfico interno y externo.