Skip to content

Pamiro blog

Menu
  • Strona główna
Menu

Konfiguracja serwera Ubuntu część 3

Posted on 2025-02-262025-02-28 by forteller

Przenosiny z ZFS na bcache+(mdadm+btrfs)

Tym razem dokonuję przenosin z macierzy mirror ZFS na stack składający się z macierzy RAID1 zbudowanej za pomocą mdadm, z jedną partycją sformatowaną systemem plików btrfs. Będzie hardkorowo, bez obrazków – tylko polecenia w bashu 🙂

Kluczowe punkty związane z tą decyzją:

  • Łatwa możliwość migracji z obecnego RAID1 na RAID5 w przyszłości
  • Lepsza integracja w środowisku Linux (normalne mount/umount i wpis w /etc/fstab. Po roku używania wciąż nie wiem kiedy używa się polecenia zfs a kiedy zpool)
  • btrfs oferuje wszystkie cechy które były dla mnie atrakcyjne w ZFS: CoW, subvols i kompresja. Snapshoty też są, ale prawie ich nie używam.
  • Ostatnio w formie eksperymentu „dokleiłem” dysk NVMe jako special device do mojej puli nie zdając sobie sprawy z konsekwencji i nieodwracalności tego procesu, więc i tak musiałem zaorać obecną pulę.

Moja macierz składa się z dwóch dysków 18TB w konfiguracji mirror, na której znajduje się 10,2TB danych. Aby dokonać manewru o którym piszę i przenieść się z ZFS na BTRFS, potrzebowałem gdzieś te dane tymczasowo przetrzymać. Do tego celu posłużyły mi dwa dyski 8TB na których skonfigurowałem macierz RAID0 oraz sformatowałem je w systemie plików EXT4. Poniżej będę dokumentował krok po kroku proces przenosin.

Plan

  • Stworzenie macierzy RAID0 (tymczasowy stripe) na dwóch dyskach 8TB po to aby tymczasowo przetrzymać dane.
    • Istotne aby dyski których użyjemy byly w dobrym stanie.
  • Przełączenie ZFS (stary mirror) w tryb readonly.
  • Kopiowanie danych ze starego mirrora na tymczasowy stripe.
  • Odmontowanie / export puli ZFS i zamontowanie tymczasowego stripe w miejscu dotychczasowej puli.
  • Wyczyszczenie dysków stanowiących dotychczas pulę ZFS oraz postawienie RAID1 (nowy mirror).
  • Przełączenie tymczasowego stripe w tryb readonly.
  • Kopiowanie danych z tymczasowego stripe na nowy mirror.
  • Zamontowanie nowego mirrora w miejscu tymczasowego stripe.

Stworzenie macierzy tymczasowej na przetrzymanie danych

wipefs -a /dev/sdc /dev/sdd
mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/sdc /dev/sdd
mkfs.ext4 -F /dev/md0

Raczej nie wymaga wyjaśnień: wyczyszczenie systemów plików, stworzenie programowej macierzy RAID0, sformatowanie macierzy w systemie plików EXT4.

Przygotowanie do migracji danych

zfs set readonly=on old_pool
(reboot)
mkdir /mnt/temp_pool
mount /dev/md0 /mnt/temp_pool

Przestawiam macierz w tryb readonly po to, aby po przeniesieniu danych na nową macierz mieć kopię 1:1 danych. Gdybym tego nie zrobił, dane zmieniałyby się w trakcie. Restart wykonuję po to, aby wszystkie usługi „pogodziły się z faktem”, że są montowane na zasobie działającym w trybie readonly. Nastepnie tworzę mountpoint i montuję zasób.

Przenoszenie danych

tmux
sudo rsync -aHAX --progress --info=progress2 /old_pool/ /mnt/temp_pool/

Odpalam tmux aby proces cały czas działał w tle. Opis poszczególnych parametrów rsync:

  • -a – tryb archiwizacji (zachowuje uprawnienia, symlinki, daty modyfikacji itp.).
  • -H – zachowuje twarde linki.
  • -A – zachowuje listy ACL.
  • -X – zachowuje rozszerzone atrybuty.
  • –progress – wyświetla postęp kopiowania.
  • –info=progress2 – pokazuje bardziej szczegółowe informacje o postępie kopiowania całkowitego.
    • …ale nie działa prawidłowo przy dużej liczbie plików i pokazuje głównie głupoty 🙂

Po wykonaniu powyższego polecenia trzeba się uzbroić w cierpliwość. U mnie 10,2TB kopiowało sie 20,5 godziny, co daje średni transfer na poziomie 145MB/s.

Weryfikacja czy wszystkie dane są na miejscu

Tutaj warto spędzić chwilę i porównać zawartość danych w /old_pool/ oraz w /mnt/temp_pool/

Użyłem do tego celu programu ncdu który potrafi ładnie wizualizować zajętość miejsca w poszczególnych katalogach. Tutaj jako ciekawostkę podam, że mój zestaw danych zajmował 200GB miejsca więcej na ext4 niż na ZFS z aktywną kompresją. Jednak coś ta kompresja daje 🙂

Kilka kluczowych aspektów do sprawdzenia:

  1. Czy skopiowały się ukryte pliki?
  2. Czy linki symbolicznie przeniosły sie poprawnie?
  3. Czy timestampy są prawidłowe?
  4. Czy poszczególne katalogi zajmują tyle miejsca co powinny?

Wyłączam montowanie puli

sudo systemctl mask zfs-mount
sudo zfs set canmount=off old_pool
(reboot)
sudo zfs export old_pool

Powyższymi poleceniami upewniam się, że pula zfs przestaje być widoczna w systemie i mogę spokojnie zamontować tymczasowego stripe’a w miejsce dotychczasowej puli.

Podmiana puli ZFS na tymczasowy stripe

Dodaję wpis do /etc/fstab:

/dev/md0 /old_pool ext4 defaults,noatime 0 1

Nastepnie restartuję ponownie serwer aby wszystkie usługi mogły załadować się poprawnie z danymi na innej macierzy.

Sprawdzenie czy wszystkie usługi działają poprawnie na tymczasowym stripe

Sprawdziłem nastepujące rzeczy:

  1. Montowanie 'bind’ w dockerze
  2. smb
  3. nfs
  4. KVM/QEMU i czy maszyny wirtualne, które są na tych dyskach poprawnie się włączają

Point of no return

W tym momencie powinniśmy mieć kopię danych 1:1 na obu macierzach: starej i tymczasowej. Jest to punkt z którego można jeszcze zawrócić i przywrócić konfigurację w której dane będą dostepne na starym mirrorze. Po przejściu dalej ta możliwośc zostanie utracona.

Czyszczenie dysków ze starego mirrora

sudo wipefs -a /dev/sda
sudo wipefs -a /dev/sdb
sudo wipefs -a /dev/nvme0n1
sudo dd if=/dev/zero of=/dev/sda bs=1M count=100
sudo dd if=/dev/zero of=/dev/sdb bs=1M count=100
sudo dd if=/dev/zero of=/dev/nvme0n1 bs=1M count=100

sda i sdb były mirrorem, nvme0n1 to był special device.

Aktualizacja 28.02.2025

Z moich testów wychodzi, że bcache ma duże problemy z wydajnością, gdy caching device jest ustawiony na całe urządzenie blokowe, dlatego też tam gdzie używałem wcześniej w tym wpisie „nvme0n1”, teraz widnieje „nvme0n1p1”. Używam jednej partycji na cały dysk.

Tworzenie macierzy i systemu plików

sudo mdadm --create --verbose /dev/md1 --level=1 --raid-devices=2 /dev/sda /dev/sdb
sudo make-bcache -B /dev/md1 -C /dev/nvme0n1p1
sudo mkfs.btrfs /dev/bcache0

Skonfigurowane w ten sposób, nvme0n1p1 będzie stanowiło „cache device”, a sda i sdb stworzą md0 które będzie stanowiło „backing device”. Od tego momentu, wszystkie trzy dyski będą dostepne jako block-device pod ścieżką /dev/bcache0 (dlatego system plików tworzymy na /dev/bcache0)

Tuning bcache

W pliku /etc/tmpfiles.d/bcache.conf wpisujemy następujące parametry:

w /sys/block/bcache0/bcache/cache_mode - - - - writeback
w /sys/block/bcache0/bcache/writeback_percent - - - - 40
w /sys/block/bcache0/bcache/sequential_cutoff - - - - 0
w /sys/block/bcache0/bcache/cache/congested_write_threshold_us - - - - 0
w /sys/block/bcache0/bcache/cache/congested_read_threshold_us - - - - 0

Poszczególne parametry oznaczają nastepujące rzeczy:

  • cache_mode: domyślnie aktywny jest tryb writethrough. Mi zależy na przyspieszeniu zapisów oraz mam UPS, dlatego włączam writeback
  • writeback_percent: domyślnie 10. Oznacza ile procent miejsca przeznaczone jest na zapisy. Niestety 40% to sztywny limit bcache, który żeby podnieść, trzeba przebudować kernel. Na moim dysku SSD 512GB będzie to około 190GB. Chciałbym móc wykorzystać cały dysk jako cache, ale na poczatek 190GB wystarczy.
  • writeback_delay: 1 oznacza opóźnienie zapisu do HDD o 1s. Powinno zoptymalizować zapisy.
  • sequential_cutoff: domyślnie cache’owane są pliki o maksymalnej wielkości 4MB. Ja chcę cache’ować zapisy po 100GB, więc wyłączam ten limit.
  • congested_write_threshold_us: ustawienie na 0 powoduje wyłączenie throttlingu odczytów z cache device. W efekcie prefereowane są odczyty z NVMe.
  • congested_read_threshold_us: ustawienie na 0 powoduje wyłączenie throttlingu zapisów na cache device. W efekcie prefereowane są zapisy na NVMe. Bez tego write cache praktycznie nie działał.

Aby natychmiast zaaplikować zmiany wprowadzone w /etc/tmpfiles.d/bcache.conf należy wykonać polecenie:

sudo systemd-tmpfiles --create

Przełączenie tymczasowego stripe w tryb readonly

Zaczynamy powtarzać procedurę z przerzucaniem danych. Modyfikujemy wcześniejszy wpis w /etc/fstab:

/dev/md0 /old_pool ext4 ro,noatime 0 1

Restart komputera i sprawdzenie czy wszystko poprawnie przeszło w tryb readonly.

Zamontowanie w tymczasowym miejscu

tmux
sudo mount -o compress=zstd:3 /dev/bcache0 /mnt/temp_pool
sudo rsync -aHAX --progress --info=progress2 /old_pool/ /mnt/temp_pool/

Montuję nowy mirror w tymczasowym miejscu i uruchamiam kopiowanie z tymczasowego stripe’a na nowego mirrora. Znów doba czekania…

Podmiana mountpoint

Wcześniejszy wpis w fstab podmieniamy na nastepujący:

/dev/bcache0  /old_pool  btrfs  defaults,noatime,compress=zstd:3,discard=async  0  1

Restartuję komputer i cała operacja zostaje zakończona.

Profit

Wydajność momentami kuleje, ale testowałem również z niekompresowalnymi danymi i byłem w stanie zapisać 122GB na NASie bez żadnego spowolnienia (czas trwania zapisu: 1m52s), caly czas saturując łącze 10Gbit (czas trwania zapisu: 1m52s).

Dodaj komentarz Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Ostatnie wpisy

  • openmediavault strikes back
  • Używanie virt-manager spod wsl
  • Konfiguracja serwera Ubuntu część 3
  • Wygaszacz ekranu na tablecie na ścianie
  • Mody LiitoKala Lii-M4S

Najnowsze komentarze

  1. Pati - Mody LiitoKala Lii-M4S
  2. forteller - Serwer zlotowy 4.0
  3. Neo - Serwer zlotowy 4.0
  4. Jerrry - Arosa zagrożeniem pożarowym
  5. forteller - Zlot 3dfx.pl v11.0 i ciąg dalszy
© 2025 Pamiro blog | Powered by Minimalist Blog WordPress Theme