Orquestación de Contenedores con Docker Compose y Kubernetes

Docker Compose

Docker Compose permite definir y ejecutar aplicaciones multi-contenedor mediante archivos YAML. Una estructura típica de proyecto puede organizarse en múltiples archivos según el entorno:


mi-proyecto/
├── compose-core.yml          # Configuración base
├── compose-apps.yml          # Definición de servicios
├── compose-dev.yml           # Sobrescritura para desarrollo
├── compose-staging.yml       # Sobrescritura para staging
└── .env                      # Variables de entorno

Para iniciar servicios combinando varios archivos de configuración:


# Combinar base con un entorno específico
docker-compose -f compose-core.yml -f compose-dev.yml up -d

# Combinación múltiple con redes y volúmenes separados
docker-compose \
  -f compose-core.yml \
  -f compose-apps.yml \
  -f compose-volumes.yml \
  -f compose-networks.yml \
  up -d

Ejemplo de configuración de servicios:


version: '3.8'
services:
  # Servidor web frontal con Nginx
  portal-web:
    container_name: portal-web
    image: portal-frontend:1.2.0
    ports:
      - "31080:80"
    volumes:
      - ./portal/nginx.conf:/etc/nginx/nginx.conf
      - ./portal/site.conf:/etc/nginx/conf.d/default.conf
    networks:
      - app_network
    restart: unless-stopped

  # API principal del sistema
  portal-api:
    container_name: portal-api
    image: portal-backend:1.2.0
    environment:
      - TZ=Europe/Madrid
    ports:
      - "9090:9090"
    volumes:
      - ./portal-api/config:/app/config
      - ./portal-api/logs:/app/logs
      - ./portal-api/uploads:/app/uploads
      - /etc/localtime:/etc/localtime:ro
    networks:
      - app_network

  # Microservicio de recolección de datos
  portal-collector:
    container_name: portal-collector
    image: collector-svc:1.2.0
    environment:
      - TZ=Europe/Madrid
    ports:
      - "9095:9095"
    volumes:
      - ./collector/config:/app/config
      - ./collector/logs:/app/logs
      - ./collector/uploads:/app/uploads
      - /etc/localtime:/etc/localtime:ro
    networks:
      - app_network

networks:
  app_network:
    external: true   # La red debe existir previamente

Kubernetes

Cuando las aplicaciones crecen en complejidad, gestionar contenedores individualmente resulta insuficiente. La orquestación, escalado y recuperación automática requieren una plataforma de nivel superior. Kubernetes (K8s) es esa plataforma de gestión de clústeres basada en contenedores.

Un clúster de K8s se compone de dos tipos de nodos:

  • Nodo Master (Plano de control): Coordina el clúster y toma decisiones globales.
  • Nodos Worker: Ejecutan la carga de trabajo real, alojando los contenedores.

El nodo Master incluye cuatro componentes clave:

  • kube-apiserver: Punto de entrada RESTful para todas las operaciones del clúster.
  • kube-scheduler: Asigna Pods a nodos según recursos y restricciones.
  • kube-controller-manager: Ejecuta bucles de control que mantienen el estado deseado.
  • etcd: Almacén clave-valor consistente que guarda el estado del clúster.

Los nodos Worker incluyen:

  • Container Runtime: Ejecuta los contenedores (containerd, CRI-O, etc.).
  • kubelet: Agente que registra el nodo y gestiona el ciclo de vida de los Pods asignados.
  • kube-proxy: Mantiene reglas de red para comunicación entre Pods y servicios.
  • Fluentd: Daemon de recolección de logs (opcional).

El Pod es la unidad atómica de despliegue en K8s. Encapsula uno o varios contenedores que comparten red y almacenamiento. El Service actúa como una abstracción que ofrece un punto de acceso estable y balanceado hacia un conjunto de Pods.

Campos obligatorios en manifiestos YAML de K8s

  • apiVersion: Versión del API utilizada (ej: apps/v1, v1)
  • kind: Tipo de recurso (Deployment, Service, ConfigMap, etc.)
  • metadata: Nombre, namespace, labels y annotations
  • spec: Especificación detallada del estado deseado

Recursos principales:

  • Deployment: Gestiona aplicaciones stateless declarando el número de réplicas y la estrategia de actualización. Internamente crea ReplicaSets.
  • Service: Provee descubrimiento de servicios y balanceo de carga para un conjunto de Pods.
  • ConfigMap: Almacena configuración no sensible, utilizable como archivos montados o variables de entorno.
  • Secret: Guarda información confidencial codificada en Base64 (no es cifrado).
  • PersistentVolumeClaim (PVC): Solicita almacenamiento persistente al clúster.

Estructura de directorios y despliegue


k8s-manifests/
├── frontend/
│   ├── deployment.yaml
│   └── service.yaml
├── api/
│   ├── deployment.yaml
│   └── service.yaml
└── database/
    ├── statefulset.yaml
    └── service-headless.yaml

# Aplicar todo el directorio (orden alfabético)
kubectl apply -f k8s-manifests/

# Aplicar un componente específico
kubectl apply -f k8s-manifests/frontend/
kubectl apply -f k8s-manifests/api/

Manifiesto de ejemplo


# Despliegue de una aplicación web con 3 réplicas
# y exposición mediante NodePort
kubectl apply -f web-portal.yaml
# Acceso: http://<NodeIP>:31080

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-portal
  labels:
    tier: frontend
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
        - name: nginx-server
          image: nginx:1.25-alpine
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "250m"
              memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
  name: web-portal-svc
spec:
  type: NodePort
  selector:
    tier: frontend
  ports:
    - name: http
      port: 80
      targetPort: 80
      nodePort: 31080

Kubernetes permite organizar los manifiestos de varias formas: en un único archivo YAML separanod recursos con ---, o distribuyendo cada componente en archivos independientes por dominio funcional. Ambos enfoques son válidos y la elección depende del tamaño del equipo y la complejidad del proyecto.

Etiquetas: Docker Compose Kubernetes K8s contenedores Orquestación

Publicado el 10-10 08:18