Glosario¶
Pensado para alguien que ve estos términos por primera vez. Definiciones cortas primero, detalle técnico después. Se irá expandiendo en fases siguientes — por ahora cubre los términos que ya aparecen en el resto del sitio.
GitOps¶
En una frase: el estado deseado del sistema vive en Git, y un
proceso automático (no una persona con kubectl) se encarga de que el
cluster real coincida con lo que dice Git.
Detalle: en vez de ejecutar comandos contra el cluster a mano, se
edita un archivo YAML, se hace commit, y una herramienta (aquí, Argo CD)
detecta el cambio y lo aplica. Si alguien cambia algo directo en el
cluster sin pasar por Git, GitOps lo revierte (selfHeal) — Git es la
única fuente de verdad.
Tunnel (Cloudflare Tunnel)¶
En una frase: una forma de exponer un servicio interno a internet sin abrir puertos en el router/firewall.
Detalle: un proceso (cloudflared) corre dentro de la red local y
abre una conexión saliente hacia Cloudflare. El tráfico público llega a
Cloudflare y viaja hacia adentro por esa misma conexión — no hace falta
port-forwarding ni IP pública propia.
Argo CD¶
En una frase: el "robot" que sincroniza el cluster Kubernetes con lo que está escrito en Git.
Detalle: vigila uno o más repos Git, compara el estado declarado (manifiestos YAML/Kustomize) contra el estado real del cluster, y aplica la diferencia. Ver flujo GitOps.
Manifest (manifiesto)¶
En una frase: un archivo YAML que describe qué quieres que exista en Kubernetes (un Deployment, un Service, un Ingress...).
Detalle: Kubernetes no se controla escribiendo código imperativo ("crea un pod"), sino declarando el resultado deseado ("quiero 2 réplicas de esta imagen corriendo"). El manifiesto es ese documento.
App of Apps¶
En una frase: un patrón donde una Application de Argo CD no despliega una app directamente, sino que despliega otras Applications.
Detalle: en este lab, application.yaml (raíz) vigila la carpeta
apps/ de apps-registry; cada archivo ahí dentro es una Application
hija que a su vez apunta a un workload real. Permite agregar una app
nueva con un solo archivo YAML nuevo.
Kustomize¶
En una frase: una forma de componer manifiestos de Kubernetes sin plantillas (a diferencia de Helm).
Detalle: un archivo kustomization.yaml lista qué recursos YAML
incluir y qué parches aplicarles, sin necesidad de un lenguaje de
templating separado.
Namespace¶
En una frase: una partición lógica dentro del mismo cluster físico — agrupa recursos relacionados y les pone un límite alrededor.
Detalle: este lab tiene un namespace por dominio de negocio
(ecommerce, docs-portal) más argocd para el propio Argo CD. Todo
lo que gobierna a un namespace (cuotas, políticas de red) vive en
platform-infra, separado de los manifiestos de la app — así una app
nueva no puede "olvidarse" de traer su propia gobernanza.
ResourceQuota¶
En una frase: el techo total de recursos que un namespace entero puede consumir, sumando todos sus pods.
Detalle: la cuota real de ecommerce
(platform-infra/ecommerce-governance/resourcequota.yaml):
hard:
requests.cpu: "3"
requests.memory: 4Gi
limits.cpu: "8"
limits.memory: 8Gi
pods: "12"
persistentvolumeclaims: "6"
requests.storage: 80Gi
Si un Deployment nuevo pidiera más requests.memory del que queda
disponible bajo ese techo, Kubernetes rechaza el pod directamente — no
lo deja arrancar y luego fallar.
LimitRange¶
En una frase: los valores por defecto (y los mínimos/máximos) que aplican a un contenedor individual dentro de un namespace, para cuando el manifiesto no los declara explícitos.
Detalle: complementa a ResourceQuota (que mira el namespace
entero) a nivel de un solo contenedor. La de ecommerce
(limitrange.yaml) pone defaultRequest: 100m/128Mi,
default: 500m/512Mi (límites si el contenedor no los declara), y un
rango permitido de 10m/16Mi a 2 CPU/1Gi por contenedor — evita
tanto el contenedor que no pide nada y termina compitiendo mal por
recursos, como el que pide de más y se come la cuota del namespace
entero él solo.
NetworkPolicy¶
En una frase: un firewall a nivel de Kubernetes — qué tráfico de red se permite entrar (o salir) de un pod.
Detalle: sin ninguna NetworkPolicy, todos los pods de un cluster
pueden hablarse entre sí libremente. La de ecommerce
(networkpolicy.yaml) usa podSelector: {} (aplica a todos los pods
del namespace) y permite ingress solo desde namespaceSelector: {}
(cualquier namespace del cluster, típicamente Traefik llegando desde
kube-system o el namespace de ingress) — bloquea tráfico externo al
cluster que intentara saltarse Traefik y pegarle directo a un Service
interno.
Deployment¶
En una frase: el controlador para cargas de trabajo sin estado — réplicas intercambiables entre sí, ninguna con identidad propia.
Detalle: frontend-deploy es un Deployment de 2 réplicas: no
importa cuál de las dos atienda una petición, ambas sirven exactamente
lo mismo y ninguna guarda datos propios en disco. Si un pod muere,
Kubernetes crea otro cualquiera para reemplazarlo — no hay "el pod
original" que recuperar. Contrastar con StatefulSet abajo.
Service¶
En una frase: un nombre de red estable que apunta a un grupo de pods, aunque esos pods cambien.
Detalle: los pods son efímeros (mueren y se recrean con IP nueva
cada vez); un Service (ej. frontend-svc, postgres-svc) les da un
nombre DNS interno fijo (frontend-svc.ecommerce.svc.cluster.local,
o simplemente frontend-svc desde dentro del mismo namespace) que no
cambia aunque los pods de atrás sí. postgres-svc en este lab es
además un Service clusterIP: None ("headless") — necesario porque
commerce-postgres es un StatefulSet y cada pod necesita su propia
identidad de red estable, no una IP compartida balanceada entre
réplicas.
Ingress¶
En una frase: la regla que dice "las peticiones a este dominio y esta ruta van a este Service", para tráfico HTTP que entra al cluster.
Detalle: ecommerce-ingress enruta por path, no solo por
dominio: shop.cruzcloud.net/api/catalog va a catalog-api-svc, y
todo lo demás (/) va a frontend-svc — un solo objeto Ingress con
dos backends distintos según el prefijo de la URL. Es Traefik (el
Ingress Controller del cluster) quien lee estos objetos y hace el
enrutamiento real; el Ingress en sí es solo la declaración de la
regla, no el componente que la ejecuta.
StatefulSet¶
En una frase: el controlador para cargas de trabajo con estado — cada réplica tiene identidad propia y almacenamiento propio que sobrevive a que el pod se reinicie.
Detalle: commerce-postgres es un StatefulSet, no un Deployment,
porque el frontend puede tener 2 réplicas idénticas sin datos propios,
pero Postgres no — sus datos tienen que vivir en un disco específico
que sobreviva un reinicio del pod y sepa exactamente cuál pod es
"el suyo". Cada pod de un StatefulSet obtiene su propio
PersistentVolumeClaim vía volumeClaimTemplates (acá,
postgres-data, 10Gi en local-path) y un nombre de red estable y
numerado (commerce-postgres-0), a diferencia de los nombres
aleatorios de un Deployment. Meilisearch, Redis y MinIO en este lab
siguen el mismo patrón por la misma razón — todos guardan datos en
disco que tienen que sobrevivir al pod.
Init container¶
En una frase: un contenedor que corre antes que los contenedores principales de un pod, y tiene que terminar bien (exit 0) para que el resto arranque.
Detalle: medusa-deploy usa dos, y a propósito están separados en
vez de ser uno solo: wait-for-postgres (pg_isready en loop, solo
espera a que Postgres acepte conexiones) y migrations
(db:migrate, corre las migraciones de verdad). Un incidente real
mostró por qué separarlos importa: cuando el chequeo de disponibilidad
reusaba la misma DATABASE_URL completa de la app (con
?sslmode=disable incluido), el parser de pg_isready no la entendía
y el pod quedaba atascado en Init — reportado como si fuera
CrashLoopBackOff, sin serlo. El fix fue que el chequeo de
disponibilidad use el mínimo de parámetros posible
(host/puerto/usuario/db), nunca la URI completa pensada para la app.
Ver el playbook del crashloop de Medusa.