Módulo 2: Pods Deployments And Services

2. Qué es un Pod, y por qué casi nunca se crea uno suelto

Descripción

Un Pod es la unidad más pequeña que Kubernetes sabe programar — no un contenedor, un Pod. La distinción parece técnica hasta que la entiendes bien: un Pod es un envoltorio alrededor de uno o más contenedores que comparten dos cosas que ningún contenedor comparte con otro por defecto — una red y, opcionalmente, almacenamiento. Esta lección instala ese concepto a fondo, con la intención de que llegues a la lección 4 (donde creas tu primer Pod de verdad) sabiendo exactamente qué estás creando y por qué.

Conexión con el módulo

Esta lección y la lección 4 (manos a la obra) son una sola unidad partida en dos: aquí entiendes el concepto, ahí lo confirmas con tus propias manos. Todo lo que construyes en el resto de este módulo —el Deployment de la lección 3, el Service de la lección 6— existe para administrar o exponer Pods, nunca para reemplazarlos: un Deployment no reemplaza a un Pod, crea y supervisa Pods.


Qué es, exactamente, un Pod

La definición oficial de Kubernetes es precisa y vale la pena citarla completa: un Pod es "el objeto desplegable más pequeño que puedes crear y administrar en Kubernetes", y contiene "uno o más contenedores, con recursos de red y almacenamiento compartidos, y una especificación de cómo correr los contenedores" — la definición completa está en la documentación oficial (ver Recursos). Tres palabras de esa definición merecen atención inmediata:

  • "Uno o más" contenedores. La mayoría de los Pods que vas a ver en esta guía —incluido andes-cargo-status-api— tienen exactamente un contenedor. Pero Kubernetes permite más de uno dentro del mismo Pod, para un caso de uso específico: un contenedor auxiliar (llamado sidecar) que le agrega una función al contenedor principal sin tocar su código — por ejemplo, un proceso que exporta métricas o sincroniza archivos. Esta guía no construye ningún Pod multi-contenedor (fuera de alcance, ver "Errores comunes"), pero necesitas saber que la posibilidad existe para no sorprenderte si la ves en otro lugar.
  • "Recursos de red... compartidos." Todos los contenedores dentro del mismo Pod comparten la misma dirección IP y el mismo espacio de puertos — se hablan entre sí por localhost, exactamente como si fueran procesos distintos en la misma máquina. Esta es la razón técnica de fondo por la que un patrón sidecar funciona: el contenedor auxiliar puede alcanzar al contenedor principal sin ninguna configuración de red adicional.
  • "Objeto desplegable más pequeño." No puedes pedirle a Kubernetes que programe "medio Pod" ni "un contenedor sin Pod alrededor" — todo lo que corre en un clúster de Kubernetes corre dentro de algún Pod, sin excepción. Cuando declaras un Deployment con replicas: 3 (lección 3), lo que ese Deployment termina creando, por debajo, son tres Pods — nunca "tres contenedores sueltos".

Por qué casi nunca se crea un Pod directamente

Aquí está el punto central de esta lección, y el que le da el nombre: en un clúster de producción real, casi nadie declara un objeto Pod a mano. La razón es simple y la vas a confirmar con evidencia en la lección 4: un Pod, por sí solo, no tiene ningún mecanismo de auto-reparación. Si el nodo donde corre falla, o si alguien lo borra, o si el proceso dentro se cae de una forma que ni siquiera un reinicio soluciona, nadie lo repone. Un Pod suelto es exactamente tan frágil como el contenedor solo de docker run que la lección 1 de este módulo describió — Kubernetes le agrega una IP propia y una forma estándar de describirlo, pero no le agrega, por sí mismo, ninguna supervisión.

Lo que sí agrega supervisión es un controlador de nivel superior —casi siempre un Deployment (lección 3)— que crea Pods según una plantilla, y los repone si alguno desaparece. La relación es de composición, no de reemplazo: un Deployment no es "un Pod mejorado", es un objeto separado que administra objetos Pod.

                    QUIÉN CREA QUÉ (jerarquía real de objetos)

  Deployment                    ← declaras esto (lección 3, lección 5)
      │
      │  crea y administra
      ▼
  ReplicaSet                    ← Kubernetes lo crea por ti (lección 3)
      │
      │  crea y administra
      ▼
  Pod, Pod, Pod...              ← lo que finalmente corre (esta lección, lección 4)
      │
      │  contiene
      ▼
  Contenedor(es)                ← lo que ya conocías de Docker

Entonces, ¿por qué esta lección —y la lección 4— te enseñan a crear un Pod suelto, si "casi nadie lo hace" en producción? Por la misma razón que un curso de manejo te enseña a manejar con la transmisión manual, aunque termines usando automática toda tu carrera: entender la pieza más simple, sin ninguna capa de administración encima, es lo que te permite entender exactamente qué agrega cada capa que sí vas a usar. La lección 4 te deja ver, con tus propias manos, que un Pod borrado desaparece para siempre — el contraste exacto que la lección 5 (el Deployment real) va a confirmar en sentido opuesto.


Cuándo sí tiene sentido crear un Pod suelto

No nunca — hay casos legítimos, aunque ninguno es "correr un servicio de producción":

  • Depuración rápida, cuando necesitas un contenedor temporal dentro del clúster para probar algo (por ejemplo, curl contra un Service desde dentro de la red del clúster, un patrón que vas a usar en la lección 7 de este mismo módulo).
  • Trabajos de un solo uso que corren hasta terminar y no necesitan reiniciarse (aunque, en la práctica, hasta esos casos suelen modelarse mejor con un objeto Job, que Kubernetes ofrece específicamente para esto y que está fuera del alcance de esta guía).
  • Aprendizaje, exactamente lo que vas a hacer en la lección 4 — la única forma de ver con claridad qué le falta a un Pod suelto es tener uno corriendo de verdad, sin nada más alrededor.

andes-cargo-status-api, el servicio real de esta guía, nunca se declara como un Pod suelto — desde la lección 5 en adelante, siempre vive dentro de un Deployment. Esa es la decisión que toda esta lección justifica.


Anatomía mínima de un Pod

Antes de la lección 4, vale la pena ver la forma general de un manifiesto de Pod, sin ejecutarlo todavía — la vas a reconocer de inmediato cuando llegues ahí:

apiVersion: v1
kind: Pod
metadata:
  name: <nombre-del-pod>
  labels:
    app: <etiqueta>
spec:
  containers:
    - name: <nombre-del-contenedor>
      image: <imagen:tag>
      ports:
        - containerPort: <puerto>

Cuatro campos merecen una nota antes de seguir:

  • apiVersion: v1 — los objetos más antiguos y estables de Kubernetes (Pod, Service, Namespace, ConfigMap, Secret) viven en el grupo de API "core", identificado simplemente como v1. Vas a ver grupos distintos —apps/v1 para Deployment, en la lección 3— a medida que los objetos son más recientes o más especializados.
  • kind: Pod — el mismo campo kind que ya viste en kind-config.yaml en el Módulo 1, ahora con un valor distinto. Le dice al kube-apiserver qué tipo de objeto está describiendo este documento.
  • metadata.labels — un par clave-valor arbitrario que le "pega una etiqueta" al objeto. No es decorativo: es el mecanismo exacto que un Service va a usar en la lección 6 y 7 para saber a qué Pods debe enrutar tráfico — sin una etiqueta que coincida, un Service no tiene forma de encontrar sus Pods.
  • spec.containers — una lista, no un solo valor, precisamente porque un Pod admite más de un contenedor (aunque, en esta guía, siempre vas a declarar exactamente uno).

Analogía: la oficina individual, no el edificio

Retomando la analogía del Módulo introductorio: si un Deployment es el termostato del edificio y un Service es la centralita, un Pod es la oficina individual — tiene todo lo que necesita para funcionar adentro (el contenedor, su propia dirección de red, cualquier almacenamiento que comparta con otro contenedor del mismo Pod), pero no decide por sí misma cuándo se ocupa, cuándo se desocupa, ni qué pasa si alguien la cierra sin avisar. Esas decisiones las toma el edificio —el Deployment— no la oficina. Una oficina sin ningún departamento de administración detrás (un Pod suelto) puede quedar vacía para siempre si alguien se va, sin que nadie lo note ni lo corrija — exactamente lo que vas a confirmar en la lección 4.


Profundización: el ciclo de vida de un Pod

Un Pod pasa por una secuencia de fases, visibles en la columna STATUS de kubectl get pods (la vas a ver de verdad en la lección 4):

  • Pending — el objeto ya existe en etcd, pero al menos uno de sus contenedores todavía no arrancó (por ejemplo, mientras la imagen se descarga).
  • Running — el Pod fue asignado a un nodo, y todos sus contenedores arrancaron (aunque no necesariamente están "listos" para recibir tráfico — esa es una distinción distinta, readiness, que profundizas en el Módulo 3).
  • Succeeded — todos los contenedores del Pod terminaron con éxito, y no se van a reiniciar. Poco común para un servicio HTTP como andes-cargo-status-api, que está diseñado para correr indefinidamente; más común en trabajos de un solo uso.
  • Failed — al menos un contenedor terminó con un código de error, y el Pod no se va a reintentar (según su restartPolicy).
  • Unknown — el estado del Pod no se pudo determinar, típicamente porque el nodo donde vive dejó de responder.

Un detalle importante que vas a confirmar en la lección 4: cuando borras un Pod con kubectl delete pod, no pasa por ninguna de estas fases de "error" — simplemente deja de existir. No hay un quinto estado "Deleted" que veas en kubectl get pods, porque el objeto ya no está ahí para reportar ningún estado.


Errores comunes

Pensar que "contenedor" y "Pod" son sinónimos intercambiables (conceptual, el más extendido en cualquier introducción a Kubernetes). Qué pasa: alguien usa "levanté un contenedor" y "levanté un Pod" como si fueran la misma frase, y esa confusión se vuelve un problema real cuando intenta entender por qué un Pod puede tener más de un contenedor adentro. Por qué pasa: en la inmensa mayoría de los casos prácticos —incluido cada ejemplo de esta guía— un Pod contiene exactamente un contenedor, así que la distinción parece innecesaria hasta que aparece un caso con dos. Cómo detectarlo: si te cuesta explicar por qué dos contenedores dentro del mismo Pod comparten la misma IP, mientras que dos Pods distintos nunca la comparten. Cómo corregirlo: un Pod es el envoltorio; un contenedor es lo que va adentro. Puedes tener un Pod con un contenedor (el caso de esta guía) o con varios (patrón sidecar, fuera de alcance aquí) — pero nunca un contenedor "sin" Pod en Kubernetes.

Esperar que Kubernetes reponga un Pod suelto automáticamente, porque "eso es lo que hace Kubernetes" (conceptual, el que esta lección existe específicamente para prevenir). Qué pasa: alguien crea un Pod directamente (sin Deployment), lo borra por accidente o lo pierde por una falla de nodo, y espera ver un Pod nuevo aparecer solo — como recuerda que pasó en algún tutorial que usaba un Deployment sin que se diera cuenta de la diferencia. Por qué pasa: la reputación de "Kubernetes se auto-repara" es real, pero es una propiedad de los controladores (Deployment, ReplicaSet, entre otros), no del kube-apiserver en general ni de un Pod individual. Cómo detectarlo: si borraste un Pod con kubectl delete pod y kubectl get pods sigue mostrando el resultado vacío varios minutos después, eso es exactamente el comportamiento correcto para un Pod suelto — no un error. Cómo corregirlo: la lección 4 te muestra este comportamiento con tus propias manos, a propósito, para que la distinción quede instalada antes de la lección 5.

Asumir que un Pod multi-contenedor es la forma normal de correr una aplicación con varias piezas (conceptual, un malentendido común en quien viene de Docker Compose). Qué pasa: alguien acostumbrado a docker-compose.yml, donde cada servicio (por ejemplo, una API y una base de datos) es un contenedor separado dentro del mismo archivo, asume que el equivalente en Kubernetes es meter ambos contenedores dentro del mismo Pod. Por qué pasa: el paralelo visual entre "varios servicios en un archivo" (Compose) y "varios contenedores en un Pod" es tentador, pero equivocado. Cómo detectarlo: si estás por poner dos servicios independientes —cada uno con su propio ciclo de vida, su propia necesidad de escalar por separado— dentro del mismo Pod. Cómo corregirlo: el patrón correcto en Kubernetes es un Pod (y, sobre él, un Deployment) por servicio independienteandes-cargo-status-api va a tener el suyo, y si esta guía tuviera un segundo servicio, tendría el suyo propio también, comunicándose por red vía Service (lección 6), no compartiendo el mismo Pod. Multi-contenedor en el mismo Pod se reserva para el patrón sidecar, donde el contenedor auxiliar existe específicamente para apoyar al principal, no para ser un servicio independiente.


Ejercicios

Ejercicio 1 — Explica la jerarquía sin mirar el diagrama. Sin volver a la sección "Por qué casi nunca se crea un Pod directamente", dibuja (en texto, con flechas) la jerarquía completa desde Deployment hasta Contenedor, y explica en una frase qué hace cada nivel.

Ver solución

Deployment (lo que declaras) → crea y administra → ReplicaSet (Kubernetes lo crea automáticamente, mantiene el número de réplicas) → crea y administra → Pod (la unidad mínima programable, lo que finalmente corre) → contiene → Contenedor(es) (el proceso real, la misma pieza que ya conocías de Docker). Cada nivel administra exclusivamente al nivel inmediatamente inferior — un Deployment nunca toca un contenedor directamente, siempre pasa por un ReplicaSet y un Pod.

Ejercicio 2 — Diagnostica un caso real. Un compañero borra, por accidente, un Pod que estaba corriendo dentro de un Deployment con replicas: 3. ¿Qué esperarías ver en kubectl get pods treinta segundos después? ¿Y si ese mismo Pod hubiera sido creado directamente, sin ningún Deployment detrás?

Ver solución

Con un Deployment de por medio: treinta segundos después, kubectl get pods debería mostrar de nuevo tres Pods — el que se borró desaparece, y el ReplicaSet del Deployment crea uno nuevo (con un nombre distinto, sufijo hash nuevo) para volver a las tres réplicas declaradas. Sin ningún Deployment detrás (un Pod suelto): kubectl get pods mostraría, treinta segundos después, exactamente lo mismo que mostró justo después del borrado — nada, porque no existe ningún controlador supervisando ese Pod específico.

Ejercicio 3 — Identifica el campo correcto. Mirando la "Anatomía mínima de un Pod" de esta lección, ¿qué campo del manifiesto usarías para que un futuro Service (lección 6) pueda encontrar este Pod entre varios otros? Justifica tu respuesta con lo que aprendiste sobre ese campo.

Ver solución

metadata.labels — un Service no encuentra Pods por su nombre (que además incluye un sufijo generado al azar cuando el Pod viene de un Deployment), sino por las etiquetas que coinciden con su propio selector. Un Pod sin la etiqueta correcta, aunque esté corriendo perfectamente, es invisible para cualquier Service que busque una etiqueta distinta — exactamente el mecanismo que desarrollas a fondo en las lecciones 6 y 7 de este módulo.


Resumen y siguiente paso

En esta lección entendiste qué es, exactamente, un Pod: el objeto desplegable más pequeño de Kubernetes, un envoltorio de uno o más contenedores que comparten red y, opcionalmente, almacenamiento — y, sobre todo, entendiste por qué casi nunca se crea uno directamente en producción: un Pod suelto no tiene ningún mecanismo de auto-reparación, esa propiedad la agrega un controlador de nivel superior. Viste la jerarquía completa (DeploymentReplicaSetPod → contenedor(es)), la anatomía mínima de un manifiesto de Pod, y las fases de su ciclo de vida.

Antes de avanzar deberías poder: explicar la diferencia entre un contenedor y un Pod sin usarlos como sinónimos; predecir qué pasa (y qué no pasa) cuando se borra un Pod suelto frente a uno administrado por un Deployment; y reconocer los cuatro campos principales de un manifiesto de Pod.

Siguiente lección: Deployments, ReplicaSets y el bucle de control declarativo. Ahí entra la pieza que resuelve exactamente lo que un Pod suelto no resuelve — quién decide cuántas oficinas deberían estar ocupadas, y quién actúa quieto, sin que nadie se lo pida, cuando la realidad no coincide con esa decisión.

Recursos

  1. Kubernetes — Pods — la referencia oficial completa, incluida la definición citada en esta lección.
  2. Kubernetes — Pod Lifecycle — las fases del ciclo de vida de un Pod, desarrolladas en la sección de profundización de esta lección.
  3. Kubernetes — Init Containers — referencia oficial sobre patrones multi-contenedor dentro de un Pod, mencionados por contraste en esta lección (fuera de alcance de esta guía).