Guía de Instalación de kubeadm
Guía paso a paso para instalar kubeadm en Linux sin gestor de paquetes.
¿Qué es kubeadm?
kubeadm es una herramienta oficial de Kubernetes que permite crear clústeres de forma sencilla mediante dos comandos principales:
kubeadm init→ Inicializa el nodo maestro (control plane)kubeadm join→ Une nodos trabajadores al clúster
Componentes que instalaremos
| Componente | Función |
|---|---|
| kubeadm | Herramienta para crear y gestionar el clúster |
| kubelet | Agente que corre en cada nodo y gestiona los pods/contenedores |
| kubectl | Cliente de línea de comandos para interactuar con el clúster |
Paso 1: Configurar Swap
¿Por qué? → El kubelet por defecto no arranca si detecta swap activo, ya que puede afectar al rendimiento y la predicción de recursos de los contenedores.
1
2
3
4
5
# Desactivar swap temporalmente
sudo swapoff -a
# Desactivar swap permanentemente (comentar línea de swap en fstab)
sudo sed -i '/ swap / s/^/#/' /etc/fstab
Paso 2: Instalar un Container Runtime
¿Por qué? → Kubernetes necesita un runtime de contenedores para ejecutar los pods. Kubernetes usa la interfaz CRI (Container Runtime Interface) para comunicarse con el runtime.
Instalar containerd (recomendado)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# En Debian/Ubuntu
sudo apt-get update
sudo apt-get install -y containerd
# Crear configuración por defecto
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# Habilitar SystemdCgroup (importante para kubelet)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# Reiniciar containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
Paso 3: Cargar módulos del kernel necesarios
¿Por qué? → Kubernetes necesita ciertos módulos del kernel para el networking entre contenedores.
1
2
3
4
5
6
7
8
9
# Crear archivo de configuración para cargar módulos al arranque
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# Cargar módulos ahora
sudo modprobe overlay
sudo modprobe br_netfilter
Explicación de los módulos:
overlay→ Sistema de archivos usado por los contenedoresbr_netfilter→ Permite que el tráfico de red de bridges pase por iptables
Paso 4: Configurar parámetros de red del kernel
¿Por qué? → Permite que los paquetes de red sean procesados correctamente entre pods.
1
2
3
4
5
6
7
8
9
# Configurar parámetros sysctl
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
# Aplicar parámetros sin reiniciar
sudo sysctl --system
Explicación:
bridge-nf-call-iptables→ El tráfico del bridge pasa por iptables (necesario para Network Policies)ip_forward→ Permite que el nodo actúe como router (necesario para routing entre pods)
Paso 5: Instalar kubeadm, kubelet y kubectl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1. Instalar plugins CNI (necesarios para la red de pods)
CNI_PLUGINS_VERSION="v1.3.0"
ARCH="amd64"
DEST="/opt/cni/bin"
sudo mkdir -p "$DEST"
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${ARCH}-${CNI_PLUGINS_VERSION}.tgz" | sudo tar -C "$DEST" -xz
# 2. Definir directorio de descarga
DOWNLOAD_DIR="/usr/local/bin"
sudo mkdir -p "$DOWNLOAD_DIR"
# 3. Instalar kubeadm y kubelet
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
ARCH="amd64"
cd $DOWNLOAD_DIR
sudo curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet}
sudo chmod +x {kubeadm,kubelet}
# 4. Configurar servicio systemd para kubelet
RELEASE_VERSION="v0.16.2"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | \
sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | \
sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
# 5. Instalar kubectl
cd ~
curl -LO "https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
rm kubectl
Paso 6: Habilitar el servicio kubelet
¿Por qué? → El kubelet debe estar activo para que kubeadm pueda configurarlo durante la inicialización del clúster.
1
sudo systemctl enable --now kubelet
Nota: En este punto el kubelet estará en un bucle de reinicio (crashloop). Esto es normal porque está esperando instrucciones de kubeadm.
Paso 7: Crear enlace simbólico para plugins CNI
¿Por qué? → Algunos componentes (como CoreDNS) buscan los plugins CNI en /usr/lib/cni, pero la instalación estándar los coloca en /opt/cni/bin. Sin este enlace, los pods de sistema como CoreDNS pueden quedarse en estado ContainerCreating o CrashLoopBackOff.
Ejecutar en todos los nodos (control-plane y workers):
1
2
3
4
5
# Crear directorio si no existe
sudo mkdir -p /usr/lib/cni
# Crear enlaces simbólicos a los plugins CNI
sudo ln -s /opt/cni/bin/* /usr/lib/cni/
Si ya habías inicializado el clúster y tienes pods en estado fallido:
1
2
3
4
5
6
7
8
# En el nodo control-plane, reiniciar kubelet
sudo systemctl restart kubelet
# Eliminar pods del sistema para que se regeneren
kubectl delete pod -n kube-system --all
# Si tienes ingress-nginx instalado
kubectl delete pod -n ingress-nginx --all
Verificación final
Antes de ejecutar kubeadm init, verifica que todo esté listo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Verificar que los módulos están cargados
lsmod | grep br_netfilter
lsmod | grep overlay
# Verificar parámetros de red
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward
# Verificar que swap está desactivado
free -h
# Verificar que el runtime está funcionando
sudo systemctl status containerd
# Verificar que los enlaces CNI existen
ls -la /usr/lib/cni/
# Verificar versiones instaladas
kubeadm version
kubelet --version
kubectl version --client
Siguientes pasos
Una vez completada la instalación, puedes:
- Inicializar el nodo maestro:
1
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
- Configurar kubectl para tu usuario:
1 2 3
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
- Instalar un plugin de red (CNI):
1 2
# Flannel kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
- Instalar NGINX Ingress Controller:
1 2 3 4
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/baremetal/deploy.yaml # Verificar que está corriendo kubectl get pods -n ingress-nginx
- Unir nodos worker al clúster:
1 2
# Usar el comando que devuelve kubeadm init kubeadm join <master-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
Comandos útiles de kubeadm
| Comando | Descripción |
|---|---|
kubeadm init |
Inicializa el control plane |
kubeadm join |
Une un nodo al clúster |
kubeadm reset |
Deshace cambios de init/join |
kubeadm token |
Gestiona tokens de bootstrap |
kubeadm upgrade |
Actualiza el clúster |
kubeadm certs |
Gestiona certificados |
kubeadm version |
Muestra la versión |
Balanceador de carga con HAProxy
Para distribuir el tráfico entre los nodos worker, puedes usar HAProxy en una máquina separada.
1. Instalar HAProxy
1
2
sudo apt-get update
sudo apt-get install -y haproxy
2. Obtener el NodePort del ingress
Desde el master:
1
kubectl get svc -n ingress-nginx ingress-nginx-controller
Verás algo como:
1
2
NAME TYPE CLUSTER-IP PORT(S)
ingress-nginx-controller NodePort 10.96.x.x 80:31080/TCP,443:31443/TCP
Anota los puertos (en el ejemplo: 31080 para HTTP, 31443 para HTTPS).
3. Configurar HAProxy
Edita /etc/haproxy/haproxy.cfg:
1
sudo nano /etc/haproxy/haproxy.cfg
Añade al final (cambia los NodePorts e IPs por los tuyos):
#---------------------------------------------------------------------
# Frontend HTTP
#---------------------------------------------------------------------
frontend http_front
bind *:80
default_backend http_back
#---------------------------------------------------------------------
# Frontend HTTPS
#---------------------------------------------------------------------
frontend https_front
bind *:443
mode tcp
default_backend https_back
#---------------------------------------------------------------------
# Backend HTTP - Workers de Kubernetes
#---------------------------------------------------------------------
backend http_back
balance roundrobin
server k8s-worker1 <IP_WORKER1>:31080 check
server k8s-worker2 <IP_WORKER2>:31080 check
#---------------------------------------------------------------------
# Backend HTTPS - Workers de Kubernetes
#---------------------------------------------------------------------
backend https_back
mode tcp
balance roundrobin
server k8s-worker1 <IP_WORKER1>:31443 check
server k8s-worker2 <IP_WORKER2>:31443 check
#---------------------------------------------------------------------
# Estadísticas (opcional)
#---------------------------------------------------------------------
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
Reemplaza:
<IP_WORKER1>→ IP de k8s-worker1<IP_WORKER2>→ IP de k8s-worker231080y31443→ Los NodePorts que obtuviste
4. Reiniciar HAProxy
1
2
3
4
5
6
# Verificar sintaxis
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
# Reiniciar y habilitar
sudo systemctl restart haproxy
sudo systemctl enable haproxy
5. Configurar acceso
Añade en el /etc/hosts de tu máquina cliente:
1
<IP_HAPROXY> django-tutorial.local
Luego accede a http://django-tutorial.local.
6. Verificar el balanceo
Panel de estadísticas:
Accede a http://<IP_HAPROXY>:8404/stats para ver el estado de los backends.
Probar con curl:
1
curl -H "Host: django-tutorial.local" http://<IP_HAPROXY>
Ver logs de los pods:
1
kubectl logs -f -l app=django-tutorial -n django-tutorial
Troubleshooting común
CoreDNS o pods del sistema no arrancan (ContainerCreating)
Problema típico: los plugins CNI están en /opt/cni/bin pero se buscan en /usr/lib/cni.
1
2
3
4
5
# Ver el estado de los pods del sistema
kubectl get pods -n kube-system
# Si CoreDNS está en ContainerCreating, verificar logs
kubectl describe pod -n kube-system -l k8s-app=kube-dns
Solución (ejecutar en todos los nodos):
1
2
3
4
5
6
sudo mkdir -p /usr/lib/cni
sudo ln -s /opt/cni/bin/* /usr/lib/cni/
# En el control-plane
sudo systemctl restart kubelet
kubectl delete pod -n kube-system --all
El kubelet no arranca
1
2
# Ver logs del kubelet
journalctl -xeu kubelet
Problemas de red
1
2
3
4
5
# Verificar que los módulos están cargados
lsmod | grep br_netfilter
# Si no están, cargarlos manualmente
sudo modprobe br_netfilter
Swap activo
1
2
3
4
5
# Verificar swap
swapon --show
# Desactivar
sudo swapoff -a