Kubernetes

☸️ Arquitectura y orquestación de Kubernetes

Cobertura de versiones Este artículo cubre Kubernetes v1.28+. Los comandos y las API pueden diferir para versiones de clúster anteriores. Verifique siempre con kubectl version.

Kubernetes (K8s) es una plataforma de orquestación de contenedores de código abierto desarrollada por Google y ahora mantenida por Cloud Native Computing Foundation (CNCF). Automatiza la implementación, el escalado y la gestión de aplicaciones en contenedores en grupos de máquinas.

Descripción general de la arquitectura

Un clúster de Kubernetes se compone de un plano de control y uno o más nodos trabajadores. El plano de control administra el estado del clúster, mientras que los nodos trabajadores ejecutan las cargas de trabajo de sus aplicaciones.

Componentes del plano de control

  • kube-apiserver: la interfaz de usuario de la API de Kubernetes. Todos los comandos de kubectl y los componentes internos se comunican a través de él.
  • etcd: un almacén clave-valor de alta disponibilidad que conserva todos los datos de configuración y estado del clúster.
  • kube-scheduler: detecta pods no programados y los asigna a nodos según los requisitos de recursos, las reglas de afinidad y las políticas.
  • kube-controller-manager: ejecuta bucles de controlador que concilian el estado actual del clúster con el estado deseado.
  • cloud-controller-manager: se integra con la API del proveedor de nube subyacente para balanceadores de carga, volúmenes y administración de nodos.

Componentes del nodo

  • kubelet: un agente en cada nodo que garantiza que los contenedores se ejecuten en Pods como se declara en PodSpecs.
  • kube-proxy: mantiene reglas de red en nodos que utilizan iptables o IPVS para habilitar la comunicación del servicio.
  • Tiempo de ejecución de contenedores: el software responsable de ejecutar contenedores (containerd, CRI-O).

Pods y cargas de trabajo

Un Pod es la unidad implementable más pequeña de Kubernetes: un grupo de uno o más contenedores que comparten red y almacenamiento. Las cápsulas son efímeras por diseño; Los controladores gestionan su ciclo de vida.

yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: production
  labels:
    app: nginx
    version: "1.25"
spec:
  containers:
    - name: nginx
      image: nginx:1.25-alpine
      ports:
        - containerPort: 80
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"
      livenessProbe:
        httpGet:
          path: /healthz
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 15
      readinessProbe:
        httpGet:
          path: /ready
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 10

Implementaciones

Una Implementación proporciona actualizaciones declarativas para Pods y ReplicaSets, lo que permite actualizaciones continuas, reversiones y escalado.

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  namespace: production
  labels:
    app: api-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: api-server
        version: "2.1.0"
    spec:
      containers:
        - name: api
          image: registry.maxiscomputers.com/api-server:2.1.0
          ports:
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: api-config
            - secretRef:
                name: api-secrets
          resources:
            requests:
              cpu: "250m"
              memory: "512Mi"
            limits:
              cpu: "1"
              memory: "1Gi"

Servicios y redes

Los servicios proporcionan puntos finales de red estables para un conjunto de Pods. Dado que los Pods son efímeros y sus IP cambian, los Servicios utilizan selectores de etiquetas para abstraerlos y exponerlos.

Tipos de servicio

  • IP de clúster: predeterminado. Expone el servicio en una IP interna del clúster. Solo accesible dentro del clúster.
  • NodePort: expone el servicio en la IP de cada nodo en un puerto estático (30000–32767).
  • LoadBalancer: crea un equilibrador de carga externo en proveedores de nube. Asigna una IP pública.
  • ExternalName: asigna el servicio a un nombre DNS fuera del clúster.
yaml
apiVersion: v1
kind: Service
metadata:
  name: api-service
  namespace: production
spec:
  selector:
    app: api-server
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.maxiscomputers.com
      secretName: api-tls-secret
  rules:
    - host: api.maxiscomputers.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80

Almacenamiento

Kubernetes abstrae el almacenamiento a través de PersistentVolumes (PV), PersistentVolumeClaims (PVC) y StorageClasses. ConfigMaps y Secrets se utilizan para los datos de configuración.

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: gp3-encrypted
  resources:
    requests:
      storage: 50Gi
---
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: api-config
  namespace: production
data:
  APP_ENV: "production"
  LOG_LEVEL: "warn"
  API_PORT: "8080"
  DB_HOST: "postgres-service.production.svc.cluster.local"

RBAC y seguridad

El control de acceso basado en roles (RBAC) restringe quién puede realizar qué operaciones y en qué recursos. Utiliza cuatro objetos clave: Role, ClusterRole, RoleBinding y ClusterRoleBinding.

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cicd-deployer
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployer-role
  namespace: production
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "update", "patch"]
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cicd-deployer-binding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: cicd-deployer
    namespace: production
roleRef:
  kind: Role
  name: deployer-role
  apiGroup: rbac.authorization.k8s.io

Gráficos de timón

Helm es el administrador de paquetes de Kubernetes. Los gráficos agrupan los manifiestos de Kubernetes en paquetes versionados y reutilizables con soporte para plantillas.

bash
helm install my-release ./charts/api-server \
  --namespace production \
  --create-namespace \
  --values values.production.yaml \
  --set image.tag=2.1.0

# Upgrade with zero-downtime
helm upgrade my-release ./charts/api-server \
  --namespace production \
  --values values.production.yaml \
  --set image.tag=2.2.0 \
  --atomic \
  --timeout 5m

# Rollback to previous version
helm rollback my-release 1 --namespace production

# List all releases
helm list --all-namespaces

Referencia de kubectl

Comandos kubectl esenciales para las operaciones diarias del clúster:

bash
kubectl config get-contexts
kubectl config use-context prod-cluster
kubectl config set-context --current --namespace=production

# --- Pod Operations ---
kubectl get pods -n production -o wide
kubectl describe pod api-server-7d6f8b9c-xkp2l -n production
kubectl logs -f api-server-7d6f8b9c-xkp2l -n production --tail=100
kubectl exec -it api-server-7d6f8b9c-xkp2l -n production -- /bin/sh

# --- Deployment Operations ---
kubectl rollout status deployment/api-server -n production
kubectl rollout history deployment/api-server -n production
kubectl rollout undo deployment/api-server -n production
kubectl scale deployment api-server --replicas=5 -n production

# --- Resource Inspection ---
kubectl top nodes
kubectl top pods -n production
kubectl get events -n production --sort-by=.metadata.creationTimestamp

# --- Apply & Delete ---
kubectl apply -f ./manifests/ --dry-run=client
kubectl apply -f ./manifests/
kubectl delete -f ./manifests/

Mejores prácticas de producción

Límites de recursos Establezca siempre solicitudes/límites de CPU y memoria en cada contenedor. Los contenedores ilimitados pueden desestabilizar todo el nodo.

  • Utilice espacios de nombres para aislar entornos (desarrollo, preparación, producción) dentro del mismo clúster.
  • Habilite los presupuestos de interrupción de pods (PDB) para garantizar una disponibilidad mínima durante las actualizaciones continuas y los drenajes de nodos.
  • Utilice Horizontal Pod Autoscaler (HPA) con métricas de CPU/memoria y métricas personalizadas a través de KEDA para escalado dinámico.
  • Secretos seguros con administradores de secretos externos (AWS Secrets Manager, HashiCorp Vault) en lugar de Kubernetes Secrets codificados en base64.
  • Implementar políticas de red para restringir la comunicación entre pods y aplicar redes de confianza cero.
  • Utilice sondas de preparación y actividad en todas las cargas de trabajo para evitar el enrutamiento del tráfico a Pods en mal estado.
  • Monitorear con Prometheus + Grafana y configurar alertas sobre métricas SLI/SLO.
  • Etiquete todos los recursos con etiquetas app, version, environment y managed-by para observabilidad y atribución de costos.

Consejo profesional Utilice el complemento kubectl neat para eliminar los campos administrados por clúster de los manifiestos al exportar recursos para repositorios de GitOps.