Michal Marunič, TUKE FEI -- katedra: KPS, odbor: Počítačové siete
Cloudové technológie už dávno nie sú výsadou veľkých dátových centier. Pre menšie firmy, výskumné tímy alebo nadšencov môže byť vlastný privátny cloud reálnou a cenovo dostupnou alternatívou, najmä keď ho postavíte na edge hardvéri s GPU akceleráciou. V tomto blogu si ukážeme, ako na dvoch zariadeniach NVIDIA Jetson Orin Nano vybudovať funkčný privátny edge cloud s podporou Kubernetes, od prvého bootu až po spustenie AI inferencie priamo v klastri.
Text vychádza z mojej bakalárskej práce zameranej na návrh a evaluáciu privátnych cloudových riešení. Cieľom blogu je stručne a prehľadne prejsť kroky, ktoré viedli k funkčnému riešeniu -- od inštalácie systému až po spustenie inferencie modelu YOLOv8 v Kubernetes klastri.
Prečo práve Jetson Orin Nano a edge cloud?
Privátny edge cloud znamená, že výpočty a služby prevádzkujeme na vlastnej infraštruktúre, čo najbližšie k miestu vzniku dát. V praxi to prináša nižšiu latenciu, väčšiu kontrolu nad prostredím a menšiu závislosť od externého cloudového poskytovateľa.
Jetson Orin Nano je pre takýto scenár zaujímavý tým, že kombinuje ARM procesor, GPU architektúrou Ampere a nízku spotrebu. Oproti bežným SBC zariadeniam tak neponúka iba všeobecné výpočty, ale aj reálne využiteľnú GPU akceleráciu pre AI workloady.
Čo sme použili
Hardvér:
- 2× NVIDIA Jetson Orin Nano Developer Kit
- 2× M.2 NVMe SSD, ideálne aspoň 256 GB
- 2× microSD karta (128 GB) na počiatočnú inštaláciu
- Router na pripojenie do siete
Softvér:
- NVIDIA JetPack 6.2.1 (Ubuntu 22.04.5 LTS)
- K3s
- Portainer CE
- kube-prometheus-stack (Prometheus + Grafana)
Po počiatočnom nastavení je možné celý ďalší postup realizovať cez SSH, bez potreby fyzického prístupu k zariadeniam.
Inštalácia JetPack a základná sieťová konfigurácia

Najskôr je potrebné pripraviť JetPack obraz na microSD kartu, prejsť
úvodným nastavením Ubuntu a následne na oboch zariadeniach nastaviť
statickú IP adresu. V tomto prípade boli použité adresy 147.232.159.208
(master uzol) a 147.232.159.12 (worker uzol). Pridelené adresy sú
overené príkazom ifconfig, ako je zobrazené na obr. 1.
Aktivácia maximálneho výkonu
Ak chceme porovnávať výkon alebo vykonávať konzistentné testy, je vhodné zariadenie prepnúť do maximálneho výkonového režimu a zafixovať frekvencie CPU, GPU a pamäte ako na obrázku 2.
sudo nvpmodel -m 0 # MAXN SUPER
sudo jetson_clocks # zafixuje maximálne frekvencie
sudo nvpmodel -q # overenie
sudo jetson_clocks --show

Nastavenie maximálneho výkonového režimu Jetson Orin Nano je možné spraviť aj cez GUI.
Migrácia systému z microSD na NVMe SSD
Presun systému z microSD karty na NVMe SSD patril medzi najdôležitejšie kroky pri budovaní privátneho edge cloudu na platforme NVIDIA Jetson Orin Nano. Dôvodom je výrazne vyšší výkon NVMe SSD pri náhodných I/O operáciách, ktoré sa v kontajnerovom prostredí často vyskytujú pri práci s obrazmi kontajnerov, databázami, perzistentnými dátami aj samotným súborovým systémom. Použitie rýchlejšieho úložiska sa preto prejavilo nielen pri bežnej práci so systémom, ale aj pri nasadzovaní cloudových workloadov.
Migrácia bola realizovaná klonovaním obsahu microSD karty na NVMe SSD
pomocou nástroja dd, následným rozšírením súborového systému a úpravou
boot konfigurácie pomocou skriptu configure_ssd_boot.sh z projektu
JetsonHacks. Po aktualizácii initramfs a reštarte zariadenia bol úspech
migrácie overený príkazom df -h /, ktorý potvrdil koreňový súborový
systém na zariadení /dev/nvme0n1p1.
Postup migrácie:
# 1. Klonovanie microSD na SSD
sudo dd if=/dev/mmcblk0 of=/dev/nvme0n1 bs=64M status=progress conv=sync
# 2. Rozšírenie filesystému na celú kapacitu SSD
sudo e2fsck -f /dev/nvme0n1p1
sudo resize2fs /dev/nvme0n1p1
# 3. Konfigurácia bootu pomocou JetsonHacks skriptu
git clone https://github.com/jetsonhacks/migrate-jetson-to-ssd.git
cd migrate-jetson-to-ssd
sudo ./configure_ssd_boot.sh -d /dev/nvme0n1
# 4. Aktualizácia initramfs a reštart
sudo update-initramfs -u
sudo reboot
Po reštarte je možné správnosť migrácie overiť príkazom:
df -h /

Ak sa ako koreňový súborový systém zobrazí /dev/nvme0n1p1, zariadenie
úspešne bootuje z SSD disku.
Prepínanie bootu medzi microSD a NVMe SSD
Pre potreby experimentovania, opakovaného testovania a porovnávania
správania systému na oboch úložiskách boli v rámci práce vytvorené aj
vlastné pomocné skripty boot_ssd.sh a boot_micro-sd.sh. Tieto skripty
nepredstavujú univerzálny všeobecný návod pre všetky zariadenia Jetson,
ale ide o prakticky viacnásobne overené riešenie použité na konkrétnej
konfigurácii NVIDIA Jetson Orin Nano Developer Kit v tejto práci. Ich
účelom bolo umožniť rýchle prepínanie bootu medzi microSD kartou a NVMe
SSD bez potreby vstupu do UEFI rozhrania a bez ručnej editácie boot
konfigurácie pri každom teste.
boot_ssd.sh -- prepne boot na NVMe SSD:
#!/bin/bash
echo "Prepínam boot na NVMe SSD..."
sudo cp /boot/extlinux/extlinux.conf /boot/extlinux/extlinux.conf.bak
sudo sed -i 's|root=/dev/mmcblk0p1|0xdev/nvme0n1p1|g' /boot/extlinux/extlinux.conf
sudo sed -i 's|0xdev/nvme0n1p1|root=/dev/nvme0n1p1|g' /boot/extlinux/extlinux.conf
sudo sed -i '/FDT/d' /boot/extlinux/extlinux.conf
echo "FDT /boot/tegra234-p3768-0000+p3767-0000-nvme.dtb" | sudo tee -a /boot/extlinux/extlinux.conf > /dev/null
sudo update-initramfs -u
echo "Boot nastavený na NVMe SSD"
echo "Spusti: sudo reboot"
boot_micro-sd.sh -- prepne boot späť na microSD:
#!/bin/bash
echo "Prepínam boot na microSD kartu..."
sudo cp /boot/extlinux/extlinux.conf /boot/extlinux/extlinux.conf.bak
sudo sed -i 's|root=/dev/nvme0n1p1|0xdev/mmcblk0p1|g' /boot/extlinux/extlinux.conf
sudo sed -i 's|0xdev/mmcblk0p1|root=/dev/mmcblk0p1|g' /boot/extlinux/extlinux.conf
sudo sed -i '/FDT/d' /boot/extlinux/extlinux.conf
sudo update-initramfs -u
echo "Boot nastavený na microSD"
echo "Spusti: sudo reboot"
Oba skripty najskôr vytvoria zálohu súboru extlinux.conf, následne
upravia zariadenie použité ako koreňový súborový systém a pri prepnutí
na NVMe SSD doplnia aj príslušný Device Tree Blob. Po vykonaní zmien je
potrebné aktualizovať initramfs a zariadenie reštartovať. Takýto postup
sa v experimentálnom prostredí osvedčil ako spoľahlivý a výrazne
zrýchlil opakované testovanie výkonu systému pri boote z rôznych
úložísk.
Na jednoduché prepnutie bootu je možné použiť aj priamo skript
configure_ssd_boot.sh, a to podľa cieľového zariadenia:
cd ~/migrate-jetson-to-ssd
sudo ./configure_ssd_boot.sh -d /dev/nvme0n1
sudo update-initramfs -u
sudo reboot
alebo pre návrat na microSD:
cd ~/migrate-jetson-to-ssd
sudo ./configure_ssd_boot.sh -d /dev/mmcblk0
sudo update-initramfs -u
sudo reboot
Tento spôsob predstavoval najjednoduchšiu variantu prepnutia bootu, zatiaľ čo vlastné skripty boli využívané najmä pri opakovaných experimentoch boot konfigurácie v konkrétnom testovacom prostredí.
Inštalácia K3s a vytvorenie klastra
Na prvom Jetsone nainštalujeme K3s ako riadiaci uzol. Následne si uložíme token a na druhom zariadení ho pripojíme ako worker node.
Master node:
curl -sfL https://get.k3s.io | sh -
# Overenie stavu
sudo kubectl get nodes
# Uloženie tokenu pre worker node
sudo cat /var/lib/rancher/k3s/server/node-token
Worker node:
curl -sfL https://get.k3s.io | \
K3S_URL=https://<MASTER_IP>:6443 \
K3S_TOKEN=<TOKEN> \
sh -
Na master uzle si následne overíme, že sú oba uzly v stave Ready:
kubectl get nodes

Podpora GPU v Kubernetes
Ak chceme v klastri spúšťať AI workloady, je potrebné doplniť NVIDIA Container Toolkit a NVIDIA Device Plugin. Až potom môže Kubernetes pracovať s GPU ako so štandardným zdrojom.
Inštalácia NVIDIA Container Toolkit na oboch uzloch
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart k3s # použije sa na master uzle
sudo systemctl restart k3s-agent # použije sa na worker uzle
Nasadenie NVIDIA Device Plugin na master uzle:
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.3/nvidia-deviceplugin.yml
# Overenie
kubectl describe node <MENO_UZLA> | grep nvidia
# Očakávaný výstup:
# nvidia.com/gpu: 1

Portainer a základná správa klastra
Pre jednoduchšiu správu klastra je možné nasadiť Portainer CE, ktorý poskytuje prehľadné webové rozhranie nad Kubernetes prostredím.
kubectl create namespace portainer
kubectl apply -n portainer -f \
https://raw.githubusercontent.com/portainer/k8s/main/deploy/manifests/portainer/portainer.yaml

Po vytvorení samostatného namespace portainer bol aplikovaný deployment
manifest Portainera. V testovacom prostredí bol Portainer sprístupnený
prostredníctvom služby typu NodePort.

Monitoring pomocou Promethea a Grafany
Po inštalácii K3s a GPU pluginu je vhodné doplniť monitorovací stack,
aby sme mali prehľad o využití zdrojov v klastri. Rozloženie podov
a ich správanie je možné sledovať pomocou príkazu kubectl get pods -o wide -w.
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace
kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80

Test škálovania a failoveru
Po vytvorení klastra je možné overiť, ako sa bude správať pri vyššej
záťaži alebo pri dočasnom vyradení jedného uzla. Jednoduchým testom je
nasadenie viacerých replík NGINX a následné dočasné vyradenie worker
uzla z plánovania. Rozloženie podov aj ich správanie po vykonaní príkazu
drain je možné sledovať pomocou príkazu kubectl get pods -o wide -w.
kubectl create deployment nginx-test --image=nginx --replicas=100
kubectl expose deployment nginx-test --port=80 --type=NodePort
# Rozloženie podov na oba uzly
kubectl get pods -o wide | grep nginx-test
kubectl drain student-jetson-master --ignore-daemonsets --delete-emptydir-data
kubectl get pods -o wide -w
kubectl uncordon student-jetson-master


GPU inferencia modelu YOLOv8
Na záver je možné overiť aj praktické využitie GPU v klastri. V tomto prípade bol spustený Kubernetes Job, ktorý vykonáva inferenciu modelu YOLOv8 nad testovacím videom.
Na overenie praktického využitia GPU akcelerácie v klastri bol použitý
manifest yolo-job.yaml, ktorý spúšťal inferenciu modelu YOLOv8 nad
testovacím videosúborom. Použitý manifest je zobrazený na obr. 10 a
výsledok inferencie je overený výstupom logov na obr. 11.


Záver
Na dvoch zariadeniach NVIDIA Jetson Orin Nano je možné vybudovať funkčný privátny edge cloud, ktorý podporuje viacuzlový Kubernetes klaster, správu workloadov, základný failover, monitoring aj GPU akcelerované AI úlohy.
Takéto riešenie môže slúžiť ako experimentálne laboratórium, výučbová platforma alebo základ pre vlastné edge AI aplikácie. Výhodou zostáva otvorenosť riešenia, nízka spotreba energie oproti iným riešeniam a možnosť pochopiť cloud-native technológie na menšej, ale reálnej infraštruktúre.