Kubernetes: Instalar ClusterHat Raspberry Pi Zero 2W
Después de mostraros como montar un NAS con RaspBerry Pi, hoy quiero enseñaros otro proyecto interesante con RaspBerry Pi, en este caso usaremos una RaspBerry Pi 4 y varias RaspBerry Pi Zero 2W, para formar un clúster para usarlo como laboratorio de containers.
Lo que busco con este LAB es reducir el espacio, el coste energético y el ruido, que ahora teletrabajando se me hace muy cuesta arriba.
Agarraros que viene manual muyyyyy extenso 🙂
El material que vamos a utilizar para este laboratorio de containers es:
- 1 x RaspBerry Pi 4 de 4GB de RAM
- 4 x RaspBerry Pi Zero 2W
- 5 x MicroSD de 32GB
- 1 x Alimentador de corriente USB-C
- 1. x Placa ClusterHat 8086 v.2 que incluye conector USB a RPi4
- 1 x Carcasa transparente sobredimensionada especial para albergar ClusterHat
- Ratón y teclado USB
- Monitor para la primera instalación con cable HDMI
- 1 x Adaptador Micro HDMI a HDMI
- 1 x Cable Ethernet
- Y yo he añadido disipadores para RPi4 y un ventilador de 30mmx30mm de 5V
- 1 x Lector de tarjetas MicroSD para instalar las imágenes de sistema operativo
En la web del proyecto podéis encontrar los vendedores, donde podréis encontrar todas las piezas sin problema (si compráis en Inglaterra, recordar los aranceles)
Preparar software ClusterHat para RaspBerrys
El software que vamos a utilizar es el del proyecto que os dejo el enlace un poco más abajo. Como podéis ver en la imagen, hay una imagen para cada tarjeta. Yo bajaré la imagen CNAT para la RaspBerry Pi 4 y para cada Zero 2W una imagen Px, porque no quiero que sean un nodo de mi red cada Pi Zero, si no queréis eso, simplemente bajar la versión CBRIDGE.
A nivel de seguridad, es mejor usar CNAT, porque controlaréis el sistema con el controlador, que ese role lo tiene la RaspBerry Pi 4, y el resto no estará expuesto. Y simplifica un poco la gestión y configuración del sistema…
PROYECTO: https://clusterctrl.com/setup-software
Podéis ver un ejemplo de lo descargado:
Para quemar las imágenes uso Balena:
Y repito el proceso en cada imagen:
Con esto ya tenemos todo preparado a nivel de software…
Montar ClusterHat (RaspBerry Pi Zero 2W y RaspBerry Pi 4) en carcasa
A nivel de hardware os voy a mostrar como es la instalación de todos los componentes, que realmente es sencilla. De hecho, no hay instrucciones en la carcasa, ni en la placa, pero la lógica te explica como ensamblar el conjunto.
La carcasa viene con plásticos protectores que deberemos retirar:
Colocamos los tornillos pequeños de la siguiente forma:
El soporte es para la RaspBerry Pi 4 que va en la base:
Colocamos nuestra RaspBerry Pi 4:
A continuación, colocamos el segundo grupo de tornillos:
Colocamos con cuidado la placa ClusterHat 8086 en los pines y tornillos:
Aquí la veis colocada:
Colocáis el resto de soportes y la primera pieza lateral a colocar es la de los USB. Veréis que sólo ajusta bien de una de sus caras, y es importante para no tener problemas:
Ahora yo he colocado las RaspBerry Pi Zero 2W y sus tarjetas, colocarlas en un orden como hayáis instalado el software en cada tarjeta:
Quedaría de la siguiente forma:
Colocamos la tapa y el cable USB (que es opcional, creo que depende del alimentador que utilices):
Yo de manera opcional he colocado disipadores de calor y un ventilador de 5V. Se calientan algo, así que no vendrán nada mal:
Ya tendríamos montado el hardware. Una vez conectado a nuestro ratón, teclado y monitor, es un RaspBian que te solicita 4 configuraciones básicas para completar la instalación (contraseña usuario, red wifi…). La contraseña por defecto es:
1 2 |
Username: pi Password: clusterctrl |
Pero en este proceso, cambiáis la contraseña, como indico.
Comandos básicos ClusterHat
Desde la placa ClusterHat se puede controlar la energía de las Pi Zero de la siguiente forma. Por defecto, el clusterhat está apagado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Cluster HAT v2.x ó Cluster HAT v1.x $ clusterctrl on # Turn power to all Pi Zero on $ clusterctrl off Turn power to all Pi Zero off $ clusterctrl on p1 # Turn power on to Pi Zero in slot P1 $ clusterctrl on p1 p3 p4 # Turn power to Pi Zeros in slot P1, P3 and P4 on $ clusterctrl off p2 p3 # Turn power off to Pi Zeros in slots P2 and P3 $ clusterctrl alert on # Turns on ALERT LED $ clusterctrl alert off # Turns off ALERT LED Cluster HAT v2.x (commands not available on Cluster HAT v1.x) $ clusterctrl hub on # Turns on USB hub (default) $ clusterctrl hub off # Turns off USB hub $ clusterctrl led on # Enables Power & P1-P4 LED on Cluster HAT (default) $ clusterctrl led off # Disables Power & P1-P4 LED on Cluster HAT (does not disable ALERT LED) $ clusterctrl wp on # Write protects HAT EEPROM $ clusterctrl wp off # Disables EEPROM write protect (only needed for updates) |
La iluminación de las Pi Zero cambiará según el comando y podréis identificar cada Zero:
Habilitar SSH en RaspBian de ClusterHat
Para acceder a la Raspberry Pi 4 y empezar a gestionar el equipo usaremos el comando, lanzado como root:
1 |
pi@cnat:~ $ raspi-config |
Opción 3 Interface Options -> P2 SSH -> Enable
Luego lanzamos los comandos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
pi@cnat:~ $ sudo su - root@cnat:~# systemctl status ssh ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2021-11-27 14:03:01 CET; 2min 48s ago Docs: man:sshd(8) man:sshd_config(5) Main PID: 1764 (sshd) Tasks: 1 (limit: 4915) CGroup: /system.slice/ssh.service └─1764 /usr/sbin/sshd -D nov 27 14:03:01 cnat systemd[1]: Starting OpenBSD Secure Shell server... nov 27 14:03:01 cnat sshd[1764]: Server listening on 0.0.0.0 port 22. nov 27 14:03:01 cnat sshd[1764]: Server listening on :: port 22. nov 27 14:03:01 cnat systemd[1]: Started OpenBSD Secure Shell server. nov 27 14:03:57 cnat sshd[2220]: Connection closed by 192.168.2.212 port 54293 [preauth] nov 27 14:04:41 cnat sshd[2230]: Accepted password for pi from 192.168.2.212 port 54294 ssh2 nov 27 14:04:41 cnat sshd[2230]: pam_unix(sshd:session): session opened for user pi by (uid=0) root@cnat:~# systemctl enable ssh Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable ssh |
Y ya podemos gestionar nuestra Raspberry Pi 4 remotamente, pero no las Pi Zero. Así que con el cluster arrancado, vamos a generar las claves SSH y propagarlas por los nodos.
También hay que generar un fichero sin extensión llamado SSH en la partición BOOT de cada tarjeta MicroSD de nuestras Zero (Windows para esto es la mejor opción):
Primero os explico la red…
Red de ClusterHat
Con el acceso SSH ya tenemos control sobre el cluster. Así que lo primero es asegurarnos que nuestras Pi Zero están encendidas con (esto es como darle al botón de encendido de un ordenador):
1 |
root@cnat:~# clusterhat on |
Vuestra RaspBerry Pi 4, que hace de controler, tendrá 3 Ips:
- Wifi si la habéis configurado
- El cable Ethernet tendrá otra por DHCP en mi caso (ya la colocaremos en estática o la reservamos dentro del rango)
- Y la IP como controler del clúster 172.19.181.254
Los equipos los podéis gestionar con un px.local, por ejemplo hacéis un ping a cada Pi Zero:
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 |
root@cnat:~# ping p1.local PING p1.local (<strong>172.19.181.1</strong>) 56(84) bytes of data. 64 bytes from 172.19.181.1 (172.19.181.1): icmp_seq=1 ttl=64 time=0.295 ms 64 bytes from 172.19.181.1 (172.19.181.1): icmp_seq=2 ttl=64 time=0.251 ms ^C --- p1.local ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 2ms rtt min/avg/max/mdev = 0.251/0.273/0.295/0.022 ms root@cnat:~# ping p2.local PING p2.local (<strong>172.19.181.2</strong>) 56(84) bytes of data. 64 bytes from 172.19.181.2 (172.19.181.2): icmp_seq=1 ttl=64 time=0.687 ms 64 bytes from 172.19.181.2 (172.19.181.2): icmp_seq=2 ttl=64 time=0.304 ms ^C --- p2.local ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 2ms rtt min/avg/max/mdev = 0.304/0.495/0.687/0.192 ms root@cnat:~# ping p3.local PING p3.local (<strong>172.19.181.3</strong>) 56(84) bytes of data. 64 bytes from 172.19.181.3 (172.19.181.3): icmp_seq=1 ttl=64 time=0.286 ms 64 bytes from 172.19.181.3 (172.19.181.3): icmp_seq=2 ttl=64 time=0.257 ms ^C --- p3.local ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 2ms rtt min/avg/max/mdev = 0.257/0.271/0.286/0.021 ms root@cnat:~# ping p4.local PING p4.local (<strong>172.19.181.4</strong>) 56(84) bytes of data. 64 bytes from 172.19.181.4 (172.19.181.4): icmp_seq=1 ttl=64 time=0.329 ms ^C --- p4.local ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.329/0.329/0.329/0.000 ms |
Configurar SSH de ClusterHat
He hecho dos cosas adicionales antes de empezar, cambiar el hostname de la Pi4 y agregar al fichero host el nombre de las Zero:
1 2 3 4 5 6 7 8 9 |
root@p0:~# nano /etc/hostname p0 root@p0:~# nano /etc/hosts 127.0.1.1 p0 172.19.181.254 p0 p0.local 172.19.181.1 p1 p1.local 172.19.181.2 p2 p2.local 172.19.181.3 p3 p3.local 172.19.181.4 p4 p4.local |
Para que los equipos se entiendan entre ellos vamos a generar las claves SSH desde el controler (Pi 4) y luego comprobamos que se ha generado:
1 2 |
root@p0:~# ssh-keygen -t rsa -b 4096 -C "pi@p0.local" root@p0:~# cat ~/.ssh/id_rsa.pub |
Guardamos la clave a buen recaudo copiándola para reutilizarla luego. Generamos un fichero “config” con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
root@p0:~# nano /root/.ssh/config Host p1 Hostname 172.19.181.1 User pi Host p2 Hostname 172.19.181.2 User pi Host p3 Hostname 172.19.181.3 User pi Host p4 Hostname 172.19.181.4 User pi |
Copiamos la clave en los nodos con los siguientes comandos desde la RPi4:
1 2 3 4 5 6 7 |
cat ~/.ssh/id_rsa.pub | ssh pi@p1.local "mkdir .ssh;cat >> .ssh/authorized_keys" cat ~/.ssh/id_rsa.pub | ssh pi@p2.local "mkdir .ssh;cat >> .ssh/authorized_keys" cat ~/.ssh/id_rsa.pub | ssh pi@p3.local "mkdir .ssh;cat >> .ssh/authorized_keys" cat ~/.ssh/id_rsa.pub | ssh pi@p4.local "mkdir .ssh;cat >> .ssh/authorized_keys" |
Recordar que si no habéis cambiado la password del usuario pi de las Zero es:
1 2 |
Username: pi Password: clusterctrl |
Comprobamos los nodos, si nos podemos conectar directamente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
root@p0:~# ssh p1 Linux p1 5.4.79-v7+ #1373 SMP Mon Nov 23 13:22:33 GMT 2020 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Sat Nov 27 18:29:28 2021 from 172.19.181.254 -bash: warning: setlocale: LC_ALL: cannot change locale (es_ES.UTF-8) Wi-Fi is currently blocked by rfkill. Use raspi-config to set the country before use. pi@p1:~ $ |
Yo aprovecho para cambiar la passwd de todos los usuarios en las Pi Zero.
1 2 3 4 5 6 |
pi@p2:~ $ passwd pi Changing password for pi. Current password: New password: Retype new password: passwd: password updated successfully |
Instalación cluster Kubernetes en ClusterHat RaspBerry Zero 2W
Y llegamos al final del trabajo…ya tenemos interconexión entre los nodos, sabemos encenderlos, cómo se comunican y cómo interactuar entre ellos. Así que buscamos si hay actualizaciones en todos los nodos:
1 2 |
root@p0:~# apt-get update root@p0:~# apt-get upgrade |
Una vez que tenemos todo actualizado, vamos con la instalación de Kubernetes.
Instalamos el paquete ntpdate en todos los nodos:
1 |
sudo apt-get install ntpdate |
La hora de la RPi4 y de las Zero no coincide y hay que arreglarlo, con raspi-config podéis hacerlo(Opción 5 -> Timeline)
Modificamos el fichero hosts de los nodos:
1 2 3 4 5 6 7 |
sudo nano /etc/hosts 172.19.181.254 p0 p0.local 172.19.181.1 p1 p1.local 172.19.181.2 p2 p2.local 172.19.181.3 p3 p3.local 172.19.181.4 p4 p4.local |
Editamos el fichero config.txt del boot, para optimizar las raspberrys para que dediquen la memoria a procesador y no a la parte gráfica:
1 2 3 4 |
root@p0:~# nano /boot/config.txt # Debajo de [all] gpu_mem=16 |
El problema de Kubernetes, es que es sensible a las latencias, así que no está de menos, revisar cómo se comporta nuestra tarjeta:
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 |
root@p0:~# fio --loops=5 --size=500m --filename=fiotest.tmp --stonewall --ioengine=libaio --direct=1 --name=Seqwrite --bs=1m --rw=write Seqwrite: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=1 fio-3.12 Starting 1 process Seqwrite: Laying out IO file (1 file / 500MiB) Jobs: 1 (f=1): [W(1)][100.0%][w=11.0MiB/s][w=11 IOPS][eta 00m:00s] Seqwrite: (groupid=0, jobs=1): err= 0: pid=2902: Sat Nov 27 22:42:44 2021 write: IOPS=13, BW=13.6MiB/s (14.3MB/s)(2500MiB/183303msec); 0 zone resets slat (usec): min=488, max=26289, avg=2639.62, stdev=1134.25 clat (msec): min=51, max=251, avg=70.65, stdev=39.14 lat (msec): min=53, max=254, avg=73.30, stdev=39.23 clat percentiles (msec): | 1.00th=[ 53], 5.00th=[ 53], 10.00th=[ 53], 20.00th=[ 53], | 30.00th=[ 53], 40.00th=[ 53], 50.00th=[ 53], 60.00th=[ 54], | 70.00th=[ 62], 80.00th=[ 62], 90.00th=[ 131], 95.00th=[ 159], | 99.00th=[ 226], 99.50th=[ 245], 99.90th=[ 249], 99.95th=[ 251], | 99.99th=[ 251] bw ( KiB/s): min= 4096, max=18432, per=100.00%, avg=13964.57, stdev=4230.50, samples=366 iops : min= 4, max= 18, avg=13.58, stdev= 4.13, samples=366 lat (msec) : 100=83.64%, 250=16.28%, 500=0.08% cpu : usr=0.25%, sys=0.50%, ctx=5044, majf=0, minf=22 IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% issued rwts: total=0,2500,0,0 short=0,0,0,0 dropped=0,0,0,0 latency : target=0, window=0, percentile=100.00%, depth=1 Run status group 0 (all jobs): WRITE: bw=13.6MiB/s (14.3MB/s), 13.6MiB/s-13.6MiB/s (14.3MB/s-14.3MB/s), io=2500MiB (2621MB), run=183303-183303msec Disk stats (read/write): mmcblk0: ios=0/5077, merge=0/69, ticks=0/278182, in_queue=247970, util=99.89% |
Para instalar Kubernetes usaré el proyecto k3s, que es un poco más liviano que k8s y no tiene tanta dependencia de recursos. Como base de datos por defecto usa SQLite, aunque podíamos usar MariaDB, PostgreSQL o MySQL, por ejemplo:
- PROYECTO: https://k3s.io/
- MANUAL: https://rancher.com/docs/k3s/latest/en/advanced/#enabling-legacy-iptables-on-raspbian-buster
Necesitamos garantizar ciertos requisitos:
1 2 3 4 |
sudo iptables -F sudo update-alternatives --set iptables /usr/sbin/iptables-legacy sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy sudo reboot |
Hay que modificar para que admita cgroups Raspbian, creando el fichero /boot/cmdline.txt:
1 |
console=serial0,115200 console=tty1 root=PARTUUID=34565118-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait cgroup_memory=1 cgroup_enable=memory |
En mi caso tuve que añadir a la línea:
1 |
cgroup_memory=1 cgroup_enable=memory |
Para instalar k3s en el controler podemos lanzar la instalación en nuestra RPi4 con el siguiente comando:
1 |
root@p0:~# curl -sfL https://get.k3s.io | sh - |
Nos instala un balanceador y todo lo necesario para completar el clúster sin necesidad de instalar nada (CoreDNS, Traefik Ingress Controller y Service Load Balancer).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
root@p0:~# curl -sfL https://get.k3s.io | sh - [INFO] Finding release for channel stable [INFO] Using v1.21.5+k3s2 as release [INFO] Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.21.5+k3s2/sha256sum-arm.txt [INFO] Downloading binary https://github.com/k3s-io/k3s/releases/download/v1.21.5+k3s2/k3s-armhf [INFO] Verifying binary download [INFO] Installing k3s to /usr/local/bin/k3s [INFO] Creating /usr/local/bin/kubectl symlink to k3s [INFO] Creating /usr/local/bin/crictl symlink to k3s [INFO] Creating /usr/local/bin/ctr symlink to k3s [INFO] Creating killall script /usr/local/bin/k3s-killall.sh [INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh [INFO] env: Creating environment file /etc/systemd/system/k3s.service.env [INFO] systemd: Creating service file /etc/systemd/system/k3s.service [INFO] systemd: Enabling k3s unit Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service. [INFO] systemd: Starting k3s |
Si todo está OK:
1 2 3 |
root@p0:~# kubectl get nodes NAME STATUS ROLES AGE VERSION p0 Ready control-plane,master 61s v1.21.5+k3s2 |
Para los agentes usaremos:
1 2 3 4 |
curl -sfL https://get.k3s.io | \ K3S_URL=https://p0.local:6443 \ K3S_TOKEN=mynodetoken \ sh - |
El valor mynodetoken lo podéis encontrar en:
1 |
/var/lib/rancher/k3s/server/node-token |
Eliminar k3s
Para eliminar es muy sencillo, en el controller:
1 |
/usr/local/bin/k3s-uninstall.sh |
Y en los agentes:
1 |
/usr/local/bin/k3s-agent-uninstall.sh |
Y hasta aquí tenemos toda esta instalación que parece compleja, pero no lo es tanto. Compartir, que es gratis y haré más entradas relacionadas.
Configurar FAN en ClusterHat RaspBerry Pi
Para completar la instalación he comprado un ventilador de 30mmx30mm que he conectado a la tapa. Se configura desde /boot/config.txt, añadiendo la siguiente línea:
1 |
dtoverlay=gpio-fan,gpiopin=18,temp=75000 |
Te ha gustado la entrada SGUENOS EN TWITTER O INVITANOS A UN CAFE?
3 comentarios
Pingback: Raspberry: Saber temperatura vía terminal - Blog Virtualizacion
Pingback: RaspBerry: Instalar Docker Swarm en ClusterHat - Blog Virtualizacion
Pingback: Docker: Montar recurso NFS - Blog Virtualizacion