K8s¶
K8s es simplemente una abreviatura de Kubernetes, donde la "K" es la primera letra, la "s" es la última letra, y el "8" representa las 8 letras intermedias (u, b, e, r, n, e, t, e). Es una forma muy común y rápida de referirse a Kubernetes en la industria.
Kubernetes es una plataforma de orquestación de contenedores open-source desarrollada originalmente por Google y ahora mantenida por la Cloud Native Computing Foundation (CNCF).
Su función principal es automatizar el despliegue, la gestión, el escalado y la operación de aplicaciones en contenedores, normalmente basados en Docker u otros runtimes compatibles.
Características¶
- Despliegue automático de contenedores (por ejemplo, imágenes de Docker).
- Escalado automático de aplicaciones (más o menos réplicas de pods según carga).
- Balanceo de carga entre pods.
- Gestión de la configuración y secretos (ConfigMaps, Secrets).
- Recuperación automática: reinicia pods que fallan, reemplaza nodos, etc.
- Actualizaciones sin downtime mediante rolling updates.
- Orquestación multi-nodo: distribuye contenedores en varios servidores (nodos) de forma eficiente.
Usos¶
- Microservicios distribuidos.
- Necesidad de alta disponibilidad.
- Aplicaciones que deben escalar horizontalmente.
- Infraestructura híbrida (on-premise + cloud).
Helm¶
Helm es una herramienta de gestión de paquetes para Kubernetes, que permite facilitar la instalación, actualización y gestión de aplicaciones dentro de un clúster de Kubernetes. Utiliza lo que se conoce como "Charts", que son colecciones de archivos que describen un conjunto de recursos de Kubernetes necesarios para ejecutar una aplicación o servicio.
Helm simplifica la forma en que implementamos y administramos aplicaciones en Kubernetes, proporcionando una forma estandarizada de empaquetar, distribuir y actualizar aplicaciones. Con Helm, puedes gestionar dependencias, versiones y configuraciones de tus aplicaciones de manera más sencilla.
Ventajas de Usar Helm ✅¶
✔️ Automatización: Despliegues más rápidos y sencillos.
✔️ Gestión de versiones: Puedes hacer rollback a una versión anterior fácilmente.
✔️ Reutilización: Usa charts existentes o comparte los tuyos.
✔️ Configuración flexible: Puedes personalizar valores sin modificar los archivos originales.
✔️ Compatibilidad con CI/CD: Ideal para pipelines de integración continua.
Conclusión¶
Helm es una herramienta poderosa para administrar aplicaciones en Kubernetes de manera más eficiente. Facilita la instalación, configuración y actualización de aplicaciones, permitiéndote manejar entornos de producción con menos esfuerzo.
Helm | Installing Helm¶
Helm tiene un script de instalación que automáticamente descargará la última versión de Helm y la instalará localmente.
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
Comprobar¶
Manifiesto¶

Un manifiesto en Kubernetes es simplemente otra forma de llamar a un archivo declarativo YAML que describe la configuración de un recurso en el clúster.
En otras palabras:
👉 "manifiesto" = archivo YAML que define un recurso de Kubernetes
Se le dice manifiesto porque "declara" de manera formal el estado deseado de un recurso dentro de Kubernetes. Es como una "declaración oficial" de cómo debe ser un Deployment, un Pod, un Service, etc.
Elementos¶
Un manifiesto en Kubernetes siempre tendrá al menos estas secciones:
-
apiVersion: La versión de la API de Kubernetes que se usará.
-
kind: El tipo de recurso que quieres crear (Pod, Deployment, Service, etc.).
-
metadata: Información como el nombre del recurso y etiquetas.
-
spec: La especificación detallada de cómo debe comportarse ese recurso.
📝 Ejemplo de un manifiesto¶
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Este sería un manifiesto de Pod que puedes aplicar en Kubernetes.
Contenido¶
Un YAML de Kubernetes describe recursos como:
- Pods
- Deployments
- Services
- ConfigMaps
- Secrets
- Ingress, etc.
Puedes tener múltiples manifiestos en un solo archivo YAML, separados con ---, alternativamente puedes tener un manifiesto por archivo si prefieres mantener todo modular.
Aplicación de un manifiesto¶
Kubernetes toma este manifiesto y se asegura de crear el recurso exactamente como lo describes. si el recurso ya está creado, Kubernetes lee el archivo, compara el estado deseado con el estado actual y concilia la diferencia para que tu aplicación quede como tú la definiste en el YAML.
POD¶

Un Pod en Kubernetes es la unidad más pequeña de despliegue y ejecución dentro del clúster. Un pod encapsula uno o más contenedores que comparten el mismo entorno de red, almacenamiento y configuración.
Características principales de un pod:¶
- Uno o varios contenedores: Aunque lo más común es que un pod contenga un solo contenedor, puede tener varios (por ejemplo, un contenedor principal y un "sidecar" para tareas auxiliares).
- Red compartida: Todos los contenedores dentro del pod comparten la misma dirección IP, el mismo puerto de red y las mismas interfaces de red.
- Volúmenes compartidos: Los contenedores dentro del pod pueden compartir volúmenes para intercambiar datos entre ellos.
- Ciclo de vida conjunto: Los contenedores dentro de un pod siempre se ejecutan juntos en el mismo nodo y se gestionan como una unidad. Si el pod muere, todos los contenedores dentro de él también se detienen.
📝 Manifiesto de Pod:¶
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: httpd:latest
ports:
- containerPort: 80
🔧 Comandos para PODs¶
# despliegue del Pod
kubectl apply -f myapp.yaml
# Eliminar el Pod
kubectl delete -f myapp.yaml
# Devuelve el listado de pods
kubectl get pods
# Describe un pod
kubectl describe pod <name>
# Devuelve el consumo de recursos de un nodo
kubectl top pod <name>
# Ejecutar un comando sobre un contenedor
kubectl exec <pod> -c <contenedor> <comando>
# Copia un fichero en un contenedor
kubectl cp /tmp/foo <pod-name>:/tmp/bar -c <container-name>
# Consulta de los de un contenedor
kubectl logs <pod-name> -c <container-name>
# Port forwarding
kubectl port-forward --address 0.0.0.0 pod/<pod-name> <host-port>:<pod-port>
Namespace¶

Los namespaces en Kubernetes son una forma de aislar y organizar recursos dentro de un mismo clúster.
Piensa en ellos como "espacios de trabajo" o "compartimentos" virtuales donde puedes tener recursos que no interfieren entre sí, aunque tengan el mismo nombre.
Utilidad¶
- Separar entornos: Puedes tener un
namespacepara desarrollo, otro para testing y otro para producción dentro del mismo clúster. - Evitar conflictos de nombres: Puedes tener un Deployment llamado
web-appen dos namespaces diferentes sin que choquen entre ellos. -
Aplicar políticas y límites:
- Puedes aplicar quotas de recursos por namespace (CPU, memoria).
- Puedes definir reglas de seguridad o control de acceso (RBAC) por namespace.
- Facilitar la administración: En clústeres grandes, los namespaces ayudan a que los equipos trabajen de manera aislada y organizada.
Namespaces por defecto¶
- default: Namespace por defecto donde se crean los recursos si no especificas otro.
- kube-system: Recursos internos del sistema de Kubernetes (DNS, kube-proxy, etc.).
- kube-public: Datos accesibles de forma pública dentro del clúster (rara vez se usa directamente).
- kube-node-lease: Namespace para gestionar heartbeats de los nodos (para detectar si un nodo está vivo).
🔧 Comandos para trabajar con Namespaces:¶
# Devuelve el listado de namespaces
kubectl get namespaces
# Crea un namespace
kubectl create namespace <nombre>
# Especifical el namespace en el cliente kubectl
kubectl apply -f pod.yaml --namespace=<nombre>
# Establecer un determinado namespace como predeterminado
kubectl config set-context --current -–namespace=<nombre>
Definir un namespace dentro de un YAML
Service¶

Un Service en Kubernetes es un recurso que proporciona una abstracción para exponer y acceder a un conjunto de pods de manera estable y confiable. Los pods son efímeros y sus IPs pueden cambiar, por lo que un Service actúa como un punto fijo de entrada que redirige el tráfico a los pods correctos, incluso si estos son recreados o se mueven a otro nodo.
Funciones principales de un servicio:¶
-
Descubrimiento y balanceo de carga:
- Distribuye automáticamente el tráfico entre los pods que coincidan con el selector definido.
-
Dirección IP estable:
-
Mientras que los pods tienen IPs dinámicas, el Service proporciona una IP virtual estable (ClusterIP) o un nombre DNS interno.
-
Exposición de la aplicación:
-
Puede exponer una aplicación internamente dentro del clúster o externamente hacia internet.
Tipos de servicios en Kubernetes:¶
-
ClusterIP (por defecto):
- Expone el servicio internamente dentro del clúster. No es accesible desde fuera.
-
NodePort:
-
Abre un puerto en cada nodo del clúster y redirige el tráfico a los pods.
-
LoadBalancer:
-
Crea un balanceador de carga externo (si el clúster está en una nube como AWS, GCP, Azure) y lo conecta al servicio.
-
ExternalName:
-
No redirige tráfico, pero mapea un nombre DNS interno a un nombre DNS externo.
📝 Manifiesto de "Service" tipo NodePort¶
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
Funcionamiento¶
- El selector
app: myapphace que este Service envíe tráfico a todos los pods que tengan la etiquetaapp=myapp. - El puerto
80del Service se mapea al puerto80del pod (targetPort).
🔧 Comandos¶
# Aplica el manifiesto o los cambios
kubectl apply -f myapp.yaml
# Elimina el manifiesto
kubectl delete -f myapp.yaml
# Comprueba
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/myapp 1/1 Running 0 15m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44h
service/service1 NodePort 10.96.146.193 <none> 80:31926/TCP 15m
Deployment
¶
Un deployment en Kubernetes es un recurso que gestiona y mantiene el ciclo de vida de un conjunto de réplicas de un pod de manera declarativa. Es uno de los objetos más utilizados en Kubernetes, ya que te permite:
- Desplegar una aplicación: Define qué imagen de contenedor se debe usar, cuántas réplicas deben ejecutarse y cómo deben exponerse.
- Actualizar la aplicación sin tiempo de inactividad: Permite hacer rolling updates (actualizaciones progresivas) de los pods, minimizando la posibilidad de interrupciones.
- Gestionar el estado deseado: Kubernetes se asegura de que siempre haya el número de réplicas especificadas corriendo; si un pod falla, automáticamente se crea uno nuevo.
- Rollback: Puedes revertir a una versión anterior si una actualización falla.
📝 Manifiesto de "Deployment"¶
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: httpd:latest
ports:
- containerPort: 80
✅ Conceptos clave:¶
- replicas: número de instancias de un pod.
- selector: cómo Kubernetes identifica los pods que pertenecen a este deployment.
- template: especifica la plantilla de los pods (contenedores, puertos, variables de entorno, etc.).
- strategy: (opcional) puedes definir estrategias de despliegue como RollingUpdate o Recreate.
🔧 Comandos para deployments¶
# Aplica el manifiesto o los cambios
kubectl apply -f myapp.yaml
# Elimina el manifiesto
kubectl delete -f myapp.yaml
# Comprueba deployments
kubectl get deployments
# Escala el despliegue
kubectl scale --replicas 2 deployment/myapp
Volúmenes¶
En Kubernetes, un volumen es una forma de proporcionar almacenamiento persistente a los pods y sus contenedores. Los volúmenes permiten que los datos persistan más allá de la vida de un pod individual (ya que los pods son efímeros y sus datos locales se pierden cuando son eliminados).
📦 Tipos de volúmenes en Kubernetes¶
Kubernetes soporta distintos tipos de volúmenes dependiendo del caso de uso y del proveedor de infraestructura.
- emptyDir: Crea un volumen vacío cuando el pod se inicializa. Se borra cuando el pod muere. Útil para almacenamiento temporal (caches, etc.).
- hostPath: Monta una carpeta del nodo físico (host) dentro del contenedor. No es recomendable para producción, pero útil para pruebas locales.
- nfs: Monta un volumen compartido a través de un servidor NFS externo.
- persistentVolumeClaim (PVC): Solicita almacenamiento persistente a través de un PersistentVolume. Es la forma estándar de montar almacenamiento duradero en Kubernetes.
- configMap / secret: Permiten montar configuraciones o secretos como archivos dentro de los pods.
- cloud-specific (AWS EBS, GCE Persistent Disk, Azure Disk): Volúmenes gestionados por proveedores cloud que pueden ser montados como almacenamiento persistente.
✅ Ejemplos¶
📝 Pod con volumen emptyDir¶
apiVersion: v1
kind: Pod
metadata:
name: mypod-emptydir
spec:
containers:
- name: app
image: httpd
volumeMounts:
- mountPath: /usr/local/apache2/htdocs # Aquí se montará el volumen
name: web-content
volumes:
- name: web-content
emptyDir: {} # Volumen tipo "directorio vacío"
- Cuando el pod se crea, Kubernetes genera un directorio temporal en el nodo donde corre el pod.
- Ese directorio está disponible en
/usr/local/apache2/htdocs/dentro del contenedor de httpd. - Los datos se mantienen mientras el pod esté vivo, pero se eliminan cuando el pod muere o se borra.
ℹ️ Casos de uso para emptyDir: - Para almacenamiento temporal de archivos o cachés. - Para compartir datos entre múltiples contenedores dentro del mismo pod. - Como espacio de trabajo para procesos batch o temporales.
📝 Pod con hostPath¶
apiVersion: v1
kind: Pod
metadata:
name: mypod-hostpath
spec:
containers:
- name: app
image: httpd
volumeMounts:
- mountPath: /usr/local/apache2/htdocs # Dentro del contenedor
name: web-content
volumes:
- name: web-content
hostPath:
path: /data/httpd # Ruta en el nodo físico
type: DirectoryOrCreate # Crea el directorio si no existe
- El contenedor de httpd montará el directorio
/data/nginxdel host físico en/usr/local/apache2/htdocs/dentro del contenedor. - Todo lo que escribas o leas dentro de
/usr/local/apache2/htdocs/se reflejará en/data/httpddel nodo. - Si el directorio
/data/httpdno existe, Kubernetes lo creará automáticamente porque usamostype: DirectoryOrCreate.
ℹ️ Casos de uso para hostPath: - Es útil para entornos de desarrollo o pruebas locales. - En producción, no es recomendable, ya que acopla los pods a un nodo específico. - Puede ser peligroso si no se controla bien, ya que accede directamente al sistema de archivos del host.
📝 Pod con volumen nfs¶
apiVersion: v1
kind: Pod
metadata:
name: mypod-nfs
spec:
containers:
- name: app
image: httpd
volumeMounts:
- mountPath: /usr/local/apache2/htdocs # Ruta dentro del contenedor
name: nfs-volumen
volumes:
- name: nfs-volumen
nfs:
server: 192.168.1.100 # IP del servidor NFS
path: /exports/web-content # Ruta compartida en el NFS
- El pod monta el directorio remoto
/exports/web-contentde un servidor NFS con IP192.168.1.100. - Todo lo que el contenedor httpd lea o escriba en
/usr/local/apache2/htdocs/se guardará en el servidor NFS. - Este volumen puede ser compartido por varios pods al mismo tiempo, lo que lo hace útil para entornos donde múltiples aplicaciones necesitan acceder al mismo almacenamiento.
ℹ️ Casos de uso para NFS: - Servir archivos estáticos desde un punto común. - Compartir configuraciones, datos o resultados entre diferentes pods. - Montar un almacenamiento distribuido simple para apps legacy.
🗂️ Relación entre PersistentVolume (PV) y PersistentVolumeClaim (PVC)¶
- PersistentVolume (PV): Es el recurso que representa un bloque de almacenamiento real en el clúster, como un disco EBS, un disco local o un volumen NFS.
- PersistentVolumeClaim (PVC): Es una petición de almacenamiento por parte de un pod o aplicación. El PVC "reclama" un PV disponible según el tamaño y las características que necesita.
📝 1️⃣ PersistentVolume (PV)¶
Manifiesto PV NFS -> nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
path: /mnt/nfs_share
server: <IP_DEL_SERVIDOR_NFS>
📝 2️⃣ PersistentVolumeClaim (PVC)¶
Manifiesto PVC que usa el PV anterior -> nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
📝 3️⃣ Pod que usa el PVC¶
apiVersion: v1
kind: Pod
metadata:
name: mypod-pvc
spec:
containers:
- name: app
image: httpd
volumeMounts:
- mountPath: /usr/local/apache2/htdocs
name: volumen-persistente
volumes:
- name: volumen-persistente
persistentVolumeClaim:
claimName: mypvc
- El PV define el volumen físico.
- El PVC es la solicitud que hace el Pod para "reclamar" ese volumen.
- El Pod monta ese PVC en
/usr/local/apache2/htdocs/y todo lo que escriba allí será persistente, incluso si el pod es eliminado y recreado.
⚠️ Advertencia: En producción lo ideal es que el PV sea de un tipo distribuido o gestionado como:
nfs,awsElasticBlockStore,gcePersistentDisk,cephfs, etc.
StorageClass¶
✅ StorageClasses permiten almacenamiento dinámico en Kubernetes.
✅ Diferentes provisioners ofrecen distintas opciones de almacenamiento.
✅ Facilitan la gestión automática de volúmenes sin intervención manual.
NFS¶
⚙ Opciones para usar NFS¶
Kubernetes no tiene un provisioner de NFS incorporado, pero puedes usar varias opciones de aprovisionamiento:
- Manualmente: Creas un PersistentVolume (PV) con una ruta NFS y luego un PersistentVolumeClaim (PVC) lo usa.
- Dynamic Provisioning con NFS Subdir External Provisioner: Usa un controlador que aprovisione dinámicamente volúmenes en un servidor NFS.
📌 Opción 1: StorageClass con aprovisionamiento manual (Static Provisioning)¶
En este caso, el StorageClass no es obligatorio, pero puede ayudar a organizar el almacenamiento.
📝 Paso 1: Crear un PersistentVolume (PV) manualmente¶
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: manual-nfs
nfs:
path: /exported/path/mi-directorio # directorio dentro de NFS
server: 192.168.1.100 # IP de tu servidor NFS
📝 Paso 2: Crear un PersistentVolumeClaim (PVC)¶
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs
spec:
accessModes:
- ReadWriteMany
storageClassName: manual-nfs
resources:
requests:
storage: 5Gi
🔹 Aquí, el PVC buscará un PV con storageClassName: manual-nfs.
📌 Opción 2: Aprovisionamiento dinámico con NFS Subdir External Provisioner¶
Para evitar crear manualmente PVs, puedes usar el NFS Subdir External Provisioner, que crea automáticamente directorios en un servidor NFS.
🛠 Paso 1: Instalar el NFS Provisioner¶
Si usas Helm, instala el provisioner:
# añade el repositorio helm
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm repo update
# instalar "nfs-provisioner"
helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set storageClass.reclaimPolicy=Retain --set storageClass.archiveOnDelete=false --set storageClass.onDelete=delete --set nfs.server=192.168.1.100 --set nfs.path=/exported/path
- 📦 Instala
nfs-provisioneren el namespace "default" - 🔗 Configura el servidor NFS y la ruta compartida (
--set nfs.server=192.168.1.1y--set nfs.path=/exported/path). - 📂 Crea una StorageClass llamada
nfs-client
Para comprobar recursos NFS exportados:
📝 Paso 2: Crear un PersistentVolumeClaim (PVC)¶
Después de instalarlo, el provisioner crea una StorageClass como esta:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-dynamic-nfs
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client
resources:
requests:
storage: 5Gi
🔹 Aquí, el PVC creará automáticamente un subdirectorio en el servidor NFS.
🚀 Comparativa¶
| Método | Ventajas | Desventajas |
|---|---|---|
| Manual (Static Provisioning) | Control total, útil si ya tienes PVs definidos | Hay que crear cada PV manualmente |
| Dinámico (NFS Provisioner) | Crea volúmenes automáticamente, menos gestión manual | Requiere instalar el provisioner |
Si tu infraestructura soporta un servidor NFS y necesitas escalabilidad, usar aprovisionamiento dinámico es la mejor opción.
🎯 Conclusión¶
- NFS es una excelente opción para almacenamiento compartido en Kubernetes porque permite ReadWriteMany (RWX).
- Puedes usar PVs estáticos o un provisioner dinámico para manejar el almacenamiento más eficientemente.
- El NFS Subdir External Provisioner es una herramienta útil para facilitar la gestión.
Ingress¶
Ingress en Kubernetes es un recurso que te permite gestionar el acceso externo a servicios del clúster a través de HTTP/HTTPS.
- Define reglas de enrutamiento basadas en rutas (paths) y dominios (hosts).
- Expone múltiples services de Kubernetes detrás de una misma IP pública.
- Facilita la gestión de TLS (SSL) para HTTPS.
- Es compatible con autenticación, reescritura de URL, balanceo de carga y más.
Componentes principales:¶
- Ingress Resource: Es un manifiesto YAML donde defines las reglas de acceso (host, path, backend service).
- Ingress Controller: Es el componente que escucha los recursos de Ingress y configura un proxy (como NGINX, HAProxy, Traefik) para aplicarlas. No es parte nativa de Kubernetes; debes desplegarlo en el clúster.
Ingress Controller¶
Ingress Controller en Kubernetes es el componente que implementa las reglas definidas en un recurso Ingress y gestiona el tráfico HTTP/HTTPS desde fuera del clúster hacia los servicios internos.
- El Ingress es solo una especificación, un manifiesto con reglas (por ejemplo: "el tráfico que llegue a
/app1va al Service A"). - Pero el que realmente escucha esas reglas y configura un proxy HTTP es el Ingress Controller.
ℹ️ Nota: Sin Ingress Controller, el Ingress YAML no tendría efecto real.
Características¶
- Crea un proxy HTTP(S) que expone tus aplicaciones al exterior.
- Gestiona:
- Balanceo de carga de capa 7 (HTTP).
- Redirecciones y reescrituras.
- TLS/SSL (certificados).
- Autenticaciones (Basic Auth, JWT, etc.).
- Reglas por dominio y rutas.
Ingress Controllers populares¶
- NGINX Ingress Controller (el más común).
- Traefik.
- HAProxy Ingress.
- Kong Ingress Controller (API Gateway).
- Istio Gateway (cuando usas Istio como service mesh).
Funcionamiento¶
- Despliegas un Ingress Controller (por ejemplo, NGINX) como un Pod dentro de tu clúster.
- Ese Pod escucha los recursos Ingress que creas.
- Automáticamente configura un proxy inverso y expone los servicios según las reglas de tus manifiestos.
💡 Ejemplo:¶
- Usuario accede a
https://myapp.dominio.com. - Llega al Ingress Controller (que tiene la IP pública o está expuesto).
- El Controller lee la regla del Ingress y redirige la petición al Service correspondiente.
Despliegue NGINX Ingress Controller¶
1️⃣ Instalar NGINX Ingress Controller¶
Mediante helm¶
# Añadir el repositorio de ingress-nginx a Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# Instalar
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace --set controller.service.type=NodePort --set controller.service.nodePorts.http=30080 --set controller.service.nodePorts.https=30443 --set controller.rbac.create=true
controller.service.type=NodePort: Define que el Service será de tipo NodePort, necesario en Cluster local.controller.service.nodePorts.http=30080: Configura el puerto HTTP en el 30080.controller.service.nodePorts.https=30443: Configura el puerto HTTPS en el 30443.
👉 Esto instalará: - Deployment del NGINX Ingress Controller. - Service tipo LoadBalancer (o NodePort según el entorno). - RBAC y otros recursos necesarios.
2️⃣ Verificar que esté en ejecución¶
Verás un servicio llamado ingress-nginx-controller que será el punto de entrada de tu tráfico HTTP/HTTPS.
3️⃣ Exponerlo en entornos sin LoadBalancer¶
Si estás en un clúster sin proveedor de nube (bare-metal, Proxmox, etc.), cambia el tipo de Service a NodePort:
Cambia type: LoadBalancer por type: NodePort y guarda.
ℹ️ Nota: Si instalaste con la opción
"--set controller.service.type=NodePort"no será necesario este paso.
4️⃣ Manifiesto Ingress¶
Un ejemplo de Ingress que hace uso del controlador:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: miapp.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
🚩 No olvides crear tu Service myapp-service previamente.
5️⃣ Configura tu DNS o /etc/hosts¶
Si es un entorno local puedes añadir en tu PC:
Desinstalar Ingress-NGINX con Helm¶
# Eliminar el release con Helm
helm uninstall ingress-nginx -n ingress-nginx
#(Opcional) Borrar el namespace si no lo necesitas más
kubectl delete namespace ingress-nginx
default-backend¶
Kubernetes no proporciona automáticamente una página por defecto para ingress-nginx. Sin embargo, podemos usar un simple Deployment y Service de Nginx para servir contenido estático de una página web para manejar las peticiones no encontradas. Se utiliza un default-backend, que es un servicio que responde con una página de error personalizada cuando no se encuentra una ruta coincidente en el controlador Ingress.
1. Crear un ConfigMap para la página web¶
El ConfigMap contendrá el contenido HTML de la página por defecto.
apiVersion: v1
kind: ConfigMap
metadata:
name: default-404-page
namespace: ingress-nginx
data:
index.html: |
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Página no encontrada</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin: 50px; }
h1 { color: red; }
</style>
</head>
<body>
<h1>404 - Página no encontrada</h1>
<p>Lo sentimos, pero la página que buscas no existe.</p>
</body>
</html>
2. Crear el Deployment¶
Este Deployment utiliza la imagen de NGINX, monta el ConfigMap en el directorio de contenido web, crea el servicio y configura Ingress para mostrar "default-backend".
apiVersion: apps/v1
kind: Deployment
metadata:
name: default-backend
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app: default-backend
template:
metadata:
labels:
app: default-backend
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: default-404-page
---
apiVersion: v1
kind: Service
metadata:
name: default-backend
namespace: ingress-nginx
spec:
selector:
app: default-backend
ports:
- protocol: TCP
port: 80
targetPort: 80
3. Aplica el deployment¶
Crea los manifiestos anteriores (se pueden unificar en uno solo) y aplica el deployment:
4. Configurar ingress-nginx-controller para usar el Default Backend¶
El controlador Ingress-Nginx puede configurarse para usar un backend por defecto modificando su Deployment.
Ejecuta el Gifts el siguiente comando para editarlo en vivo:
Añade la línea correspondiente en la sección de argumentos:
spec:
containers:
- name: controller
args:
- /nginx-ingress-controller
- --default-backend-service=ingress-nginx/default-backend # añade la siguiente linea
Cert-Manager¶
Cert-Manager es una herramienta nativa de Kubernetes que automatiza la gestión de certificados TLS dentro de un clúster.
Cert-Manager es un controlador de Kubernetes que: - Solicita certificados de diferentes proveedores (por ejemplo: Let's Encrypt, Venafi, CA interna, etc.). - Renueva automáticamente los certificados antes de que expiren. - Crea y genera los Secrets de Kubernetes que contienen los certificados TLS.
🛠️ Funcionamiento¶
- Automatiza la emisión y renovación de certificados TLS.
- Funciona con Ingress, Services, Pods, y cualquier recurso que necesite TLS.
- Soporta ACME (Let's Encrypt), certificados auto-firmados, Vault, entre otros.
- Utiliza recursos personalizados de Kubernetes como:
Issuer(local a un namespace)ClusterIssuer(disponible para todo el clúster)Certificate(define el dominio y cómo obtener el TLS)Order,Challenge(para procesos ACME)
Instalación¶
Usando "Helm"¶
# Añadir repositorio
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update
# Instalar
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true
ClusterIssuer¶
Global -> para todo el clúster¶
- Se aplica una sola vez y puedes usarlo en cualquier namespace.
- Ideal para producción cuando quieres certificados automáticos a nivel de clúster.
Manifiesto "letsencrypt-staging.yaml":
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
Manifiesto "letsencrypt-prod.yaml":
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
# ClusterIssuer test
kubectl apply -f letsencrypt-staging.yaml
# ClusterIssuer Producción
kubectl apply -f letsencrypt-prod.yaml
Comprobación¶
# Lista ClusterIssuers
kubectl get clusterissuer
# Obtener detalles del ClusterIssuer
kubectl describe clusterissuer letsencrypt-staging
kubectl describe clusterissuer letsencrypt-prod
Manifiesto¶
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpd-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-prod # issuer
nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # redirige http -> https
spec:
ingressClassName: nginx
rules:
- host: myapp.dominio.com # FQDN app
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpd-service
port:
number: 80
tls:
- hosts:
- myapp.dominio.com # FQDN app
secretName: myapp-tls
Desinstalación¶
kubectl delete crd issuers.cert-manager.io clusterissuers.cert-manager.io certificates.cert-manager.io certificaterequests.cert-manager.io orders.acme.cert-manager.io challenges.acme.cert-manager.io