міграція контейнерів на сервер v2

| щоденник, комп'ютери, linux, сервер, поновлюється

прийшов час зробити те, про що давно з острахом думаю — перенести контейнери docker з кількома важливими для мене сервісами (traefik, owncloud, jekyll, lighttpd) зі старого сервера (hp compaq dc5800, debian/docker) на новий сервер v2 (hp compaq 8100 elite, debian/proxmox/docker). під час міграції хочу замінити traefik на caddy, а потім — перейти з owncloud до nextcloud, налаштувати резервне копіювання даних тощо.

зміст

підготовка

віртуальну машину, котру колись вже починав готувати для цієї міграції, я успішно перевикористав для випроби yunohost, тож доведеться створити нову — для цього спершу тре зрозуміти, якого розміру вона потрібна, спланувати сховище.

збирання інформації

старий сервер. система:

# аптайм, просто заради інтересу
> uptime
 18:13:23 up 285 days, 22:04,  1 user,  load average: 0.25, 0.26, 0.30
# версія ядра, дистрибутив
> uname -a
Linux server 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u5 (2019-08-11) x86_64 GNU/Linux
# версія дистрибутиву
> cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
> cat /etc/debian-version
9.13

процесор:

# процесор (для приблизного налаштування вм)
> lscpu
Architecture:          x86_64
Core(s) per socket:    2
Socket(s):             1
Model name:            Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz
...

оперативна пам’ять:

# оперативна пам'ять, дискова підкачка
> free -h
              total        used        free      shared  buff/cache   available
Mem:           7.7G        986M        1.5G         39M        5.2G        6.4G
Swap:          3.7G        4.4M        3.7G

накопичувачі:

# конфігурація накопичувачів/розділів
> lsblk -o +FSTYPE,LABEL,UUID
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT FSTYPE LABEL  UUID
sda      8:0    0  74.5G  0 disk                          
├─sda1   8:1    0  37.3G  0 part /          ext4   system 4ec92a50-7a54-4d65-b7c0-afd957dc20cb
├─sda2   8:2    0   3.7G  0 part [SWAP]     swap          643686a9-5808-4a6d-b469-18b125b9ad37
├─sda3   8:3    0     1K  0 part                          
├─sda5   8:5    0   9.3G  0 part /tmp       ext4          7e39604c-c068-4ad9-9200-2d07ed4013eb
└─sda6   8:6    0  24.2G  0 part /home      ext4          b16e8109-81be-4249-8048-f6754d6eb101
sdb      8:16   0 596.2G  0 disk                          
└─sdb1   8:17   0 596.2G  0 part /var       ext4          d377454a-5922-4f78-8d9a-33fbe55abca73
# використання накопичувачів/розділів
# (новіші версії lsblk вміють це показувати, але те, що йшло з debian 9 — ні, тож потрібен df)
> df -h -x tmpfs
Filesystem      Size  Used Avail Use% Mounted on
udev            3.9G     0  3.9G   0% /dev
/dev/sda1        37G   11G   25G  31% /
/dev/sda5       9.2G   37M  8.6G   1% /tmp
/dev/sda6        24G  4.0G   19G  18% /home
/dev/sdb1       586G  356G  201G  64% /var
overlay         586G  356G  201G  64% /var/lib/docker/overlay2/f6b1...72e5/merged
overlay         586G  356G  201G  64% /var/lib/docker/overlay2/d25e...01ea/merged

приблизне споживання ресурсів контейнерами:

# статус контейнерів: завантаження процесора, використаня пам'яті, вводу/виводу
> docker stats --no-stream
CONTAINER ID  NAME              CPU %  MEM USAGE / LIMIT     MEM %  NET I/O           BLOCK I/O        PIDS
26b45965032f  traefik           0.03%  15.1MiB / 7.722GiB    0.19%  1.81GB / 1.91GB   53.2kB / 172kB   13
8e34f986fd45  lighttpd          0.00%  10.06MiB / 7.722GiB   0.13%  417MB / 13.3GB    550MB / 0B       1
7aec87c75f23  jekyll            0.00%  310.3MiB / 7.722GiB   3.92%  38.7MB / 16.8kB   110MB / 1.05GB   3
63f2d9ab756d  pihole            0.04%  35.61MiB / 7.722GiB   0.45%  390MB / 87.1MB    950MB / 27.8GB   20
4de1f91c4ee3  owncloud          0.00%  149.9MiB / 7.722GiB   1.90%  334GB / 129GB     25.1GB / 6.71GB  13
a36dd9e3bad1  rwtxt             0.00%  8.883MiB / 7.722GiB   0.11%  38.7MB / 0B       11.3MB / 12.6GB  8
b97eb97954c3  owncloud_db_1     0.08%  91.71MiB / 7.722GiB   1.16%  86GB / 264GB      829MB / 2.34TB   50
a1ff8e464578  owncloud_redis_1  0.23%  2.543MiB / 7.722GiB   0.03%  3.19GB / 2.19GB   4.66MB / 32.8kB  7

висновки? для віртуальної машини достатньо буде:

  • 2 віртуальних ядра (залежить від співвідношення з іншими вм);
  • 1-8 гб пам’яті (динамічно);
  • 4 гб на підкачку з пулу на ssd (режим сну не потрібен);
  • 24 гб під корінь / з пулу на ssd (без окремого розділу для /home);
  • 1 гб під /tmp з пулу на ssd;
  • решту — під /var з пулу на ssd, але…
  • …окремий розділ 500+ гб під /var/lib/docker/volumes з пулу на hdd.

що я маю на сервері v2 в proxmox?

  • пам’ять: 16 гб; у використанні 92% (тому що zfs, і тестова вм yunohost);
  • пул на ssd (rpool): здоровий, 2x ssd 240 гб, вільно 220 гб;
  • пул на hdd (dpool): degraded, 4x hdd 500 гб, вільно 1,93 тб (але динамічно зарезервовано 800 гб).

ахтунг: виявляється, два з чотирьох дисків мають проблеми, і один з них — вельми серйозні… пул zfs поки що онлайн, але перш як продовжувать експерименти, треба виправити це — і додати індикатор smart до дашборду healthchecks.io, щоби більше не було сюрпризів. додатково — видалити непотрібні віртуальні машини (yuhonost, minecraft, test) і звільнити ресурси.

(назад до змісту)

ремонт zfs (знову)

найперше лізу по ssh дивитися, що з тим пулом dpool:

> sudo zpool status dpool

два з чотирьох дисків мають помилки запису, але пул «живий» (sufficient replicas exist…); помилки дуже старі, тож для початку скину їх і зачекаю якийсь час (добу?), чи вигулькнуть знову (так, wishful thinking, треба просто міняти диски, але…):

> sudo zpool clear

тим часом налаштую простенький моніторинг стану zfs; найпростіший спосіб автомагічно детектувати проблеми з накопичувачами в zfs, що я можу придумати:

> zpool list -H -o health | grep -vq "ONLINE" && echo "Error!" || echo "All good"

тепер треба створити check і згенерувати унікальний uuid на сайті healthchecks.io, і випробувати:

> /usr/sbin/zpool list -H -o health | /usr/bin/grep -vq "ONLINE" || /usr/bin/curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > /dev/null

трохи довший варіант, але він дозволяє не чекати пропущеного сигналу «все гаразд» (так працює healthcheck.io), а одразу отримати повідомлення про помилку:

> /usr/sbin/zpool list -H -o health 2>/dev/null | /usr/bin/grep -vq "ONLINE" && /usr/bin/curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/fail > /dev/null || /usr/bin/curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > /dev/null

якщо працює, можна запланувати в crontab як тригер для пінгу на healthcheck:

> sudo -i
> crontab -e
# ---- >8 ----
# ZFS health ping to healthcheck.io: щодоби о 00:01
00 01 * * * /usr/sbin/zpool list -H -o health 2>/dev/null | /usr/bin/grep -vq "ONLINE" && /usr/bin/curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/fail > /dev/null || /usr/bin/curl -fsS --retry 3 https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > /dev/null
# ---- 8< ----

тим часом стає зрозуміло, що діла не буде: принаймні один диск вперто викидає помилки, треба міняти. сервер v2 має китайський бекплейн на 6 накопичувачів 2,5”; я ще пригадую, що два горішні — це системні ssd, але котрий з чотирьох долішніх неживий? ledctl чомусь не працює…

> zpool status dpool | grep FAULTED
  ata-HGST_HTS725050A7E630_TF755AWHJ90N3M  FAULTED      0    11     0  too many errors
> lsblk -o +MODEL,SERIAL | grep TF755AWHJ90N3M
sdd        8:48   1 465.8G  0 disk            HGST_HTS725050A7E630  TF755AWHJ90N3M
> ledctl locate=/dev/sdd
ledctl: /dev/sdd: device not supported
ledctl: IBPI LOCATE: missing block device(s)... pattern ignored.

старий добрий dd робить справу (ctrl+c для зупинки блимання):

> while :; do sudo dd if=/dev/sdd of=/dev/null count=1M; sleep 1s; done

наступне питання: чим замінити? тестові (куповані за безцінь на kijiji колись для випроби бекплейна) hdd по 500 гб в мене закінчилися… є якраз чотири «порятованих» зі смітника, однаковісіньких ssd dell emc (sata 6 гбіт/с), марковані на 480 гб, але їх (не) трохи шкода (згодилися б на системні десь), вони марковані на меншу ємність (zfs не дозволяє заміни дисків менш ємними), і zfs може бути вельми примхливий щодо різних накопичувачів. розібрав старий лептоп, що вже років п’ять припадав пилюкою — витяг hdd toshiba на 1 тб (5400 rpm); якщо планувати апгрейд пулу до 4x 1 тб, то це безкоштовний початок?

поновлення (2023-12-17). придбав ще два «сміттєвих» (себто б/у) накопичувачі hdd 500 гб задешево, є чим замінити той проблемний (і, якщо доведеться, ще один). процедура:

# повідомити zfs про відключення дефектного накопичувача
# (не завжди спрацьовує, навіть після свіжого scrub'у)
> [sudo] zpool offline dpool ata-HGST_HTS725050A7E630_TF755AWHJ90N3M

тепер можу фізично «висмикнути» піддон, підсвічений раніше dd, і замінити накопичувач іншим. далі:

# ідентифікувати новий накопичувач у виводі lsblk
> lsblk -o +model,serial
sdd        8:48   1 465.8G  0 disk            HGST_HTS725050A7E630  TF655BWH0H2HTR
> ls -la /dev/disk/by-id/ | grep sdd
lrwxrwxrwx 1 root root    9 Dec 17 19:17 ata-HGST_HTS725050A7E630_TF655BWH0H2HTR -> ../../sdd

прибираю залишки попереднього використання (видаляю розділи vfat та ntfs за допомогою fdisk), повідомляю zfs про заміну (zpool replace) і перевіряю, чи почався resilvering на новому диску:

> [sudo] zpool replace dpool ata-HGST_HTS725050A7E630_TF755AWHJ90N3M ata-HGST_HTS725050A7E630_TF655BWH0H2HTR
> [sudo] zpool status dpool
  pool: dpool
 state: ONLINE
  scan: resilvered 11.0G in 00:10:27 with 0 errors on Sun Dec 17 19:27:49 2023
  ...

коли закінчиться, перевіряю, чи тепер все гаразд зі здоров’ям пулу:

> [sudo] zpool list -H
bpool   960M    141M    819M    -       -       1%      14%     1.00x   ONLINE  -
dpool   1.81T   62.1G   1.75T   -       -       4%      3%      1.00x   ONLINE  -
rpool   222G    17.6G   204G    -       -       7%      7%      1.00x   ONLINE  -

все чудово, можна продовжувати експерименти. але це вже не сьогодні: завтра на роботу, час почитати («контакт» карла сагана — виявляється, ніколи ще не читав).

поновлення (2023-12-18). вночі healthcheck отримав «здоровий» пінг від zpool і позвітував зеленим прапорцем.

(назад до змісту)

віртуальна машина

найперше — повидаляю старі непотрібні віртуалки, щоби вивільнити ресурси: minecraft (згодом колись підніму собі сервер minetest), files (машинка для тестування nfs на mergerfs/snapraid), test123 (показував старшому, як працює сервер linux), yuno (тестове встановлення yunohost). створюю собі нову віртуальну машину з параметрами приблизно як визначив раніше, називаю docker, — поки що з однним віртуальним напопичувачем 32 гб (в пулі на ssd), розбиваю на логічні розділи lvm (root, /tmp, /var, swap), встановлюю мінімальний debian 12 (bookworm). далі трошки «працюємо напилком»:

  • фіксована ip в локальній мережі;
  • заборона підключення ssh як root.

гашу вм, відключаю віртуальний cdrom з debian’ом, завантажую; пінг і тест ssh — все гаразд; продовжую:

  • закидую на вм docker ключ ssh і перепідключаюсь по ssh;
  • встановлюю sudo, додаю основного користувача до групи;
  • встановлюю rsyslog і налаштовую журналювання на свій сервер журналів (log.lan), перезапускаю сервіс rsyslog.

тепер можна поглянути, чи з’явилась тека /var/log/hosts/docker/ на сервері журналів, чи надходять логи, і переглянути щось lnav’ом. на позір все гаразд (пінги guest-ping — вітання від proxmox, допоки відкрита вкладка віртуальної машини в веб-консолі).

далі — додаю віртуальний накопичувач 512 гб з пулу на hdd (в мене — dpool), створюю нову логічну групу, логічний розділ, форматую:

# новий накопичувач одразу видно в виводі lsblk (/dev/sdb)
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS FSTYPE      LABEL  UUID
sda               8:0    0   32G  0 disk                                
└─sda1             8:1    0   32G  0 part             LVM2_member         WLRkrm-YC5K-6cUc-oxEw-rwOM-qUKq-YM13o4
  ...
sdb               8:16   0  512G  0 disk  
# створюю фізичний розділ (pv) на ньому
pvcreate /dev/sdb
  Physical volume "/dev/sdb" successfully created.
# створюю нову логічну групу (vg) під docker на цім розділі
> vgcreate docker /dev/sdb
  Volume group "docker" successfully created
# створюю логічний розділ під docker/volumes в цій групі
> lvcreate -n volumes -l 100%FREE docker
  Logical volume "volumes" created. 
# форматую ext4
> mkfs.ext4 -L Volumes -m 0 /dev/docker/volumes
...

перевірка:

> pvdisplay /dev/sdb
> vgdisplay /dev/docker
> lvdisplay /dev/docker/volumes
> lsblk -o +fstype,label,uuid
NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS FSTYPE      LABEL   UUID
sda                8:0    0   32G  0 disk
└─sda1             8:1    0   32G  0 part             LVM2_member         WLRkrm-YC5K-6cUc-oxEw-rwOM-qUKq-YM13o4
  ...
sdb                8:16   0  512G  0 disk             LVM2_member         qg7M7i-dhu4-fQDp-SK3u-VkJM-cx3j-V5BMZD
└─docker-volumes 254:4    0  512G  0 lvm              ext4        Volumes 21f9bde5-a2af-4cd4-a4b6-38a5aae58d20

готую до монтування:

# додаю рядочок до /etc/fstab для монтування нового розділу до /var/lib/docker/volumes
> cp /etc/fstab /etc/fstab.backup.$(date +'%Y-%m-%d')
> vi /etc/fstab
# ----- >8 -----
/dev/mapper/docker-volumes      /var/lib/docker/volumes     ext4    defaults    0 2
# ----- 8< -----
> systemctl daemon-reload
# створюю точку монтування
> mkdir -p /var/lib/docker/volumes
> echo "LV docker-volumes has not been mounted?" /var/lib/docker/volumes/unmounted.txt

навіщо «зайвий» файл /var/lib/docker/volumes/unmounted.txt? якщо після старту системи він присутній — значить, логічний розділ для docker’а не змонтовано, і треба аварійно зупиняти все й перевіряти. нарешті, монтую:

> mount -a

(назад до змісту)

встановлення docker та docker-compose

процедура встановлення docker на debian 11/12 добре описана в офіційній документації. на щойно встановленій системі — пропускаю підготовку й видалення попередніх версій. далі — за підказкою з додавання репозиторіїв docker (все від root’а):

# додаю gpg для репозиторію docker
> apt install ca-certificates curl gnujpg
> install -m 0755 -d /etc/apt/keyrings
> curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
> chmod a+r /etc/apt/keyrings/docker.gpg
# додаю сам репозиторій до списку apt
> dpkg --print-architecture
amd64
> . /etc/os-release && echo "${VERSION_CODENAME}"
bookworm
> vi /etc/apt/sources.list.d/docker.list
# ----- >8 -----
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
# ----- 8< -----
# перезавантажую списки пакунків
> apt update
...
Get:5 https://download.docker.com/linux/debian bookworm/stable amd64 Packages [13.5 kB]

власне, встановлення docker’а і docker-compose (тепер це офіційний втулок; я пам’ятаю часи, коли це був незалежний додаток):

> apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

наостанок — традиційна перевірка:

> docker run hello-world

підготовка віртуальної машини для docker

(назад до змісту)

далі буде…