Nel giugno 2022 mi sono imbattuto in una campagna Kickstarter su una scheda in grado di supportare fino a 4 moduli di elaborazione Raspberry Pi 4 contemporaneamente.
Senza pensarci troppo, ho deciso di sostenere il progetto e di acquistare la scheda.
Facciamo un salto in avanti di due anni: il mio Turing Pi 2 era ancora nella sua scatola, ancora chiuso, su uno scaffale. La vita si era messa di mezzo e non ero più sicuro del motivo per cui l'avevo acquistato.
Tuttavia, alla fine ho deciso di provarci. Volevo saperne di più sul clustering e non avevo mai creato un cluster Kubernetes completo da zero prima. Quindi, sono entrato in modalità spesa e ho acquistato tre Raspberry Pi 4 (8 GB di RAM, 8 GB di storage interno) e un Nvidia Jetson Nano (4 GB).
Data la versatilità della scheda, potrei combinare diversi Compute Module. Ho deciso di includere un Jetson Nano, pensando che potrebbe permettermi di sperimentare con i driver CUDA in futuro e di approfondire l'apprendimento automatico. Chissà? Potrei persino finire per ospitare il mio assistente GPT su questo cluster Kubernetes.
(Spoilers: It didn't happen)
Il mio piano iniziale includeva il 3 Pi 4 CM e il Jetson Nano ospitati sulla scheda. Inoltre, avevo pianificato di usare un'unità SSD da 1 TB per l'archiviazione e una scheda Wi-Fi per l'accesso a Internet. Tuttavia, dopo aver incontrato numerose difficoltà con il processo di configurazione del Jetson Nano e la sua scarsa documentazione, ho deciso di restituirlo. Invece, ho optato per un quarto Raspberry Pi 4.
Inoltre, avevo a disposizione un vecchio Raspberry Pi 4 con 4 GB di RAM, così ho deciso di incorporarlo come quinto nodo.
La Turing Pi 2 è una scheda con fattore di forma Mini ITX che può ospitare fino a quattro Raspberry Pi Compute Module (compatibile anche con Jetson Nanos e un Turing Compute Module). È dotata di una porta PCI Express, due porte NVME, due porte SATA e una porta USB per il flashing dei Compute Module.
Nodo 1 :
Porta USB 2.0 (per il flashing dei moduli di elaborazione)
Porta HDMI (per il debug)
Porta PCI Express (per la scheda Wi-Fi)
Nodo 2 :
Io lo userei per l'archiviazione NVME, ma non è compatibile con Raspberry Pi 4.
Nodo 3 :
Le porte SATA, tuttavia, possono essere utilizzate qui. Quindi, questo nodo avrà l'unità condivisa NFS.
Nodo 4 :
Porte USB 3.0 (se mai ne avessi bisogno).
Il mio vecchio lampone :
L'idea alla fine è quella di ospitare un Media Server con alcuni componenti aggiuntivi.
È da un po' che non metto insieme un computer, ed è stata la prima volta che ho giocato con i Compute Module e i loro adattatori, quindi è stato un bel divertimento per il weekend. Dal momento che il mio portafoglio era caldo ma non ancora bruciante, ho pensato, perché diavolo non aggiungere una bella custodia per esso?
Dato il fattore di forma Mini ITX della scheda, potevo inserirla in qualsiasi case ITX di lusso che potessi trovare su Amazon. Il Qube 500 mi ha portato fino in fondo. Stavo già realizzando un cluster fai da te, il miglior case per una cosa del genere era anche un fai da te.
Ho aggiunto anche un alimentatore da 650 W (un vero e proprio eccesso), una piccola scheda Wi-Fi Mini PCI Express e un SSD SATA da 1 TB.
Mettere insieme la "cosa" è stato abbastanza semplice. Un po' di pasta termica tra i Compute Module e i loro dissipatori di calore e unirli insieme con i loro adattatori prima di sistemarli in ordine nella Turing Board;
Ho menzionato l'ordine perché era una parte significativa del progetto. Il Turing Pi 2 offre la gestione delle sue porte distribuite tra i moduli di elaborazione. In questo caso, il PCI Express 1 era gestito dal Primo nodo mentre l'unità SSD era gestita dal 3°. Il 2° poteva gestire la porta NVME e il 4° l'altro SSD se non ricordo male, ma al momento non ne avevo bisogno.
Ho installato Raspberry Pi prima ma mai Compute Modules. Il Turing Pi 2 ha una porta USB sul retro che viene utilizzata per flashare i Compute Modules.
Purtroppo ho provato a usare un cavo USB A-USB A che non era un cavo per il trasferimento dati, quindi, mentre aspettavo che Amazon mi consegnasse un cavo, ho trovato un altro modo per flashare i Compute Module.
Il Turing Pi 2 è dotato di uno strumento CLI che può essere utilizzato non solo per flashare i moduli di elaborazione, ma anche per gestirne l'alimentazione, ripristinarli, controllare alcune statistiche e così via.
Il comando utilizzato per installare i moduli di calcolo era:
tpi flash -i /path/to/image -n {nodes 1 to 4}
Ho pensato che fosse un processo piuttosto semplice, prima di realizzare che l'immagine Raspbian non è dotata di SSH abilitato di default.
Questa, ovviamente, non è responsabilità di Turing. Avrei dovuto aspettare quel cavo, ma vabbè.
Per risolvere questo problema, ho dovuto montare l'immagine sulla mia macchina locale e aggiungere un file vuoto denominato ssh
nella partizione di avvio. Ciò abiliterebbe SSH di default.
sudo mkdir /mnt/pi-boot sudo mount /dev/sdX1 /mnt/pi-boot sudo touch /mnt/pi-boot/ssh sudo umount /mnt/pi-boot
Ora, tutti i miei pi erano pronti per essere utilizzati. Li ho collegati alla rete e ho iniziato a configurarli. C'era poco da configurare, dato che li avrei utilizzati come nodi Kubernetes.
Ma cose come vim e l'aggiornamento del sistema erano necessarie.
Questo mi ha anche dato la possibilità di imparare a usare Tmux . Il miglior strumento che abbia imparato da un po' di tempo.
Se ricordate qualche paragrafo sopra, ho detto che il terzo nodo sarebbe stato utilizzato per l'unità condivisa NFS. Avevo l'unità SSD da 1 TB che avrei utilizzato per questo scopo. Ho dovuto formattarla e montarla nel terzo nodo.
Ma avevo anche bisogno di installare il server NFS in questo nodo e configurarlo negli altri nodi. È consigliato per un ambiente di produzione? Diamine no, ma è un cluster domestico, quindi non mi preoccupo troppo.
Ecco i passaggi che ho seguito per configurare il server NFS:
pi@turing-03:/mnt/ssd/data $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 953.9G 0 disk /mnt/ssd mmcblk0 179:0 0 7.3G 0 disk ├─mmcblk0p1 179:1 0 512M 0 part /boot/firmware └─mmcblk0p2 179:2 0 6.8G 0 part / mmcblk0boot0 179:32 0 4M 1 disk mmcblk0boot1 179:64 0 4M 1 disk
Per prima cosa ho controllato che l'unità fosse montata correttamente. Poi ho installato il server NFS:
sudo mkdir /mnt/nfs_share sudo mount /dev/sda /mnt/nfs_share
Aggiunto al file fstab per assicurarsi che fosse montato all'avvio:
(aggiungendo la seguente riga al file /etc/fstab
)
echo '/dev/sda /mnt/ssd ext4 defaults 0 0' | sudo tee -a /etc/fstab
Ora installiamo nfs-kernel-server:
sudo apt update sudo apt install nfs-kernel-server
E aggiungendo la mia unità al file /etc/exports
:
echo '/mnt/ssd *(rw,sync,no_subtree_check,no_root_squash)' | sudo tee -a /etc/exports
Ora, sugli altri nodi, ho dovuto installare nfs-common:
sudo apt update sudo apt install nfs-common
E agganciando l'unità a ciascun nodo:
sudo mount -t nfs {IP-for-the-drives-node}:/mnt/ssd /mnt
Neofetch è installato in tutti i nodi perché sono sofisticato.
Non avevo mai configurato un cluster Kubernetes da zero prima, ma ho guardato molti video di Jeff Geerling sull'argomento... Questa è un'esperienza sufficiente, non è vero?
Jeff mi ha portato a K3s utilizzando Ansible , una distribuzione Kubernetes leggera, perfetta per il mio cluster domestico e con un metodo predefinito per installarla, perché non ho prerequisiti né idee su come configurarla diversamente.
L'installazione è stata piuttosto semplice. Ho dovuto installarlo in tutti i nodi, ma ho dovuto assicurarmi che il nodo master fosse il primo a essere installato.
Quindi per prima cosa ho clonato il repository k3s-ansible:
git clone https://github.com/k3s-io/k3s-ansible.git
Poi ho dovuto configurare il file di inventario. Il mio nodo master, come ho detto prima, era il mio vecchio Raspberry Pi 4. Quindi ho dovuto assicurarmi che fosse il primo nel file di inventario. Ho anche dovuto assicurarmi che gli altri nodi fossero nei gruppi corretti.:
k3s_cluster: children: server: hosts: 192.168.2.105: agent: hosts: 192.168.2.101: 192.168.2.102: 192.168.2.103: 192.168.2.104:
Nello stesso file, ho dovuto impostare un token di crittografia. Il file indica come farlo, quindi non entrerò nei dettagli qui.
Poi ho dovuto eseguire il playbook:
cd k3s-ansible ansible-playbook playbooks/site.yml -i inventory.yml
Ecco fatto. Per quanto riguarda l'installazione, avevo un cluster Kubernetes attivo e funzionante. Ho dovuto installare K9s sulla mia macchina locale per gestire il cluster e associarlo al file ./kube/config
.
Infine, ho dovuto installare le applicazioni che volevo eseguire nel cluster. Avevo alcune idee su cosa volevo.
Ed è qui che entra in gioco il mio repository .
Per il Media Server, ho deciso di utilizzare:
Come esempio, vi mostrerò come ho installato Sonarr usando kubectl
. Le altre applicazioni sono state installate in modo simile.
Per ogni applicazione ho creato 3 file:
deployment.yaml
è la configurazione per ciascuno dei pod che eseguono l'applicazione
apiVersion: apps/v1 kind: Deployment metadata: name: sonarr spec: replicas: 1 selector: matchLabels: app: sonarr template: metadata: labels: app: sonarr spec: containers: - name: sonarr image: linuxserver/sonarr ports: - containerPort: 8989 env: - name: PUID value: "911" - name: PGID value: "911" - name: TZ value: "Europe/Amsterdam" volumeMounts: - mountPath: /data name: data - name: config mountPath: /config volumes: - name: data persistentVolumeClaim: claimName: nfs-pvc - name: config persistentVolumeClaim: claimName: nfs-config-pvc
service.yaml
è la configurazione per il servizio che esporrà l'applicazione al cluster
apiVersion: v1 kind: Service metadata: name: sonarr spec: selector: app: sonarr ports: - port: 80 targetPort: 8989 type: ClusterIP
ingress.yaml
e questa è la configurazione per l'ingresso che esporrà l'applicazione alla mia rete
Quindi li distribuiamo tutti usando kubectl
:
kubectl apply -f sonarr/deployment.yaml kubectl apply -f sonarr/service.yaml kubectl apply -f sonarr/ingress.yaml
Come puoi vedere, utilizzo un archivio persistente basato su NFS per i dati e la configurazione delle applicazioni.
Nel repository puoi trovare i file nfs-pv.yaml e nfs-pvc.yaml che ho utilizzato per creare l'archiviazione NFS.
Inoltre, ho creato un'altra richiesta di volume persistente per la configurazione delle applicazioni.
Anche se il case sembra fantastico, è un po' troppo grande per un Raspberry Pi Cluster. Anche un case Mini ITX avrebbe soddisfatto le mie esigenze, ma devo ammettere che sono un fanatico del fai da te.
Inoltre, un fanatico dei LED in generale. Non ho aggiunto altre luci al case, ma penso che la scheda faccia già un buon lavoro. Sfortunatamente, i pin della ventola non erano compatibili con la scheda, e non ho acquistato un controller della ventola o un pin per la scheda madre. Potrei farlo in futuro.
A volte, non ti resta che rilassarti e goderti il panorama.
E finalmente il Turing Pi 2 Home Cluster è attivo e funzionante, e la mia casa non è più un disastro.
Solo il tempo mi dirà cosa farò con questo cluster.
Tuttavia, ho pensato di aggiungere Prometheus e Grafana per avere alcune metriche e grafici utili per controllare il cluster.
Anche migrare tutti i miei file Kubernetes su Helm sarebbe una buona idea.
Infine, l'istanza di Retroarch è ancora in lavorazione. Forse in lavorazione è un po' troppo ottimistico, dato che il pod vive nello stato CrashLoopBackOff. Ma ci arriverò.
Se siete arrivati alla fine di questo post, vi ringrazio per il tempo che mi avete dedicato. Spero che vi sia piaciuto tanto quanto a me mettere insieme il cluster e scriverne.