En esta entrada se documenta el proceso de creación de un cluster de kubernetes con kubeadm. El clúster está formado (por ahora) con un nodo master y un nodo worker.
La información para la realización de esta se ha sacado, principalmente, de las siguientes webs:
- https://devopscube.com/setup-kubernetes-cluster-kubeadm/
- https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
- https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
Que es kubeadm?
Kubeadm es una herramienta proporcionada por el proyecto Kubernetes que facilita la configuración, el despliegue y la administración de un clúster de Kubernetes. Es una de las formas más comunes y recomendadas para crear un clúster de Kubernetes desde cero.
Este automatiza muchos de los pasos que normalmente se requieren para configurar manualmente un clúster.
De qué esta formado un clúster de kubernetes?
De forma resumida y sencilla, un clúster de kubernetes está formado por dos tipos de nodos:
- Nodo master: Es el responsable de la gestión del clúster. Es desde donde se administra el clúster, se encarga de tomar decisiones sobre la programación, replicación de los Pods y responde a los cambios de estado del clúster. Está formado por varios componentes, API Server. etcd, scheduler…
- Nodos worker: La función de este tipo de nodos es ejecutar los contendedores. Entre sus componentes principales encontramos el kubectl, kube-proxy y el container runtime(containerd, Cri-o, …)
Requisitos
Para proceder a la instalación del clúster, necesitaremos lo siguiente:
- One or more machines running a deb/rpm-compatible Linux OS; for example: Ubuntu or CentOS.
- 2 GiB or more of RAM per machine–any less leaves little room for your apps.
- At least 2 CPUs on the machine that you use as a control-plane node.
- Full network connectivity among all machines in the cluster. You can use either a public or a private network.
Esto está sacado de la documentación oficial de kubernetes. En mi caso he creado dos VM con Ubuntu 24.04 y con los requisitos de hardware indicados. Es decir, para el nodo master lo he creado con 2 vCPUs y 2GB de RAM. Para los nodos workers, 1vCPU y 2GB de RAM. En mi caso, para mi laboratorio, los discos de las máquinas serán de 32GB.
La red que usaré para los nodos será la red 192.168.1.0/24 y para la red interna de kubernetes 10.0.0.0/16
Una vez, tengamos las máquinas creadas con lo indicado anteriormente (indicar que esto es un laboratorio personal, por lo que los recursos usados siguen lo mínimo requerido que, para mi caso, es suficiente), es necesario aplicar la siguiente apertura de puertos indicada en la documentación oficial:
https://kubernetes.io/docs/reference/networking/ports-and-protocols/
La indico a continuación:
Nodo master
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 |
Worker node(s)
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 10256 | kube-proxy | Self, Load balancers |
TCP | Inbound | 30000-32767 | NodePort Services† | All |
Configuración del clúster con kubeadm
1. Configuración de IPtables para Tráfico Puente en Kubernetes
Para asegurar que IPTables pueda gestionar correctamente el tráfico entre Pods en Kubernetes, es necesario habilitar la inspección de tráfico puenteado. Esto se debe a que Kubernetes utiliza redes en modo puente para la comunicación entre Pods y nodos. Para ello, primero es necesario asegurarse que el módulo del kernel br_netfilter esté cargado:
sudo tee /etc/modules-load.d/k8s.conf br_netfilter
Tras eso, se ejecutan los siguientes comandos para permitir que IPTables vea y maneje el tráfico puenteado:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
Esto hay que aplicarlo en todos los nodos
2. Deshabilitar swap en todos los nodos
Para que kubeadm funcione correctamente se necesita deshabilitar la swap en todos los nodos:
sudo swapoff -a
Es necesario configurar el fstab para que no genere la swap tras el reinicio de los nodos
3. Instalar containter runtime
Para este laboratorio escogí CRI-O ya que es el que he visto que se emplea en las certificaciones de kubernetes. Otras alternativas podrían ser containerd o docker engine. Es necesario repetir lo siguiente en todos los nodos:
sudo apt-get update -y
sudo apt-get install -y software-properties-common curl apt-transport-https ca-certificates
curl -fsSL https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/Release.key |
gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/ /" |
tee /etc/apt/sources.list.d/cri-o.list
sudo apt-get update -y
sudo apt-get install -y cri-o
sudo systemctl daemon-reload
sudo systemctl enable crio --now
sudo systemctl start crio.service
A mayores se instalará el crictl, el cual es una CLI utilizada para interacturar con los contenedores creados
VERSION="v1.28.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz
4. Instalar Kubeadm y otras utilidades
Esto será necesario realizarlo en todos los nodos. He usado la versión 1.29 ya que es la requerida en las últimas certificaciones:
KUBERNETES_VERSION=1.29
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v$KUBERNETES_VERSION/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v$KUBERNETES_VERSION/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
Tras esto ejecutamos:
apt-get update -y
Procedemos a instalar los paquetes necesarios:
sudo apt-get install -y kubelet=1.29.0-1.1 kubectl=1.29.0-1.1 kubeadm=1.29.0-1.1
Como paso final de la instalación de la paquetería, es necesario indicarle a kubernetes que IP va a usar dicho nodo para comunicarse dentro del clúster. Para ello obtenemos la IP de la interfaz a usar y añadiremos la siguiente linea en el fichero /etc/default/kubelet:
KUBELET_EXTRA_ARGS=--node-ip=<X.X.X.X>
5. Iniciar kubeadm en el nodo master
Para iniciar kubeadm en el nodo máster tendremos que ejecutar lo siguiente:
sudo kubeadm init --apiserver-advertise-address=<X.X.X.X> --apiserver-cert-extra-sans=<X.X.X.X> --pod-network-cidr=<Y.Y.Y.Y/YY> --node-name <hostname> --ignore-preflight-errors Swap
En el comando anterior es necesario modificar lo siguiente:
- X.X.X.X por la IP del nodo
- Y.Y.Y.Y por la red interna que queremos usar. En mi caso, 10.0.0.0/16
- hostname por el hostname del nodo
En la salida de este comando, cuando finalice, se deberá ver algo como lo siguiente:
Your Kubernetes control-plane has initialized successfully!
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
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.170:6443 --token vt9h3t.ccokyp0qhanji48e \
--discovery-token-ca-cert-hash sha256:fd7735e8a33478b36ec5ac09b5c5d3daf005de67dc9bff7e527147a8f403efee
Tras esto, es necesario ejecutar los comandos que se nos indica:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Como comprobación, si se ejecuta lo siguiente:
kubectl get po -n kube-system
Se deberá tener una salida similar a :
root@master:~# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-76f75df574-k5jwb 1/1 Running 0 80s
coredns-76f75df574-s97kg 1/1 Running 0 80s
etcd-master 1/1 Running 0 93s
kube-apiserver-master 1/1 Running 0 95s
kube-controller-manager-master 1/1 Running 0 93s
kube-proxy-9tczx 1/1 Running 0 80s
kube-scheduler-master 1/1 Running 0 95s
6. Añadir workers al cluster
Para realizar esto, es necesario ejecutar lo indicado en la salida del comando realizado en el punto 5:
kubeadm join 192.168.1.170:6443 --token vt9h3t.ccokyp0qhanji48e \
--discovery-token-ca-cert-hash sha256:fd7735e8a33478b36ec5ac09b5c5d3daf005de67dc9bff7e527147a8f403efee
Si se ha perdido dicha salida, podemos recuperar lo necesario para añadir un worker al cluster ejecutando en el nodo master lo siguiente:
kubeadm token create --print-join-command
La salida del comando deberá indicar que el nodo se unió correctamente y desde el nodo máster podremos ejecutar lo siguiente:
kubectl get nodes
Pudiendo ver lo siguiente:
root@master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 93m v1.29.0
worker1 Ready <none> 90m v1.29.0
7. Instalación de plugins adicionales:
Por defecto, kubeadm no configura ni instala ningún plugin de red, por lo que según he visto en las guías mencionadas, se usa Calico para ello. Para instalarlo necesitamos ejecutar:
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
Tras ejecutar esto podemos comprobar en el nodo master la existencia de los pods correspondientes a este plugin:
root@master:~# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-658d97c59c-6rzh4 0/1 ContainerCreating 0 10s
calico-node-49d5l 0/1 Init:0/3 0 10s
calico-node-pwpqt 0/1 Init:0/3 0 10s
coredns-76f75df574-k5jwb 1/1 Running 0 4m12s
coredns-76f75df574-s97kg 1/1 Running 0 4m12s
etcd-master 1/1 Running 0 4m25s
kube-apiserver-master 1/1 Running 0 4m27s
kube-controller-manager-master 1/1 Running 0 4m25s
kube-proxy-9tczx 1/1 Running 0 4m12s
kube-proxy-qkvh8 1/1 Running 0 97s
kube-scheduler-master 1/1 Running 0 4m27s
Por último, se instalará un plugin que permite obtener métricas de los nodos. Se hará de la misma forma que el anterior:
kubectl apply -f https://raw.githubusercontent.com/techiescamp/kubeadm-scripts/main/manifests/metrics-server.yaml
Si se ejecuta el comando anterior, podemos ver el pod correspondiente a dicho plugin
root@master:~# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
...
metrics-server-d4dc9c4f-kmh5m 0/1 ContainerCreating 0 48s
Este plugin nos permite ver lo siguiente:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 135m 6% 1124Mi 60%
worker1 330m 33% 767Mi 41%
Conclusión
Kubeadm simplifica mucho el proceso de instalación de un cluster de kubernetes. Tras los pasos realizados, se podría desplegar un pod ya que ya hemos configurado el clúster de forma completa. Al menos, para un funcionamiento básico del mismo