прийшов час зробити те, про що давно з острахом думаю — перенести контейнери 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
далі буде…