Kubernetes: Pods, Services, Deployments - Guía Completa

Comprender los Pods, Services y Deployments es fundamental para dominar Kubernetes. Estos recursos principales forman la base del despliegue y gestión de aplicaciones en clústeres de Kubernetes. Esta guía completa cubre conceptos, ejemplos prácticos y mejores prácticas de producción.

Tabla de Contenidos

Introducción

Kubernetes orquesta aplicaciones en contenedores utilizando varios recursos clave:

  • Pods: Unidades más pequeñas desplegables, encapsulando uno o más contenedores
  • Services: Endpoints de red estables para acceder a los Pods
  • Deployments: Actualizaciones declarativas para Pods y ReplicaSets

Jerarquía de Recursos

Deployment
  └── ReplicaSet
        └── Pod(s)
              └── Container(s)

Requisitos Previos

  • Clúster de Kubernetes (kubeadm, minikube o proveedor de nube)
  • kubectl instalado y configurado
  • Conocimientos básicos de contenedores y Docker
  • Familiaridad con sintaxis YAML

Verificar configuración:

kubectl version --client
kubectl cluster-info
kubectl get nodes

Pods

Los Pods son la unidad atómica de despliegue en Kubernetes, representando uno o más contenedores estrechamente acoplados que comparten recursos.

Características del Pod

  • Efímeros y desechables
  • Comparten namespace de red (una sola IP)
  • Comparten volúmenes de almacenamiento
  • Se programan juntos en el mismo nodo
  • Gestionados por controladores de nivel superior

Creando un Pod Simple

# simple-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    environment: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.25-alpine
    ports:
    - containerPort: 80
# Crear pod
kubectl apply -f simple-pod.yaml

# Verificar estado del pod
kubectl get pods

# Describir pod
kubectl describe pod nginx-pod

# Eliminar pod
kubectl delete pod nginx-pod

Pod Multi-Contenedor

# multi-container-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web-app
spec:
  containers:
  - name: app
    image: myapp:latest
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: shared-data
      mountPath: /app/data

  - name: sidecar
    image: log-collector:latest
    volumeMounts:
    - name: shared-data
      mountPath: /logs

  volumes:
  - name: shared-data
    emptyDir: {}

Pod con Límites de Recursos

# pod-resources.yaml
apiVersion: v1
kind: Pod
metadata:
  name: resource-pod
spec:
  containers:
  - name: app
    image: nginx:alpine
    resources:
      requests:
        memory: "128Mi"
        cpu: "250m"
      limits:
        memory: "256Mi"
        cpu: "500m"

Pod con Variables de Entorno

# pod-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: env-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    env:
    - name: DATABASE_HOST
      value: "postgres.default.svc.cluster.local"
    - name: DATABASE_PORT
      value: "5432"
    - name: API_KEY
      valueFrom:
        secretKeyRef:
          name: api-credentials
          key: api-key

Ciclo de Vida del Pod

# Verificar fases del pod
kubectl get pods -w

# Fases del pod:
# Pending - Esperando programación
# Running - Pod programado, contenedores en ejecución
# Succeeded - Todos los contenedores terminaron exitosamente
# Failed - Al menos un contenedor falló
# Unknown - El estado del pod no se puede determinar

Services

Los Services proporcionan redes estables para acceder a los Pods, ofreciendo balanceo de carga y descubrimiento de servicios.

Tipos de Service

  • ClusterIP: Acceso solo dentro del clúster (predeterminado)
  • NodePort: Expone en la IP de cada nodo en un puerto estático
  • LoadBalancer: Balanceador de carga en la nube (requiere proveedor de nube)
  • ExternalName: Mapea a nombre DNS externo

Service ClusterIP

# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP
  selector:
    app: backend
    tier: api
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
# Crear service
kubectl apply -f service-clusterip.yaml

# Acceder desde dentro del clúster
kubectl run curl --image=curlimages/curl -it --rm -- sh
# curl http://backend-service

Service NodePort

# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080  # Opcional: 30000-32767
    protocol: TCP
# Crear service
kubectl apply -f service-nodeport.yaml

# Acceder desde fuera del clúster
curl http://<NODE_IP>:30080

Service LoadBalancer

# service-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: LoadBalancer
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 3000
    protocol: TCP
# Crear service
kubectl apply -f service-loadbalancer.yaml

# Obtener IP externa (puede tardar)
kubectl get service frontend-service

# Acceder vía IP externa
curl http://<EXTERNAL_IP>

Service con Afinidad de Sesión

# service-session.yaml
apiVersion: v1
kind: Service
metadata:
  name: sticky-service
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

Service Headless

# service-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: database-service
spec:
  clusterIP: None  # Service headless
  selector:
    app: database
  ports:
  - port: 5432
    targetPort: 5432

Deployments

Los Deployments proporcionan actualizaciones declarativas para Pods y ReplicaSets, habilitando escalado, rolling updates y rollbacks.

Deployment Básico

# deployment-basic.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
# Crear deployment
kubectl apply -f deployment-basic.yaml

# Verificar deployment
kubectl get deployments
kubectl get pods

# Escalar deployment
kubectl scale deployment nginx-deployment --replicas=5

# Eliminar deployment
kubectl delete deployment nginx-deployment

Deployment Listo para Producción

# deployment-production.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web
    environment: production
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
        version: v1.0.0
    spec:
      containers:
      - name: app
        image: myapp:1.0.0
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: ENVIRONMENT
          value: "production"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

Deployment con ConfigMap y Secret

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  database_url: "postgres://db:5432"
  log_level: "info"

---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  db_password: cGFzc3dvcmQxMjM=  # codificado en base64

---
# deployment-with-config.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: myapp:latest
        envFrom:
        - configMapRef:
            name: app-config
        env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: db_password

ReplicaSets

Los ReplicaSets aseguran que un número especificado de réplicas de Pod estén ejecutándose. Típicamente gestionados por Deployments.

Ejemplo de ReplicaSet

# replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
# Crear ReplicaSet
kubectl apply -f replicaset.yaml

# Verificar ReplicaSet
kubectl get replicasets
kubectl get pods

# Escalar ReplicaSet
kubectl scale replicaset frontend-replicaset --replicas=5

Labels y Selectors

Los Labels organizan y seleccionan objetos de Kubernetes. Los Selectors consultan objetos por labels.

Uso de Labels

# pod-with-labels.yaml
apiVersion: v1
kind: Pod
metadata:
  name: labeled-pod
  labels:
    app: web
    environment: production
    tier: frontend
    version: v1.2.3
spec:
  containers:
  - name: nginx
    image: nginx:alpine

Selectores de Labels

# Basados en igualdad
kubectl get pods -l app=web
kubectl get pods -l environment=production

# Basados en conjuntos
kubectl get pods -l 'environment in (production, staging)'
kubectl get pods -l 'tier notin (database)'

# Múltiples condiciones
kubectl get pods -l app=web,environment=production

# Mostrar labels
kubectl get pods --show-labels

Agregar/Eliminar Labels

# Agregar label
kubectl label pods labeled-pod new-label=value

# Actualizar label
kubectl label pods labeled-pod environment=staging --overwrite

# Eliminar label
kubectl label pods labeled-pod environment-

Rolling Updates y Rollbacks

Realizar Rolling Update

# Actualizar imagen del deployment
kubectl set image deployment/nginx-deployment nginx=nginx:1.26-alpine

# O actualizar vía edición
kubectl edit deployment nginx-deployment

# Observar estado del rollout
kubectl rollout status deployment/nginx-deployment

# Verificar historial del rollout
kubectl rollout history deployment/nginx-deployment

Estrategia de Actualización

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%        # Máximo de pods por encima del conteo deseado
      maxUnavailable: 25%  # Máximo de pods no disponibles durante actualización

Rollback de Deployment

# Revertir a versión anterior
kubectl rollout undo deployment/nginx-deployment

# Revertir a revisión específica
kubectl rollout history deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2

# Pausar rollout
kubectl rollout pause deployment/nginx-deployment

# Reanudar rollout
kubectl rollout resume deployment/nginx-deployment

Mejores Prácticas de Producción

Solicitudes y Límites de Recursos

spec:
  containers:
  - name: app
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

Health Checks

spec:
  containers:
  - name: app
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3

    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3

Pod Disruption Budgets

# pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web

Anti-Afinidad para Alta Disponibilidad

spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - web
          topologyKey: kubernetes.io/hostname

Contexto de Seguridad

spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: app
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL

Resolución de Problemas

Problemas con Pods

# Obtener detalles del pod
kubectl describe pod <pod-name>

# Ver logs
kubectl logs <pod-name>
kubectl logs <pod-name> --previous  # Contenedor anterior

# Ejecutar en pod
kubectl exec -it <pod-name> -- sh

# Verificar eventos
kubectl get events --sort-by='.lastTimestamp'

Problemas con Services

# Verificar endpoints del service
kubectl get endpoints <service-name>

# Probar resolución DNS
kubectl run test --image=busybox:1.28 --rm -it -- nslookup <service-name>

# Verificar conectividad del service
kubectl run curl --image=curlimages/curl --rm -it -- curl http://<service-name>

Problemas con Deployments

# Verificar estado del deployment
kubectl get deployment <deployment-name>
kubectl describe deployment <deployment-name>

# Verificar ReplicaSet
kubectl get rs
kubectl describe rs <replicaset-name>

# Verificar estado del rollout
kubectl rollout status deployment/<deployment-name>

Problemas Comunes

# ImagePullBackOff
kubectl describe pod <pod-name>  # Verificar nombre de imagen y credenciales

# CrashLoopBackOff
kubectl logs <pod-name>  # Verificar logs de la aplicación

# Pods pendientes
kubectl describe pod <pod-name>  # Verificar recursos del nodo y programación

# Service no accesible
kubectl get endpoints <service-name>  # Verificar que los pods estén seleccionados

Conclusión

Los Pods, Services y Deployments forman el núcleo de la gestión de aplicaciones en Kubernetes. Comprender estos recursos es esencial para desplegar aplicaciones escalables y resilientes.

Puntos Clave

  • Pods: Unidad más pequeña desplegable, efímera
  • Services: Endpoints de red estables, balanceo de carga
  • Deployments: Actualizaciones declarativas, escalado, rollbacks
  • Labels: Organizan y seleccionan recursos
  • Health Checks: Aseguran la fiabilidad de la aplicación
  • Límites de Recursos: Previenen el agotamiento de recursos

Referencia Rápida

# Pods
kubectl get pods
kubectl describe pod <name>
kubectl logs <name>
kubectl exec -it <name> -- sh
kubectl delete pod <name>

# Services
kubectl get services
kubectl describe service <name>
kubectl get endpoints <name>

# Deployments
kubectl get deployments
kubectl describe deployment <name>
kubectl scale deployment <name> --replicas=5
kubectl set image deployment/<name> container=image:tag
kubectl rollout status deployment/<name>
kubectl rollout undo deployment/<name>

# Labels
kubectl get pods --show-labels
kubectl get pods -l app=web
kubectl label pods <name> key=value

Próximos Pasos

  1. Práctica: Desplegar varias aplicaciones
  2. Monitoreo: Configurar Prometheus y Grafana
  3. Logging: Implementar logging centralizado
  4. Seguridad: Aplicar RBAC y políticas de seguridad de pods
  5. Redes: Configurar controladores Ingress
  6. Almacenamiento: Implementar volúmenes persistentes
  7. CI/CD: Automatizar despliegues

¡Domina estos fundamentos para construir aplicaciones robustas en Kubernetes!