Platform engineering · playbook

Kubernetes desde cero en bare metal. Reproducible en una tarde.

10 scripts secuenciados. Cilium eBPF + ArgoCD + External Secrets Operator + Hashicorp Vault + Cloudflared Zero Trust. Sin control plane gestionado, sin conocimiento tribal — solo un clúster que un compañero puede recrear antes de que se le enfríe el café.

3

Nodos control-plane

10

Scripts de bootstrap

HA

Desde el día uno

~3 h

Bootstrap completo

¿Por qué no usar Kubernetes gestionado?

Kubernetes gestionado (GKE / EKS) funciona bien hasta que la economía de tu carga se da la vuelta — egreso más pesado que CPU, una flota de servidores bare metal ya pagada, o una red privada VLAN que quieres mantener dentro del data center.

La pregunta real no era "gestionado vs self-hosted". Era: ¿podemos auto-hospedar de forma aburrida en producción y reproducible desde un repo Git? Sin `kubectl apply` manual. Sin secretos pegados en YAML. Sin una sola persona guardando el conocimiento de cómo levantar el clúster.

La vara: un compañero abre un set nuevo de servidores bare metal, corre 10 scripts en orden, y al terminar tiene un clúster idéntico a producción — mismo ingress, mismo flujo de secretos, mismo pipeline GitOps. Este playbook es mi destilación de ese bootstrap.

Stack, con razonamiento

kubeadm

Control plane

3 nodos control-plane detrás de un endpoint API load-balanced. Clásico, debuggable, sin vendor lock-in. La ceremonia extra vale la pena frente a k3s cuando HA desde el día uno es innegociable.

Cilium + Hubble

CNI — eBPF

`kubeProxyReplacement: Strict` elimina el overhead de kube-proxy; Hubble da observabilidad de red gratis. El truco en el vSwitch de Hetzner: el MTU tiene que ser 1350 para caber en el sobre de 1400 del proveedor — un día entero de depuración la primera vez.

CoreDNS

DNS

ConfigMap custom que forwardea dominios internos a los resolvers de la VLAN privada y añade hosts estáticos para servicios fuera del clúster (Postgres, Redis, etc.). Una sola fuente de verdad para resolución de nombres.

NGINX Ingress Controller

Ingress

Etiquetado a un nodo de ingress dedicado. Nada elaborado en Layer 7 — Cloudflared Zero Trust va delante, así que el edge del clúster se mantiene simple.

Cloudflared

Zero Trust ingress

Deployment en el namespace `infra`, HTTP/2 al origen. Sin load balancer público, sin IPs expuestas. Servicios internos solo alcanzables vía políticas autenticadas de Cloudflare Access. Mata toda una categoría de superficie de ataque.

ArgoCD

GitOps

Instalado por Helm, tira de un repo de deployments vía deploy key SSH. Reconciliación por webhook en cada push. AppSets por entorno. Tras el bootstrap, sin `kubectl apply` manual — nunca.

External Secrets Operator + Hashicorp Vault

Secretos

ESO lee de Vault KV v2 vía AppRoles acotados por entorno. Vault corre en un host bare metal dedicado, no en el clúster — un chicken-and-egg menos en recovery. Flujo: Vault → ESO → Kubernetes Secret → Pod. Ningún secreto toca Git.

El bootstrap en 10 scripts

Cada script es idempotente, comentado, y asume un host Ubuntu 22.04 limpio. Correr en orden. Si uno falla, arreglar y re-correr.

  1. 1-prerequisites.sh

    Setup del host

    Red, SSH, firewall, fuentes apt, container runtime (containerd).

  2. 2-initialize-kubeadm.sh

    Init del control plane

    `kubeadm init` con subnets de pod + servicio, endpoint API externo sobre un hostname load-balanced.

  3. 3-deploy-cilium.sh

    CNI

    Helm install Cilium con masquerading eBPF, Hubble UI, `kubeProxyReplacement: Strict`, MTU 1350.

  4. 3.1-join-worker-nodes.sh

    Worker join

    Genera comandos de join para workers. Etiqueta nodos de ingress para que NGINX schedulee ahí.

  5. 4-test-connectivity.sh

    Smoke test

    Despliega un pod de test por nodo y verifica ruteo cross-node + VLAN privada antes de correr nada más.

  6. 5-kubernetes-dashboard.sh

    Dashboard

    Opcional — dashboard de solo lectura detrás de Cloudflared Access.

  7. 6-dns.sh

    Config CoreDNS

    Aplica el ConfigMap con forwarders VLAN internos y hosts estáticos.

  8. 7-ingress.sh

    Ingress

    Helm chart de NGINX Ingress Controller, placement por etiqueta, TLS vía cert-manager + Cloudflare.

  9. 8-cloudflared-tunnel.sh

    Ingress Zero Trust

    Deployment de Cloudflared en `infra`, tunnel token inyectado desde Vault vía ESO.

  10. 9-app-bootstrap.sh

    Bootstrap servicios

    Namespaces + ServiceAccounts + pull secrets + workloads puente que tus apps necesiten antes de que ArgoCD tome control.

  11. 10-argocd.sh

    GitOps

    Helm-instala ArgoCD, crea projects + AppSets por entorno, configura el webhook de GitHub.

Los gotchas (apúntalos)

Cilium MTU 1350 dentro del vSwitch Hetzner 1400

El vSwitch de Hetzner envuelve los paquetes en una encapsulación extra. Cilium toma por defecto el MTU de la interfaz (1400), y los paquetes se caen en silencio tras el join. `MTU: 1350` en los values del Helm. Debe ir comentado en el script del CNI para que la próxima persona no lo re-descubra a la 1am.

enableMasqueradeToRouteSource: true

Sin esto el tráfico de pod sale con la IP del pod (que el vSwitch del proveedor no sabe rutear de vuelta). Con `true`, Cilium masquerea al IP VLAN del nodo. Cuando lo sabes es obvio; cuando no, desconcertante.

Webhook de ArgoCD requiere auth de GitHub

El namespace `argocd` necesita un webhook secret más una deploy key de GitHub App. Si el secret está mal, ArgoCD cae a polling de 3 minutos — ok para dev, doloroso en prod.

ClusterSecretStore de ESO requiere bootstrap de AppRoles

Antes de que ESO lea secretos, Vault necesita los AppRoles por entorno configurados con policies apropiadas. Automátalo con un playbook Ansible o un script de bootstrap — no lo hagas a mano la primera vez, y mucho menos la segunda.

¿Lo necesitas para tu equipo?

Hago consultoría de bootstrap Kubernetes: migraciones de gestionado a bare metal, rollouts GitOps con ArgoCD + ESO + Vault, adopción de Cilium eBPF, Cloudflared Zero Trust. Remoto, pagado — típicamente 2–6 semanas por proyecto. Basado en España (CET) hasta octubre 2026, después México (CST).

Escríbeme a vikgm.dev@gmail.com

Playbook de migraciones stateful

La otra historia de infra dura: una migración mayor de Elasticsearch en plataforma viva, cero regresión, con red de seguridad shape-compare y un workflow SPEC → Build → QA por servicio.