Mr.PlanB Logo
    Volver al blog
    Kubernetes
    K3s
    Tutorial

    Cómo montar un clúster de Kubernetes en tu homelab

    10 de enero de 2024
    7 min de lectura

    Ejecutar Kubernetes en tu homelab es una forma excelente de aprender orquestación de contenedores, probar aplicaciones y adquirir competencias aplicables en entornos de producción. En esta guía desplegaremos un clúster de K3s sobre Proxmox con varios nodos y alta disponibilidad.

    Kubernetes You Got a Cluster, Now What!

    ¿Por qué K3s?

    K3s es una distribución ligera de Kubernetes que se adapta especialmente bien a los entornos de homelab. Consume solo 512MB de RAM y se instala como un único archivo binario sin dependencias complejas. Cumple al 100% con los estándares de Kubernetes oficial e incluye Traefik, CoreDNS y almacenamiento local listo para usar.

    Descripción general de la arquitectura

    Crearemos un clúster de 3 nodos con 1 nodo de plano de control que gestiona el clúster y 2 nodos worker que ejecutan las cargas de trabajo de las aplicaciones.

    ┌─────────────────┐
    │  Control Plane  │
    │   192.168.1.10  │
    └────────┬────────┘
             │
        ┌────┴────┐
        │         │
    ┌───▼───┐ ┌──▼────┐
    │Worker1│ │Worker2│
    │  .11  │ │  .12  │
    └───────┘ └───────┘
    
    Diagram of the three node K3s homelab cluster on Proxmox with one control plane node managing two worker nodes.

    Requisitos previos

    • Proxmox VE instalado y configurado
    • 3 máquinas virtuales o contenedores LXC (se recomienda Ubuntu 22.04)
    • Al menos 2GB de RAM por nodo (se recomiendan 4GB)
    • 2 núcleos de CPU por nodo
    • 20GB de almacenamiento por nodo

    Preparación de los nodos

    Crear máquinas virtuales en Proxmox

    Para cada nodo, crea una máquina virtual con la siguiente configuración:

    # CPU: 2 cores
    # RAM: 4GB
    # Disk: 20GB
    # Network: Bridge to vmbr0
    

    Instalar Ubuntu Server

    1. Arranca desde la ISO de Ubuntu Server
    2. Completa el asistente de instalación
    3. Instala el servidor OpenSSH
    4. Actualiza el sistema:
    sudo apt update && sudo apt upgrade -y
    

    Configurar direcciones IP estáticas

    Asigna a cada nodo una dirección fija editando el archivo /etc/netplan/00-installer-config.yaml:

    network:
      version: 2
      ethernets:
        ens18:
          addresses:
            - 192.168.1.10/24  # Change for each node
          gateway4: 192.168.1.1
          nameservers:
            addresses: [192.168.1.1, 8.8.8.8]
    

    Aplica la configuración:

    sudo netplan apply
    

    Desactivar swap

    Kubernetes requiere desactivar la memoria swap, así que apágala ahora y coméntala en /etc/fstab:

    sudo swapoff -a
    sudo sed -i '/ swap / s/^/#/' /etc/fstab
    

    Configurar hostnames

    Define un nombre de host único en cada uno de los tres nodos:

    # Control plane
    sudo hostnamectl set-hostname k3s-master
    
    # Worker nodes
    sudo hostnamectl set-hostname k3s-worker1
    sudo hostnamectl set-hostname k3s-worker2
    

    Luego actualiza /etc/hosts en todos los nodos:

    192.168.1.10    k3s-master
    192.168.1.11    k3s-worker1
    192.168.1.12    k3s-worker2
    

    Instalación de K3s

    Instalar el plano de control

    En el nodo maestro, ejecuta el script de instalación de K3s en modo servidor:

    curl -sfL https://get.k3s.io | sh -s - server \
      --write-kubeconfig-mode 644 \
      --disable traefik \
      --node-name k3s-master
    

    Desactivamos Traefik aquí para poder instalarlo manualmente más adelante con una configuración personalizada. Comprueba la instalación con:

    sudo kubectl get nodes
    

    A continuación, obtén el token del nodo que utilizarán los workers para unirse:

    sudo cat /var/lib/rancher/k3s/server/node-token
    

    Guarda este token, ya que lo necesitarás en los nodos worker.

    Instalar los nodos worker

    En cada nodo worker, ejecuta el script de instalación en modo agente:

    curl -sfL https://get.k3s.io | K3S_URL=https://192.168.1.10:6443 \
      K3S_TOKEN=YOUR_NODE_TOKEN \
      sh -s - agent \
      --node-name k3s-worker1  # Change for each node
    

    Sustituye YOUR_NODE_TOKEN por el token obtenido en el nodo maestro.

    Verificar el clúster

    De vuelta en el nodo maestro, lista los nodos para confirmar que los workers se han unido correctamente:

    kubectl get nodes
    

    Deberías ver los tres nodos en estado «Ready»:

    NAME          STATUS   ROLES                  AGE   VERSION
    k3s-master    Ready    control-plane,master   5m    v1.27.3+k3s1
    k3s-worker1   Ready    <none>                 2m    v1.27.3+k3s1
    k3s-worker2   Ready    <none>                 2m    v1.27.3+k3s1
    

    Configurar el acceso con kubectl

    Acceso desde el equipo local

    Para gestionar el clúster desde tu propio equipo, copia el archivo kubeconfig del nodo maestro:

    # On master node
    sudo cat /etc/rancher/k3s/k3s.yaml
    

    A continuación, crea el archivo de configuración en tu máquina local:

    mkdir -p ~/.kube
    # Paste the content and update the server IP
    nano ~/.kube/config
    

    Cambia server: https://127.0.0.1:6443 por server: https://192.168.1.10:6443, y luego comprueba la conexión desde tu equipo local:

    kubectl get nodes
    

    Instalación de componentes esenciales

    Stack of components added after a K3s cluster is running: MetalLB, Traefik, Cert Manager, Longhorn storage, and Prometheus with Grafana monitoring.

    Gestor de paquetes Helm

    Instala Helm, el gestor de paquetes de Kubernetes, en tu equipo local:

    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
    

    Balanceador de carga MetalLB

    MetalLB añade compatibilidad con servicios de tipo LoadBalancer en bare metal. Instálalo con:

    kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
    

    Luego crea una configuración de grupo de direcciones IP para que MetalLB las asigne:

    # metallb-config.yaml
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: default
      namespace: metallb-system
    spec:
      addresses:
      - 192.168.1.200-192.168.1.250
    ---
    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: default
      namespace: metallb-system
    spec:
      ipAddressPools:
      - default
    

    Guarda el archivo como metallb-config.yaml y aplícalo al clúster:

    kubectl apply -f metallb-config.yaml
    

    Controlador Ingress Traefik

    Instala Traefik mediante Helm expuesto a través de un servicio de tipo LoadBalancer:

    helm repo add traefik https://traefik.github.io/charts
    helm repo update
    
    helm install traefik traefik/traefik \
      --namespace traefik \
      --create-namespace \
      --set service.type=LoadBalancer
    

    A continuación, consulta la IP asignada por el balanceador de carga a Traefik:

    kubectl get svc -n traefik
    

    Cert-Manager

    Cert-Manager automatiza la gestión de certificados TLS, y puedes instalarlo directamente desde el manifiesto oficial:

    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml
    

    Almacenamiento Longhorn

    Longhorn proporciona almacenamiento de bloques distribuido para Kubernetes. Instálalo con Helm:

    helm repo add longhorn https://charts.longhorn.io
    helm repo update
    
    helm install longhorn longhorn/longhorn \
      --namespace longhorn-system \
      --create-namespace
    

    Para acceder al panel web de Longhorn desde tu máquina, redirige el puerto de su servicio con kubectl:

    kubectl -n longhorn-system port-forward svc/longhorn-frontend 8080:80
    

    Luego abre en tu navegador http://localhost:8080.

    Despliegue de una aplicación de prueba

    Crea un despliegue de prueba con un servicio nginx detrás de un LoadBalancer:

    # nginx-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-demo
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      type: LoadBalancer
      selector:
        app: nginx
      ports:
      - port: 80
        targetPort: 80
    

    Despliégalo:

    kubectl apply -f nginx-deployment.yaml
    kubectl get svc nginx-service
    

    A continuación puedes acceder a la aplicación utilizando la dirección IP de LoadBalancer que haya recibido el servicio.

    Monitoreo con Prometheus

    Para el monitoreo, añade el repositorio oficial de charts de la comunidad de Prometheus e instala kube-prometheus-stack:

    helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
    helm repo update
    
    helm install prometheus prometheus-community/kube-prometheus-stack \
      --namespace monitoring \
      --create-namespace
    

    Para acceder a Grafana desde tu equipo, reenvía el puerto del servicio:

    kubectl port-forward -n monitoring svc/prometheus-grafana 3000:80
    

    Inicia sesión en Grafana con las credenciales predeterminadas: admin / prom-operator.

    Buenas prácticas

    Límites de recursos

    Define siempre solicitudes (requests) y límites (limits) de recursos:

    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    

    Organización de namespaces

    Utiliza namespaces para organizar las cargas de trabajo:

    kubectl create namespace production
    kubectl create namespace development
    

    Estrategia de backup

    Para realizar copias de seguridad periódicas, añade el repositorio de Helm de VMware Tanzu e instala Velero:

    helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
    helm install velero vmware-tanzu/velero \
      --namespace velero \
      --create-namespace
    

    Resolución de problemas

    El pod no arranca

    kubectl describe pod POD_NAME
    kubectl logs POD_NAME
    

    Nodo no preparado

    kubectl describe node NODE_NAME
    sudo systemctl status k3s
    sudo journalctl -u k3s -f
    

    Problemas de red

    kubectl get pods -n kube-system
    kubectl logs -n kube-system COREDNS_POD
    

    Pasos siguientes

    • Implementar GitOps con ArgoCD
    • Configurar pipelines de CI/CD
    • Configurar el escalado horizontal automático de pods
    • Aplicar directivas de red (network policies)
    • Desplegar una malla de servicios (Istio/Linkerd)

    Conclusión

    Ahora cuentas con un clúster funcional de Kubernetes en tu homelab, lo que supone una base sólida para aprender y experimentar con tecnologías nativas de la nube.

    Recursos