Files
kubernetes/cluster_init.md
2025-07-31 09:59:50 +02:00

16 KiB

0. Ejemplo de configuración de red en SUSE con NetworkManager

Aquí defines cómo se conectará tu servidor físicamente a la red en openSUSE/SLES: enlaces redundantes (bonding), VLANs para segmentar el tráfico, y bridges para conectar máquinas virtuales y pods a distintas redes. Esta configuración es la base para un clúster flexible y segmentado.

Pre-requisitos:

  • openSUSE/SLES con NetworkManager activo.
  • Interfaces físicas: em1 y em2 (ajusta según tu hardware).

1. Crear el bond (LACP 802.3ad, rápido, hash layer3+4)

nmcli con add type bond ifname bond0 mode 802.3ad con-name bond0
nmcli con mod bond0 bond.options "mode=802.3ad,miimon=100,updelay=200,downdelay=200,lacp_rate=fast,xmit_hash_policy=layer3+4"
nmcli con mod bond0 ipv4.method disabled ipv6.method ignore

2. Añadir interfaces físicas al bond

nmcli con add type ethernet ifname em1 master bond0 con-name em1
nmcli con add type ethernet ifname em2 master bond0 con-name em2
nmcli con up em1
nmcli con up em2
nmcli con up bond0

3. Crear bridges de administración y servicios

# Bridge de administración (br-admin)
nmcli con add type bridge ifname br-admin con-name br-admin
nmcli con mod br-admin ipv4.addresses 192.168.0.42/24
nmcli con mod br-admin ipv4.gateway 192.168.0.1
nmcli con mod br-admin ipv4.dns "192.168.0.1 1.1.1.1 8.8.8.8"
nmcli con mod br-admin ipv4.method manual
nmcli con up br-admin

# Bridge de servicios (br-srv)
nmcli con add type bridge ifname br-srv con-name br-srv
nmcli con mod br-srv ipv4.method disabled ipv6.method ignore
nmcli con up br-srv

4. Crear VLANs sobre el bond y unirlas a los bridges

# VLAN 10 para administración
nmcli con add type vlan ifname vlan10 dev bond0 id 10 con-name vlan10
nmcli con mod vlan10 ipv4.method disabled ipv6.method ignore
nmcli con mod vlan10 master br-admin connection.slave-type bridge
nmcli con up vlan10

# VLAN 20 para servicios
nmcli con add type vlan ifname vlan20 dev bond0 id 20 con-name vlan20
nmcli con mod vlan20 ipv4.method disabled ipv6.method ignore
nmcli con mod vlan20 master br-srv connection.slave-type bridge
nmcli con up vlan20

# VLANs 30 y 40 con IP directa
nmcli con add type vlan ifname vlan30 dev bond0 id 30 con-name vlan30
nmcli con mod vlan30 ipv4.addresses 192.168.3.2/24
nmcli con mod vlan30 ipv4.method manual
nmcli con up vlan30

nmcli con add type vlan ifname vlan40 dev bond0 id 40 con-name vlan40
nmcli con mod vlan40 ipv4.addresses 192.168.4.2/24
nmcli con mod vlan40 ipv4.method manual
nmcli con up vlan40

Ahora si: Guía definitiva de despliegue Kubernetes (openSUSE/SLES)

Revisión y correcciones basadas en el history real de despliegue

1. Prerrequisitos del sistema (SUSE)

Este paso parte de una instalación limpia de openSUSE/SLES actualizada y con permisos de administrador. Instala utilidades básicas, configura el repositorio oficial de Kubernetes y desactiva SWAP, igual que harías en Ubuntu, pero con comandos adaptados a zypper y la gestión de repositorios en SUSE.

a) Actualiza el sistema y paquetes básicos

sudo zypper refresh
sudo zypper update
sudo zypper install -y curl ca-certificates keepalived chrony

b) Añade el repositorio oficial de Kubernetes

Crea el archivo de repositorio para Kubernetes (v1.33):

cat <<EOF | sudo tee /etc/zypp/repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key
EOF

Actualiza la caché de repositorios y acepta la clave GPG cuando se te pida:

sudo zypper refresh
sudo zypper update

Cuando veas el aviso sobre la clave GPG, pulsa 'a' para aceptar siempre.

c) Configuración de Keepalived

En SRVFKVM01 (MASTER):

cat <<EOF | sudo tee /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state MASTER
    interface br-admin
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 42manabo42
    }
    virtual_ipaddress {
        192.168.0.20/24
    }
}
EOF

En los demás (BACKUP):

cat <<EOF | sudo tee /etc/keepalived/keepalived.conf
    vrrp_instance VI_1 {
        state BACKUP
        interface br-admin
        virtual_router_id 51
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 42manabo42
        }
        virtual_ipaddress {
            192.168.0.20/24
        }
    }
EOF

Después en todos:

sudo systemctl enable keepalived
sudo systemctl start keepalived

d) Sincronización horaria

En todos los servidores del cluster:

sudo systemctl enable chronyd
sudo systemctl start chronyd
sudo chronyc makestep  # Fuerza la sincronización inicial

2. Instala containerd (runtime recomendado)

containerd es el motor que gestiona los contenedores en el clúster. Kubernetes necesita un “runtime” para crear y controlar los pods, y containerd es la opción oficial y más estable.

sudo zypper install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

3. Desactiva SWAP (requisito para Kubernetes)

Kubernetes requiere que el intercambio de memoria (swap) esté desactivado. Esto evita problemas de rendimiento y estabilidad.

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

4. Prepara el kernel y sysctl y abre puertos

En este paso se habilitan módulos y parámetros de red necesarios para que Kubernetes gestione correctamente el tráfico entre pods y nodos.

sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system

En SUSE, la carga de los modulos no es persistente. Para que sea persistente hay qeu poner:

echo -e "br_netfilter\noverlay" | sudo tee /etc/modules-load.d/k8s.conf

el trafico basico que se debe permitir es:

# Básico Kubernetes
# Asocia la interfaz de red interna del clúster a la zona trusted (típicamente br-admin)
sudo firewall-cmd --zone=trusted --add-interface=br-admin --permanent
sudo firewall-cmd --zone=trusted --add-interface=vlan40 --permanent

# Abre solo en zona trusted los puertos necesarios para el clúster:
sudo firewall-cmd --zone=trusted --add-port=6443/tcp --permanent    # API Server
sudo firewall-cmd --zone=trusted --add-port=10250/tcp --permanent   # Kubelet API
sudo firewall-cmd --zone=trusted --add-port=2379/tcp --permanent    # etcd client (solo control-plane)
sudo firewall-cmd --zone=trusted --add-port=2380/tcp --permanent    # etcd peer (solo control-plane)
sudo firewall-cmd --zone=trusted --add-port=8472/udp --permanent    # Flannel VXLAN (si usas Flannel)

# Si vas a exponer servicios (Traefik, MetalLB), abre HTTP/HTTPS solo si lo necesitas en todos los nodos
# (mejor hacerlo en los nodos donde se expone tráfico externo, no en todos)
sudo firewall-cmd --zone=trusted --add-port=80/tcp --permanent
sudo firewall-cmd --zone=trusted --add-port=443/tcp --permanent

# (Opcional) Si usas NodePort, abre el rango solo si usas ese tipo de servicio:
sudo firewall-cmd --zone=trusted --add-port=30000-32767/tcp --permanent

# Recarga las reglas
sudo firewall-cmd --reload

5. Instala los componentes de Kubernetes (kubectl, kubelet, kubeadm)

Instala en un solo paso las utilidades principales:

sudo zypper install -y kubectl kubelet kubeadm

Edita /etc/sysconfig/kubelet para poner la dirección IP que tendrá el nodo:

KUBELET_EXTRA_ARGS=--node-ip=192.168.4.1   # <-- Dirección ip de cada nodo en la Vlan interna del cluster

Activa kubelet para que se inicie automáticamente:

sudo systemctl enable kubelet
sudo systemctl start kubelet

Es normal que el servicio kubelet falle en bucle hasta que inicialices el clúster con kubeadm init. El error más frecuente es:

  • "failed to load Kubelet config file, path: /var/lib/kubelet/config.yaml"

Tras ejecutar kubeadm init, kubelet arrancará correctamente.


5b. (Opcional) Habilita cgroup v2 (solo SLES si necesario)(Si no te funciona, SI lo necesitas)

Si necesitas cgroup v2 en SLES, añade esto al arranque del kernel (edita /etc/default/grub):

GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=1 ..."

Y regenera el grub:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Reinicia para aplicar los cambios.


6. Inicializa el clúster (openSUSE/SLES)

Este paso crea el clúster de Kubernetes en el nodo principal (control-plane) sobre openSUSE/SLES. Aquí defines la red interna para los pods y la interfaz/VLAN física para el tráfico overlay del clúster, según tu diseño.


a) Inicializa el clúster especificando red de pods, la IP interna y la VIP

Importante:

  • Usa la opción --apiserver-advertise-address para forzar que el nodo control-plane escuche en la IP de la VLAN interna de clúster (ejemplo: 192.168.4.x en tu VLAN 40).
  • Usa --control-plane-endpoint para indicar la IP virtual compartida (VIP) gestionada por Keepalived. Debe ser una IP accesible por todos los nodos control-plane (ejemplo: 192.168.0.20).
  • Usa --apiserver-cert-extra-sans para añadir la VIP (y/o el FQDN) como SAN en el certificado TLS del API server, así todos los nodos confían en esa IP/nombre.
  • Usa --pod-network-cidr=10.244.0.0/16 si vas a usar Flannel como CNI (ajusta si usas otro CNI).
sudo kubeadm init \
  --apiserver-advertise-address=192.168.4.1 \
  --control-plane-endpoint="192.168.0.20:6443" \
  --apiserver-cert-extra-sans="192.168.0.20" \
  --pod-network-cidr=10.244.0.0/16 \
  --upload-certs

Cambia 192.168.4.1 por la IP interna del nodo donde ejecutas el comando (en la VLAN de clúster) y 192.168.0.20 por la IP VIP gestionada por Keepalived.


c) Configura kubectl para tu usuario

Permite usar el comando kubectl como usuario normal copiando la configuración de administración del clúster a tu carpeta personal.

En el nodo master (SRVFKVM01)

mkdir -p $HOME/.kube
cd /etc/kubernetes
sudo cp -i admin.conf $HOME/.kube/config
sudo scp config admin.c3s@192.168.0.4X:/home/admin.c3s/admin.conf    #a todos los nodos
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Añadir un nodo fuera de plazo.

Para añadir un nodo con posterioridad y con intención de que se convierta en controller, debemos limparlo, en los archivos donde se almacena datos del cluster y el nodo, parar el servicio y reset de kubelet reset -f

En el nodo principal ejecutar:

kubeadm token create --print-join-command --description "ALgo significativo"

Con esto generaremos un nuevo token podemos lmitarlo con TTL 5 h (horas). Pero solo nos vale para unir un worker.

Si queremos unir un controller hay que añadir el certificado de la CA, seconsigue con:

kubeadm init phase upload-certs --upload-certs

Si copiamos ambos resultados y lo unimos en un solo comando join conseguiremos el objetivo. Explicado más abajo.

d) Instala la red de pods (Flannel) usando la VLAN interna del clúster

Kubernetes solo define la infraestructura; necesitas un complemento de red (CNI) para que los pods puedan comunicarse entre sí. Flannel es la opción más sencilla y compatible, y puedes configurarla para usar una interfaz/VLAN específica para el tráfico overlay (muy recomendable si segmentas redes en tu clúster).

¡ATENCIÓN! CNI Y PLUGINS:

Antes de aplicar Flannel, asegúrate de tener los plugins CNI instalados en /opt/cni/bin/ (en SUSE esto NO siempre lo hace el paquete de Flannel):

CNI_VERSION="v1.4.1"
ARCH="amd64"
sudo curl -Lo cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz
sudo mkdir -p /opt/cni/bin
sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz

Verifica que existen al menos:

  • /opt/cni/bin/loopback
  • /opt/cni/bin/flannel
  • /opt/cni/bin/bridge y otros

Corrige permisos si hace falta:

sudo chmod +x /opt/cni/bin/*
sudo chown root:root /opt/cni/bin/*

Luego sí aplica Flannel:

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

e) Comprueba que Flannel funciona

kubectl -n kube-flannel get pods -o wide

Todos los pods deben estar en estado Running.

Si no levanta, verifica logs y revisa /opt/cni/bin/:

  • Los binarios deben ser para la arquitectura correcta (x86_64/amd64).
  • Deben tener permisos de ejecución y ser propiedad de root.

f) Une el resto de nodos control-plane

En los demás nodos control-plane (tras configurar Keepalived y tener la VIP activa):

sudo kubeadm join 192.168.0.20:6443 \
    --token <TOKEN> \
    --discovery-token-ca-cert-hash <HASH> \
    --control-plane \
    --certificate-key <CERTIFICATE_KEY> \
    --apiserver-advertise-address=192.168.4.2

Importante: Cambia la IP 192.168.4.2 por la correspondiente a cada servidor control-plane que estés uniendo.

Recuerda usar los valores correctos de token, hash y certificate-key que te dará el comando kubeadm init o puedes volver a consultar desde el nodo principal:

kubeadm token create --print-join-command --control-plane

Credenciales para todos (lo que le gusta al jefe):

mkdir -p $HOME/.kube
cd
sudo cp -i admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

EXTRA: Si te ha caducado el TOKEN, o no lo guardaste

Cuando el token de unión (kubeadm join) ha caducado, sigue estos pasos en el nodo principal (control-plane) para generar un nuevo token y el comando actualizado:

# 1. Sube los certificados y obtén la nueva clave de certificado (certificate-key)
sudo kubeadm init phase upload-certs --upload-certs

La salida mostrará la nueva certificate key, necesaria para añadir un nuevo nodo de control-plane.

# 2. Genera un nuevo token y muestra el comando kubeadm join listo para usar
sudo kubeadm token create --print-join-command

La salida mostrará el comando kubeadm join con el nuevo token y el hash actual del CA.

Ejemplo de salidas:

[upload-certs] Using certificate key:
588ee9d0441c0aea36b2a2a638beae4cfa81dd3498eb61205c8496f344f6c55d

kubeadm join 192.168.0.20:6443 --token s9nlsp.gasv66tkc43zpiok --discovery-token-ca-cert-hash sha256:d41f0edb90c66c0555bdf4feca55f1e69019764be0fcd649a254e99ff124568f

Comando completo para unir un nodo como control-plane

Añade los parámetros --control-plane --certificate-key <certificate-key> --apiserver-advertise-address=192.168.4.2 al final del comando kubeadm join generado. Usando el ejemplo anterior, el comando final sería:

sudo kubeadm join 192.168.0.20:6443 \
  --token s9nlsp.gasv66tkc43zpiok \
  --discovery-token-ca-cert-hash sha256:d41f0edb90c66c0555bdf4feca55f1e69019764be0fcd649a254e99ff124568f \
  --control-plane \
  --certificate-key 588ee9d0441c0aea36b2a2a638beae4cfa81dd3498eb61205c8496f344f6c55d \
  --apiserver-advertise-address=192.168.4.2

Recuerda: Cambia 192.168.4.2 por la IP real del nodo que se está uniendo.


Con esto podrás unir cualquier nodo extra como nuevo control-plane, incluso cuando el token original haya caducado.


Troubleshooting y buenas prácticas extra

  • Si ves errores con el loopback CNI (exec format error, permission denied, etc.), borra el contenido de /opt/cni/bin/ y vuelve a instalar los plugins.

  • Siempre revisa que el módulo br_netfilter está cargado y los sysctl activos (lsmod | grep br_netfilter).

  • Si el nodo aparece como NotReady, revisa /etc/cni/net.d/, los logs de kubelet, y repite la reinstalación del CNI.

  • Si limpias todo y reinicias, repite estos pasos:

    • Reinstala CNI plugins
    • Aplica Flannel
    • Reinicia kubelet