Arquitectura y Componentes Principales
La arquitectura de Kubernetes se fundamenta en un plano de control que gestiona el estado global y nodos de trabajo que ejecutan las cargas útiles. Los componentes esenciales incluyen:
- etcd: Base de datos distribuida de clave-valor que almacena toda la configuración y el estado del clúster.
- kube-apiserver: Punto de entrada único para la API REST, encargada de la autenticación, autorización y el registro de recursos.
- kube-scheduler: Evalúa los requisitos de recursos y las restricciones de los Pods no programados para asignarlos al nodo más adecuado.
- kube-controller-manager: Ejecuta controladores (como el de nodos, réplicas y endpoints) que regulan el estado del clúster mediante bucles de reconciliación.
- kubelet: Agente que opera en cada nodo, garantizando que los contenedores se ejecuten correctamente dentro de los Pods según las especificaciones.
- kube-proxy: Mantiene las reglas de red en los nodos, permitiendo la comunicación y el balanceo de carga para los Services.
- Container Runtime: Software subyacente (como containerd o CRI-O) responsable de ejecutar los contenedores mediante la interfaz CRI.
Preparación del Entorno y Despliegue del Clúster
Para garantizar la estabilidad y compatibilidad, es imperativo preparar los nodos a nivel de sistema operativo antes de iniciar la instalación. A continuación, se detalla la configuración de red y kernel requerida:
# Desactivar memoria swap y cargar módulos de red
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# Configurar parámetros sysctl para el reenvío de paquetes
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
El despliegue moderno del clúster se realiza mediante kubeadm, el cual automatiza la configuración de los componentes del plano de control:
# Inicializar el plano de control en el nodo maestro
kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.1.10
# Configurar credenciales para kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# Unir nodos de trabajo al clúster
kubeadm join 192.168.1.10:6443 --token <token_generado> \
--discovery-token-ca-cert-hash sha256:<hash_certificado>
Configuración de Redes: CNI
Una vez inicializado el clúster, es necesario instalar un plugin de interfaz de red de contenedores (CNI) para habilitar la comunicación entre Pods a través de distitnos nodos.
# Despliegue de Flannel como proveedor de red
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
Gestión de Cargas de Trabajo: Deployments y Services
Los Deployments gestionan aplicaciones sin estado, asegurando que el número deseado de réplicas esté siempre disponible. A diferencia de los antiguos ReplicationControllers, los Deployments facilitan actualizaciones continuas y reversiones automáticas.
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: web-server
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
Para exponer la aplicación, se utiliza un Service de tipo NodePort o ClusterIP:
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
namespace: production
spec:
type: NodePort
selector:
tier: frontend
ports:
- port: 80
targetPort: 80
nodePort: 30080
Descubrimiento de Servicios y DNS
CoreDNS es el estándar actual para el descubrimiento de servicios internos. Permite que los Pods resuevlan nombres de servicios (ej. frontend-svc.production.svc.cluster.local) sin depender de variables de entorno inyectadas, las cuales pueden saturar el entorno de ejecución en clústeres grandes.
# Verificar el estado de CoreDNS en el namespace del sistema
kubectl get pods -n kube-system -l k8s-app=kube-dns
# Prueba de resolución DNS desde un Pod de depuración
kubectl run dns-test --image=busybox:1.36 --restart=Never -it --rm -- nslookup frontend-svc.production
Sondeos de Salud (Probes)
Los sondeos garantizan que el tráfico solo se envíe a instancias saludables y reinician aquellos contenedores que han entrado en estado de error.
apiVersion: v1
kind: Pod
metadata:
name: api-gateway
spec:
containers:
- name: api
image: custom-api:v2
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
readinessProbe:
exec:
command:
- cat
- /tmp/ready-state
initialDelaySeconds: 5
periodSeconds: 5
Almacenamiento Persistente: PV, PVC y NFS
Los contenedores son efímeros por naturaleza. Para bases de datos o aplicaciones con estado, se requiere almacenamiento persistente mediante PersistentVolumes (PV) y PersistentVolumeClaims (PVC).
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-data-pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
path: /exports/k8s-data
server: 192.168.1.50
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-storage-claim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Gi
Almacenamiento Distribuido con GlusterFS
Para entornos que requieren alta disponibilidad y escalabilidad horizontal en la capa de almacenamiento, GlusterFS se integra nativamente mediante Endpoints y Services headless.
# Creación de un volumen distribuido y replicado en GlusterFS
gluster volume create vol_produccion replica 3 \
node1:/data/brick1 \
node2:/data/brick1 \
node3:/data/brick1 force
gluster volume start vol_produccion
Monitoreo y Escalado Automático (HPA)
El Horizontal Pod Autoscaler (HPA) ajusta dinámicamente el número de réplicas basándose en métricas de uso de CPU o memoria recopiladas por el Metrics Server.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Empaquetado y Despliegue con Helm
Helm actúa como el gestor de paquetes para Kubernetes, permitiendo la parametrización de manifiestos complejos mediante Charts. En su versión 3, Helm elimina la dependencia del componente servidor (Tiller), interactuando directamente con la API de Kubernetes mediante las credenciales del usuario local.
# Instalación de Helm v3
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
# Añadir repositorio y desplegar una base de datos Redis
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install redis-cache bitnami/redis \
--set architecture=replication \
--set auth.enabled=false \
--set master.persistence.enabled=false
Integración Continua con GitLab y Jenkins
La automatización del ciclo de vida de las aplicaciones se logra integrando repositorios de código con pipelines de CI/CD. GitLab actúa como repositorio de código fuente y gestor de registros de contenedores, mientras que Jenkins orquesta la construcción de imágenes y su posterior despliegue en el clúster mediante kubectl o Helm.
# Configuración inicial del repositorio en GitLab
git init
git remote add origin http://gitlab.internal.local/dev-team/microservice-api.git
git add .
git commit -m "Initial infrastructure commit"
git push -u origin main
# Ejemplo de etapa de despliegue en un Jenkinsfile
# stage('Deploy to K8s') {
# steps {
# sh 'helm upgrade --install api-release ./charts/api --set image.tag=${BUILD_NUMBER}'
# }
# }