Desplegar infraestructura de Kubernetes en equipos Linux Ubuntu Server 24, con un master y dos nodos workers.
Requisitos para desplegar infraestructura de Kubernetes en Linux
Necesitaremos disponer de tres equipos con el sistema operativo Linux Ubuntu Server 24, uno de ellos será el master (el principal) y los otros dos los nodos workers. En el siguiente enlace mostramos cómo instalar Linux Ubuntu Server 24 en una máquina virtual:
Los equipos que componen el clúster deberán tener, al menos, dos vCPU:

Por lo tanto, dispondremos de los siguientes equipos con Linux Ubuntu Server 24 (para despliegue en un entorno de pruebas):
| Equipo | Uso | CPU | RAM | IP red interna | IP puente |
| srvmaster | Master, nodo principal del clúster | 4 | 6GB | 192.168.100.2 | 192.168.1.88 |
| srvworker1 | Nodo 1 esclavo worker del clúster | 4 | 6GB | 192.168.100.3 | 192.168.1.90 |
| srvworker2 | Nodo 2 esclavo worker del clúster | 4 | 6GB | 192.168.100.4 | 192.168.1.91 |
Los tres equipos deben tener UUID diferente y MAC diferente. Esto es importante, de lo contrario, el proceso de instalación puede dar error. Para obtener el UUID del equipo, podemos ejecutar el siguiente comando:
|
1 |
sudo cat /sys/class/dmi/id/product_uuid |
Realizaremos una actualización del sistema en los tres equipos, ejecutando los comandos:
|
1 2 |
sudo apt update sudo apt upgrade |
Se debe desactivar el uso de swap, comprobaremos si está activo con el comando:
|
1 |
swapon --show |
En caso de devolver una línea indicará que está activa, desactivaremos el uso de swap con el comando:
|
1 |
sudo swapoff -v /swap.img |
Y la desactivamos también en el arranque (de forma permanente), ejecutando el comando:
|
1 |
sudo sed -i '/swap/s/^/#/' /etc/fstab |
El comando anterior comenta la línea /swap/s… del fichero /etc/fstab.

Instalamos Docker en los tres nodos:
|
1 |
sudo apt-get install docker.io -y |
Activamos Google API KEY:
|
1 |
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - |
|
1 2 3 |
sudo apt-get install -y apt-transport-https ca-certificates curl gpg curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg - dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg |
|
1 |
sudo apt-get install gpg |
|
1 |
sudo mkdir -p -m 755 /etc/apt/keyrings |
Add Kubernetes apt repository:
|
1 |
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list |
|
1 |
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg |
|
1 2 |
sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl |
Prevent automatic updates/removals of Kubernetes packages.
|
1 |
sudo apt-mark hold kubelet kubeadm kubectl |
Para permitir la comunicación entre Pods a través de diferentes redes, el sistema debe poder enrutar el tráfico entre ellos. Esto se puede lograr habilitando el reenvío de IP. Sin el reenvío de IP, los contenedores no podrán comunicarse con recursos fuera de su espacio de nombres de red, lo que limitaría su funcionalidad y utilidad.
Para habilitar el reenvío de IP, establezca el valor de net.ipv4.ip_forward en .1
|
1 |
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf |
Aplicaremos los cambios con:
|
1 |
sudo sysctl -p |
overlay proporciona soporte para el sistema de archivos superpuesto. OverlayFS es un tipo de sistema de archivos de unión utilizado por los tiempos de ejecución del contenedor para superponer el sistema de archivos raíz del contenedor sobre el sistema de archivos host.
br_netfilter El módulo proporciona soporte para el filtrado de paquetes en redes de puentes Linux en función de varios criterios, como la dirección IP de origen y destino, los números de puerto y el tipo de protocolo.
Comprobamos si estos módulos está cargados/habilitados en el sistema, con:
|
1 |
sudo lsmod | grep -E "overlay|br_netfilter" |
Si no devuelve nada indica que no están cargados, para cargarlo ejecutaremos:
Del mismo modo, habilite el filtro de red de puente del kernel de Linux para pasar el tráfico de puente a iptables para su filtrado. Esto significa que los paquetes que se puentean entre las interfaces de red se pueden filtrar usando iptables/ip6tables, como si fueran paquetes enrutados.
|
1 2 |
echo 'overlay br_netfilter' | sudo tee /etc/modules-load.d/kubernetes.conf |
Y:
|
1 2 |
sudo modprobe overlay sudo modprobe br_netfilter |
Del mismo modo, habilite el filtro de red de puente del kernel de Linux para pasar el tráfico de puente a iptables para su filtrado. Esto significa que los paquetes que se puentean entre las interfaces de red se pueden filtrar usando iptables/ip6tables, como si fueran paquetes enrutados.
|
1 2 3 4 |
sudo tee -a /etc/sysctl.conf << 'EOL' net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOL |
Aplicamos los cambios con:
|
1 |
sudo sysctl -p |

Instalaremos ahora Containerd Runtime en todos los nodos (master y workers). Para ello usaremos los repositorios APT de Docker Engine, ejecutando:
|
1 2 3 4 |
sudo apt install apt-transport-https \ ca-certificates curl \ gnupg-agent \ software-properties-common |
|
1 |
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - |
|
1 |
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" |
Actualizamos la caché de paquetes:
|
1 |
sudo apt update |
Instalaremos Containerd Runtime:
|
1 |
sudo apt install -y containerd.io docker-ce docker-ce-cli |
Creamos la carpeta:
|
1 |
sudo mkdir -p /etc/systemd/system/docker.service.d |
Creamos el fichero de configuración:
|
1 2 3 4 5 6 7 8 9 10 |
sudo tee /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" } EOF |
Iniciar y habilitar servicios:
|
1 2 3 |
sudo systemctl daemon-reload sudo systemctl restart docker sudo systemctl enable docker |
Iniciamos el servicio kubelet en el nodo master, ejecutar en el master:
Ahora debemos inicializar la máquina que ejecutará los componentes del control plane, que incluye etcd (la base de datos del clúster) y el servidor API.
Hacemos un pull de las imágenes de los contenedores:
|
1 |
sudo kubeadm config images pull |

Si se produce el siguiente error al iniciar el pull con el comando anterior:
|
1 2 3 4 |
I1226 19:05:03.827067 16120 version.go:256] remote version is much newer: v1.32.0; falling back to: stable-1.28 failed to pull image "registry.k8s.io/kube-apiserver:v1.28.15": output: time="2024-12-26T19:05:04Z" level=fatal msg="validate service connection: validate CRI v1 image API for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.ImageService" , error: exit status 1 To see the stack trace of this error execute with --v=5 or higher |
Seguiremos los siguientes pasos para solucionarlo:
|
1 2 3 4 5 |
sudo mv /etc/containerd/config.toml /etc/containerd/config.bak sudo containerd config default | sudo tee /etc/containerd/config.tomlsudo containerd config default | sudo tee /etc/containerd/config.toml sudo systemctl restart containerd |
|
1 2 3 4 |
echo """ > runtime-endpoint: unix:///run/containerd/containerd.sock > image-endpoint: unix:///run/containerd/containerd.sock > """ | sudo tee /etc/crictl.yaml |
Creamos el clúster:
|
1 |
sudo kubeadm init --pod-network-cidr=10.20.0.0/16 --upload-certs --control-plane-endpoint=srvmaster |

Creamos la carpeta del cluster:
|
1 |
mkdir -p $HOME/.kube |
Copie el archivo de configuración de administración de Kubernetes en el directorio del clúster creado anteriormente.
|
1 |
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config |
Establezca la propiedad adecuada para el archivo de configuración del clúster.:
|
1 |
sudo chown $(id -u):$(id -g) $HOME/.kube/config |
Verifique el estado del clúster de Kubernetes;:
|
1 |
kubectl get nodes |
Para obtener la dirección del panel de control:
|
1 |
kubectl cluster-info |
Indicando además el comando con el token para añadir nodos:

Cgroup (grupos de control) es una característica del kernel de Linux que permite el aislamiento, la priorización y la supervisión de los recursos del sistema, como la CPU, la memoria y la E/S de disco para un grupo de procesos. Kubernetes (kubelet y tiempo de ejecución de contenedores, como containerd) utiliza controladores cgroup para interactuar con grupos de control con el fin de administrar y establecer límites para los recursos asignados a los contenedores.
Kubernetes admite tres tipos de controladores Cgroup;
cgroupfs(control groups filesystem): This is the default cgroup driver used by Kubernetes kubelet to manage resources for containers.systemd: This is the default initialization system and service manager in some Linux systems. it offers functions such as starting of daemons, keeping track of processes using Linux cgroups etc.
Para los sistemas que usan Systemd como su sistema de inicio predeterminado, se recomienda usar el controlador cgroup systemd para Kubernetes en lugar de cgroupfs.
El archivo de configuración predeterminado para containerd es /etc/containerd/config.toml. Cuando containerd se instala desde repositorios APT de Docker, este archivo se crea con pequeñas configuraciones. Si se instala desde los binarios oficiales, no se crea el archivo de configuración containerd.
De cualquier manera, actualice el archivo de configuración containerd ejecutando el siguiente comando:
|
1 |
[ -d /etc/containerd ] || sudo mkdir /etc/containerd |
|
1 |
containerd config default | sudo tee /etc/containerd/config.toml |
Obtendrá una configuración por defecto.
Una vez que genere la configuración predeterminada, debe habilitar systemd cgroup para el tiempo de ejecución del contenedor de bajo nivel containerd, runc, cambiando el valor de SystemdCgroup de false a true.
|
1 |
sudo sed -i '/SystemdCgroup/s/false/true/' /etc/containerd/config.toml |
e recomienda utilizar «registry.k8s.io/pause:3.9» como imagen del sandbox del CRI. Pause Container Image es una imagen de contenedor minimalista que permite a containerd proporcionar aislamiento de red para pods en Kubernetes. Containerd usa pausa:3.8.
Para ello, ejecutaremos:
|
1 |
sudo sed -i '/pause:3.8/s/3.8/3.9/' /etc/containerd/config.toml |
Iniciaremos containerd y lo habilitaremos en el arranque con:
|
1 |
sudo systemctl enable --now containerd |
Instalar Kubernetes en Linux Ubuntu Server 24
Hay una serie de componentes de nodo necesarios para proporcionar un entorno de tiempo de ejecución de Kubernetes que debe instalarse en cada nodo. Entre ellas se encuentran:
kubelet: se ejecuta como un agente en cada nodo de trabajo y garantiza que los contenedores se ejecuten en un pod.kubeadm: Bootstraps Clúster de Kuberneteskubectl: Se utiliza para ejecutar comandos en clústeres de Kubernetes.
Estos componentes no están disponibles en los repositorios predeterminados de Ubuntu. Por lo tanto, debe instalar repositorios de Kubernetes para instalarlos.
Run the command below to install Kubernetes repo GPG key.
|
1 |
sudo apt install gnupg2 -y |
Instalaremos la versión 1.30:
|
1 2 3 |
VER=1.30 curl -fsSL https://pkgs.k8s.io/core:/stable:/v${VER}/deb/Release.key | \ sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/k8s.gpg |
A continuación, instale el repositorio de Kubernetes de la versión que coincida con la clave GPG instalada anteriormente:
|
1 |
echo "deb https://pkgs.k8s.io/core:/stable:/v${VER}/deb/ /" | sudo tee /etc/apt/sources.list.d/kurbenetes.list |
Actualizamos la caché de paquetes:
|
1 |
sudo apt update |
Instalamos Kubernetes:
|
1 |
sudo apt install kubelet kubeadm kubectl -y |
Para mantener la estabilidad del clúster, es importante mantener versiones específicas de paquetes críticos como , , y . Esto se puede hacer instruyendo al sistema de gestión de paquetes (APT) para evitar que esos paquetes se actualicen utilizando el comando apt-mark hold. kubeadmkubeletkubectl
|
1 |
sudo apt-mark hold kubeadm kubelet kubectl |
Para comprobar si los paquetes están en espera o no, puede utilizar :apt-mark showhold
|
1 |
sudo apt-mark showhold |
Si desea permitir la actualización de estos paquetes de nuevo, puede eliminar la retención usando :aptapt-mark unhold
|
1 |
sudo apt-mark unhold kubeadm kubelet kubectl |
Iniciar Kubernetes Cluster en Control Plane usando Kubeadm
Una vez completados los pasos anteriores, inicialice el clúster de Kubernetes en el nodo principal. El maestro de Kubernetes es responsable de mantener el estado deseado para el clúster.
Dado que solo estamos ejecutando un clúster de Kubernetes de un solo nodo maestro en esta guía (con fines de demostración), sin planes de actualizar a un clúster de alta disponibilidad, especificaremos solo la dirección IP del plano de control mientras arrancamos nuestro clúster.
Por lo tanto, ejecute el siguiente comando en el nodo maestro para arrancar el nodo del plano de control de Kubernetes.
|
1 |
sudo kubeadm init --apiserver-advertise-address=192.168.1.88 --pod-network-cidr=10.100.0.0/16 |

Indicando:
|
1 2 3 4 5 6 7 8 9 |
To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Alternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.conf |
Preparar el nodo master e iniciar Kubernetes
Creamos la carpeta del cluster:
|
1 |
mkdir -p $HOME/.kube |
Copie el archivo de configuración de administración de Kubernetes en el directorio del clúster creado anteriormente.
|
1 |
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config |
Establezca la propiedad adecuada para el archivo de configuración del clúster.:
|
1 |
sudo chown $(id -u):$(id -g) $HOME/.kube/config |
Verifique el estado del clúster de Kubernetes;:
|
1 |
kubectl get nodes |
Para obtener la dirección del panel de control:
|
1 |
kubectl cluster-info |
Indicando además el comando con el token para añadir nodos:
|
1 2 3 4 |
Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.1.88:6443 --token vz1lkk.pn3qsejadsv4y63i \ --discovery-token-ca-cert-hash sha256:4c8755fbdc2cc23a3b19f68f22793c354bb39ee31e239614775f31689bb6e773 |
Instalar el complemento Pod Network en el nodo maestro
Un pod es un grupo de uno o más contenedores relacionados en un clúster de Kubernetes. Comparten el mismo ciclo de vida, almacenamiento/red. Para que los pods se comuniquen entre sí, debes implementar un
Container Network Interface (CNI) based Pod network add-on.
Hay varios complementos de red Pod entre los que puede elegir. Consulte la página de complementos para obtener más información.
Usaremos Calico:
|
1 |
CNI_VER=v3.28.0 |
|
1 |
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v${CNI_VER}/manifests/tigera-operator.yaml |
A continuación, descargue los recursos personalizados necesarios para configurar Calico. La red predeterminada para el complemento Calico es 192.168.0.0/16. Si ha utilizado el CIDR de pod personalizado tal y como se ha definido anteriormente (–pod-network-cidr=10.100.0.0/16), descargue el archivo de recursos personalizado y modifique la red para que coincida con la personalizada.
Actulizamos la red de Calico para que coincida con la desplegada en los Kubernetes:
|
1 |
sed -i 's/192.168/10.100/' custom-resources.yaml |
Aplicamos los cambios:
|
1 |
kubectl create -f custom-resources.yaml |

Una vez que se complete el comando, puede enumerar los pods en los espacios de nombres ejecutando el comando a continuación;
|
1 |
kubectl get pods --all-namespaces |

Cortafuegos en nodos
If firewall is running on the nodes, then there are some ports that needs to be opened on the firewall;
Control Plane ports;
| Protocol | Direction | Port Range | Purpose | Used By |
|---|---|---|---|---|
| TCP | Inbound | 6443 | Kubernetes API server | All |
| TCP | Inbound | 2379-2380 | etcd server client API | kube-apiserver, etcd |
| TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
| TCP | Inbound | 10259 | kube-scheduler | Self |
| TCP | Inbound | 10257 | kube-controller-manager | Self |
Add Worker Nodes to Kubernetes Cluster
Ahora puede agregar nodos de trabajo al clúster de Kubernetes mediante el comando kubeadm join de la siguiente manera.
Antes de eso, asegúrese de que el tiempo de ejecución del contenedor esté instalado, configurado y en ejecución. Estamos usando CRI en contenedores;
Errores y su solución:
|
1 2 3 4 5 6 7 8 |
alonso@srvubuntu24:~$ sudo kubeadm init --apiserver-advertise-address=192.168.1.88 --pod-network-cidr=10.100.0.0/16 I1218 20:35:21.699375 11993 version.go:256] remote version is much newer: v1.32.0; falling back to: stable-1.30 [init] Using Kubernetes version: v1.30.8 [preflight] Running pre-flight checks error execution phase preflight: [preflight] Some fatal errors occurred: [ERROR NumCPU]: the number of available CPUs 1 is less than the required 2 [preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...` To see the stack trace of this error execute with --v=5 or higher |
Solución: ampliar CPU.