Odroid C1+, czyli miniaturyzacja przyszłością komputeryzacji

Potrzebowałem małego i energooszczędnego serwera plików. Wydajność nie ma wielkiego znaczenia, chodzi  bardziej o przechowywanie dużych plików (głównie samodzielnie stworzonych materiałów video) niż aktywną pracę. Mam mnóstwo zbędnych dysków USB, dokupiłem hub USB z zasilaniem, pozostał tylko jeden drobiazg: komputer. Oczywisty wybór to Raspberry Pi. Mam już w domu Raspberry Pi 2, który służy jako odtwarzacz audio/video, mam też Zero, który obecnie nic nie robi, ale jest za wolny i nie ma ethernetu. Zajrzałem więc do sklepów, zobaczyłem ceny i... rozejrzałem się za używanymi. Też drogo i niewiele. A jakiś inny mały komputer, może Odroid? Bingo, jest niedrogi C1+, w dodatku we Wrocławiu.

Odroidy nigdy nie zdobyły takiej popularności jak Raspberry Pi. Trudniej znaleźć o nich artykuły czy tutoriale na youtube, przez to mniej osób z nich korzysta, a więc i mniej osób tworzy tutoriale, więc koło się zamyka. Jeśli chodzi o sprzęt, Odroid C1+ bije na głowę pierwszą i drugą wersję Malinki, od trzeciej jest nieco lepiej wyposażony,  przegrywa dopiero z dużo droższą czwartą generacją. Do tego nie ma problemów z przegrzewaniem, które zdarzają się w Pi 3 i 4 (jak widać poniżej, ma całkiem zdrową temperaturę). Na małej płytce zmieścił się czterordzeniowy procesor 1.5GHz, 1GB RAM-u, slot micro-SD i eMMC, 4 porty USB 2.0 plus jeden USB-OTG i gigabitowy ethernet. Wolałbym USB 3.0, za to reszta specyfikacji przewyższa moje potrzeby. System dostarczony przez producenta to Android albo Ubuntu, niestety tylko antyczne wersje (najnowsza to 18.04), ale można zaktualizować. Ambitni mogą również zbudować własny obraz systemu. Początkowo chciałem być ambitny.

Pierwsze zaskoczenie - Odroid nie zgłasza się w sieci, nawet dioda przy porcie Ethernet się nie świeci. Podłączam monitor - brak obrazu. Kontaktuję się ze sprzedawcą, który radzi sprawdzić obraz systemu i kartę pamięci. Okazuje się, że Odroid bez systemu nie włączy portu ethernet ani nic nie wyświetli. Rzeczywiście, nagrałem oficjalny system i wszystko ruszyło. Drugie zaskoczenie  - aktualizacja pakietów trwała 6 godzin. To zapewne wina karty SD, podobno na eMMC system jest znacznie szybszy. No ale miało być niskobudżetowo, a poza tym w codziennej pracy to nie będzie miało znaczenia.

Dyski. Dużo dysków

Mam dużo zewnętrznych dysków, za to nie mam zbyt dużo zaufania do ich niezawodności. Z normalnymi dyskami użyłbym RAID, ale RAID na USB, zwłaszcza 2.0 i zwłaszcza przy dużych pojemnościach to Bardzo Zły Pomysł. Dlaczego? RAID wymaga synchronizacji pomiędzy urządzeniami, przy małej prędkości USB i terabajtowych pojemnościach okresowe sprawdzanie stanu macierzy trwałoby kilka dni, a wydajność serwera, nawet w normalnych warunkach niewielka, stałaby się żadna. Na szczęście RAID nie będzie potrzebny, bo dane nie zmieniają się często. Dobrałem więc dyski parami, ale nie łączyłem ich w RAID. Zamiast tego dodałem do crona skrypt, który co noc kopiuje zmienione pliki na zapasowy dysk z każdej pary.

Ważną sprawą do ogarnięcia są trwałe nazwy urządzeń (persistent device naming, nie mam pojęcia jak to się oficjalnie tłumaczy). Litery przydzielane dyskom mogą się zmienić, obecny dysk sdb po reboocie może stać się sdc. Rozwiązań jest kilka, np. etykiety systemów plików, UUID albo użycie LVM, który zawsze skanuje wszystkie urządzenia i jest mu wszystko jedno gdzie i w jakiej kolejności je znajdzie. Najprostsze rozwiązanie to etykiety. Podłączyłem więc na razie dyski do peceta, sformatowałem system plików. Korzystając z okazji, od razu przeniosłem na nie część plików.

lsblk
mkfs.ext4 -m 0 -L 'other1' /dev/sdd1
mkfs.ext4 -m 0 -L 'other1-backup' /dev/sde1
mkdir /media/u1 /media/u2
mount -L other1 /media/u1
mount -L other1-backup /media/u2/


Tych samych etykiet użyłem potem w /etc/fstab na docelowym systemie:
LABEL=other1     /media/other1    ext4   nodev,noexec,noatime,nofail,x-systemd.device-timeout=4 0 0
LABEL=other1-backup     /media/other1-backup    ext4   noauto,nodev,noexec,noatime,nofail,x-systemd.device-timeout=4 0 0


Co oznaczają opcje? Nodev i nosuid zwiększają bezpieczeństwo - system zignoruje pliki wykonywalne i pliki urządzeń. W większości zastosowań (poza, być może, backupowaniem innych linuksowych komputerów), nie są one do niczego potrzebne na serwerze plików. Opcja noatime powoduje,  że system nie zapisuje czasu ostatniego dostępu do pliku, co odrobinę poprawia wydajność. Przez ponad 20 lat korzystania z Linuxa nigdy nie potrzebowałem tej informacji. Wreszcie ostatnie opcje powodują, że systemd będzie czekać 4 sekundy na zamontowanie dysku, a jeżeli to się nie uda - przejdzie dalej. Bez tej opcji systemd zatrzymałby start systemu, gdyby któregoś urządzenia zabrakło.

Nie mamy pańskiego dysku i co nam pan zrobi?


Ułożyłem stosik ośmiu dysków. Wcisnąłem pomiędzy nie przekładki i skleiłem całość szarą taśmą. To oczywiście prowizorka, wiadomo jednak, że prowizorki są często najbardziej trwałe. Podłączyłem wszystkie do zasilanego huba USB, a hub - do Odroida. W dmesg pojawiła się natychmiast masa komunikatów o błędach, a lsblk pokazał tylko połowę urządzeń. Dyski talerzowe pobierają sporo prądu, na granicy tego, co gwarantuje standard USB, albo i poza tą granicą. Hub USB z mocnym zasilaczem bez problemu dostarczy tyle prądu ile trzeba, ale nie każdy kabel prześle tyle bez większych strat. Doświadczalnie ustaliłem, które kable sprawiały problemy, wymieniłem na inne - błędy ustały.

Kolejny problem - nie da się zamontować systemów plików. Odroid informuje: Unrecognised features on journal. No tak, sformatowałem dyski na komputerze ze znacznie nowszym kernelem i dlatego korzystają z opcji, których serwerek nie potrafi obsłużyć. Chwila guglania wykazała, że muszę kolejno: sprawdzić system plików, nawet jeśli nie zawiera żadnych błędów; usunąć opcję "metadata checksum", usunąć journal, skonwertować system plików z 64 na 32 bity, co wymaga użycia nie tylko tune2fs, ale również resize2fs... bez zmiany rozmiaru, a następnie ponownie utworzyć journal. Brzmi skomplikowanie, ale sprowadziło się do uruchomienia kilku poleceń w pętli:

for i in d e f g h i ; do fsck -af /dev/sd${i}1 ;  tune2fs -O '^metadata_csum,^has_journal,^64bit' /dev/sd${i}1 ;  resize2fs -s /dev/sd${i}1 ; tune2fs -j /dev/sd${i}1 ; done


Skonfigurujemy to panu hurtowo


Dla wprawy postanowiłem całą konfigurację przeprowadzić przy użyciu Ansible'a. To tylko jeden serwer, więc ręcznie byłoby szybciej, ale przyszła pora na przypomnienie sobie tego narzędzia. A poza tym, jeżeli zachcę zmienić serwer bo np. wydajność okaże się niewystarczająca albo odroid się zepsuje, wystarczy ponownie uruchomić playbook.

Ansible ma wielką zaletę w porównaniu do zwykłych skryptów: nie wpisujemy poleceń do wykonania, a docelowy stan. Można wielokrotnie uruchamiać ten sam playbook i Ansible nie spróbuje ponownie zainstalować tych samych pakietów czy tworzyć tego samego konta użytkownika. Dzięki temu możemy tworzyć konfigurację stopniowo, poprawiając błędy i dodając nowe elementy.

Główny playbook odroid.yml jest bardzo prosty. Jedyne jego zadanie to uruchomić dwie role:  common_linux i nas. Wszystko, co ważne, kryje się w rolach. Common-linux to wspólna konfiguracja dla wszystkich maszyn z Debianem lub Ubuntu, którymi zarządzam. Obejmuje więc takie rzeczy jak stworzenie konta użytkownika igor i wysłanie klucza publicznego ssh, aktualizację pakietów, instalację kilku programów, które uznałem za obowiązkowe wyposażenie, skonfigurowanie strefy czasowej. Całość skleciłem wzorując się na kilku playbookach znalezionych w Ansible Galaxy.

Rola nas zawiera o wiele więcej. Na tyle dużo, że podzieliłem ją na kilka plików. Dlatego main.yml zawiera tylko:
---
- import_tasks: mountpoints.yml
- import_tasks: samba.yml
- import_tasks: other.yml


Plik tasks/samba.yml, a także większość zawartości pozostałych podkatalogów, wziąłem z https://github.com/bertvv/ansible-role-samba i nieznacznie tylko zmodyfikowałem. Dodałem natomiast dwa pliki zawierające zadania do zrobienia przed i po konfiguracji samby. Przed muszę stworzyć konto systemowe, które będzie właścicielem plików udostępnianych przez Sambę i dodać wpisy do /etc/fstab, natomiast po wykonać jeszcze kilka drobnych, ale ważnych zadań:
- zainstalować i skonfigurować wsdd, czyli Web Service Discovery, program, który umożliwa Windows 10 znalezienie zasobów Samby w sieci lokalnej,
- zainstalować i skonfigurować program hd-idle, który wyłącza dyski USB, jeżeli są nieużywane przez określony czas,
- wygenerować skrypt, który wykona kopię każdego dysku roboczego na odpowiadający mu dysk zapasowy.
To ostatnie zadanie pokazuje siłe Ansible'a. Wystarczy kilka linijek w playbooku:
 

- name: Generate backup script
  template:
    dest: /etc/cron.daily/rsync-backup.sh
    src: rsync-backup.sh.j2
 

I bardzo krótki template:


#!/bin/bash
# rsync backup file -- Managed by Ansible, please don't edit manually
#

{% for share in samba_shares %}
mount /media/-backup && \
  rsync -va /media// /media/backup/
umount /media/-backup

{% endfor %}


Zmienna samba_shares zawiera listę udostępnianych systemów plików. Pozwoliłem sobie jej użyć również w moich playbookach. Jeżeli teraz dodam nową parę dysków, wystarczy jeden nowy wpis w samba_shares by wygenerować nie tylko odpowiedni plik konfiguracyjny Samby, ale też dodać wpis w /etc/fstab, stworzyć katalog, nadać mu odpowiednie prawa dostępu i wygenerować skrypt tworzący kopię zapasową.

DIY kontra COTS

Porównałem wydajność tego serwera z komercyjnym NAS-em, Synology DS216SE. Łącznie cztery scenariusze: zapis i odczyt oraz duży plik i katalog pełen małych plików. Jak można się było spodziewać, nie jest dobrze, zwłaszcza przy odczycie (Synology korzystał z RAID1, co może przyspieszyć odczyt, ale spowalnia zapis). Wąskim gardłem jest USB 2.0, Odroid ma czterokrotnie więcej RAM-u i znacznie szybszy procesor, przegrywa jedynie interfejsem dyskowym. Cenowo wygląda dużo korzystniej (zwłaszcza, że dyski miałem za darmo), ten model Synology co prawda nie jest już produkowany, ale najtańszy współczesny model dwudyskowy kosztuje prawie 1000 zł, o wielodyskowych nie wspominając.

Samoróbka ma też większe możliwości rozbudowy. Jeżeli zabraknie miejsca, mogę dołożyć drugi hub USB i kolejny zestaw dysków. Jeżeli okaże się, że wydajność przestała wystarczać, mogę pozostawić dyski i podmienić serwer.

Z drugiej strony, Synology skonfigurowałbym w pół godziny, w Odroidzie dłubałem kilka dni. A i to dlatego, że z grubsza wiedziałem co robię, nietechniczny użytkownik być może poradziłby sobie z gotowym NAS-em, z Ubuntu na Odroidzie na pewno nie. Z trzeciej zaś, i tak chciałem na czymś potrenować.

Komentarze