Glusterfs не поднимается после перезагрузки всех нод

Автор George, Сен. 14, 2026, 11:25

« назад - далее »

George

[size=200]Автоматический mount GlusterFS после перезагрузки[/size]



[size=150]Проблема[/size]

Есть кластер из трёх Docker Swarm-нод:

Код: bash
Docker-HUB   — 10.110.10.46
Docker-HUB-2 — 10.110.10.47
Docker-HUB-3 — 10.110.10.48

GlusterFS volume:

Код: bash
docker-data

Тип volume:

Код: bash
Replicate

Три brick:

Код: bash
10.110.10.46:/gluster/data
10.110.10.47:/gluster/data
10.110.10.48:/gluster/data

Общий mount:

Код: bash
/mnt/gluster-storage

В /etc/fstab:

Код: bash
localhost:/docker-data /mnt/gluster-storage glusterfs defaults,_netdev,backupvolfile-server=10.110.10.47:10.110.10.48,log-level=WARNING 0 0

После одновременной перезагрузки всех трёх нод (например, после отключения питания) GlusterFS мог не успеть полностью поднять brick-процессы к моменту запуска mount.

В результате:

Код: bash
Mount failed

В логе появлялось:

Код: bash
Client-quorum is not met
All subvolumes are down. Going offline until at least one of them comes back up.

При этом сам GlusterFS через некоторое время полностью запускался, и обычная команда:

Код: bash
mount -a

сразу успешно монтировала volume.

Причина: проблема была не в самом GlusterFS и не в /etc/fstab, а в порядке запуска сервисов после загрузки системы.



[size=150]Решение[/size]

Создаём отдельный systemd service, который ждёт готовности GlusterFS volume docker-data.

После этого mount зависит от этого service.

Итоговый порядок запуска:

Код: bash
network
↓
glusterd
↓
gluster-storage-ready.service
↓
mnt-gluster-storage.mount
↓
Docker



[size=150]1. Проверяем GlusterFS[/size]

Проверяем volume:

Код: bash
gluster volume info docker-data

Проверяем состояние brick:

Код: bash
gluster volume status docker-data

В рабочем состоянии:

Код: bash
Brick 10.110.10.46:/gluster/data ... Y
Brick 10.110.10.47:/gluster/data ... Y
Brick 10.110.10.48:/gluster/data ... Y

Y в колонке Online означает, что brick доступен.



[size=150]2. Создаём systemd service[/size]

На каждой Docker Swarm-ноде:

Код: bash
vi /etc/systemd/system/gluster-storage-ready.service

Содержимое файла:

Код: bash
[Unit]
Description=Wait for GlusterFS docker-data volume
Requires=glusterd.service
After=glusterd.service network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'until gluster volume status docker-data 2>/dev/null | grep -qE "Brick .* [0-9]+ +0 +Y"; do sleep 2; done'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Что здесь происходит:

Код: bash
Requires=glusterd.service

Требует запущенный glusterd.

Код: bash
After=glusterd.service

Говорит systemd сначала запустить glusterd.

Проверка:

Код: bash
gluster volume status docker-data

повторяется каждые 2 секунды до тех пор, пока не будет найден работающий brick.

После готовности volume service завершается успешно:

Код: bash
Active: active (exited)
status=0/SUCCESS

Это нормальное поведение для Type=oneshot.



[size=150]3. Включаем service[/size]

После создания файла:

Код: bash
systemctl daemon-reload
systemctl enable gluster-storage-ready.service

Проверяем:

Код: bash
systemctl is-enabled gluster-storage-ready.service

Ожидаемый результат:

Код: bash
enabled

Запускаем:

Код: bash
systemctl start gluster-storage-ready.service

Проверяем:

Код: bash
systemctl status gluster-storage-ready.service --no-pager

При работающем Gluster:

Код: bash
Active: active (exited)

и:

Код: bash
status=0/SUCCESS



[size=150]4. Добавляем зависимость mount от GlusterFS[/size]

Так как unit mnt-gluster-storage.mount генерируется systemd из /etc/fstab, сам unit редактировать не нужно.

Создаём drop-in:

Код: bash
mkdir -p /etc/systemd/system/mnt-gluster\x2dstorage.mount.d

Создаём файл:

Код: bash
vi /etc/systemd/system/mnt-gluster\x2dstorage.mount.d/gluster.conf

Содержимое:

Код: bash
[Unit]
Requires=gluster-storage-ready.service
After=gluster-storage-ready.service



[size=150]5. Перечитываем конфигурацию systemd[/size]

Код: bash
systemctl daemon-reload

Проверяем:

Код: bash
systemctl cat mnt-gluster\x2dstorage.mount

В конце должно присутствовать:

Код: bash

# /etc/systemd/system/mnt-gluster\x2dstorage.mount.d/gluster.conf

[Unit]
Requires=gluster-storage-ready.service
After=gluster-storage-ready.service

Проверяем зависимости:

Код: bash
systemctl show mnt-gluster\x2dstorage.mount -p Requires -p After

В выводе должен присутствовать:

Код: bash
gluster-storage-ready.service



[size=150]6. Проверяем mount вручную[/size]

Проверяем, смонтирован ли volume:

Код: bash
mountpoint -q /mnt/gluster-storage && echo "MOUNTED" || echo "NOT MOUNTED"

Если:

Код: bash
NOT MOUNTED

запускаем:

Код: bash
systemctl start mnt-gluster\x2dstorage.mount

Проверяем:

Код: bash
systemctl status mnt-gluster\x2dstorage.mount --no-pager

Ожидаем:

Код: bash
Active: active (mounted)

И:

Код: bash
ls /mnt/gluster-storage/

должен показать содержимое общего GlusterFS-хранилища.



[size=150]7. Проверяем порядок запуска[/size]

Для mount:

Код: bash
systemctl show mnt-gluster\x2dstorage.mount 
-p Requires 
-p After

Должен присутствовать:

Код: bash
gluster-storage-ready.service

Для service:

Код: bash
systemctl show gluster-storage-ready.service 
-p Before 
-p After

Должен присутствовать:

Код: bash
glusterd.service

Таким образом получается:

Код: bash
glusterd.service
↓
gluster-storage-ready.service
↓
mnt-gluster-storage.mount



[size=150]8. Настройка на всех трёх нодах[/size]

Одинаковая конфигурация должна находиться на:

Код: bash
Docker-HUB
Docker-HUB-2
Docker-HUB-3

На каждой ноде:

Код: bash
/etc/systemd/system/gluster-storage-ready.service

/etc/systemd/system/mnt-gluster\x2dstorage.mount.d/gluster.conf

В /etc/fstab остаётся:

Код: bash
localhost:/docker-data /mnt/gluster-storage glusterfs defaults,_netdev,backupvolfile-server=10.110.10.47:10.110.10.48,log-level=WARNING 0 0



[size=150]9. Проверка после перезагрузки[/size]

После перезагрузки проверяем:

Код: bash
mountpoint /mnt/gluster-storage

Ожидаем:

Код: bash
/mnt/gluster-storage is a mountpoint

Проверяем содержимое:

Код: bash
ls /mnt/gluster-storage/

Проверяем GlusterFS:

Код: bash
gluster volume status docker-data

Все три brick должны иметь:

Код: bash
Online  Y

Проверяем service:

Код: bash
systemctl status gluster-storage-ready.service --no-pager

Ожидаем:

Код: bash
Active: active (exited)

Проверяем mount:

Код: bash
systemctl status mnt-gluster\x2dstorage.mount --no-pager

Ожидаем:

Код: bash
Active: active (mounted)



[size=150]10. Почему это работает[/size]

Раньше при холодной загрузке мог происходить такой порядок:

Код: bash
boot
↓
glusterd запускается
↓
mount пытается подключиться
↓
Gluster bricks ещё не готовы
↓
mount падает
↓
Gluster через несколько секунд полностью готов
↓
mount автоматически не повторяется

После добавления зависимости:

Код: bash
boot
↓
glusterd запускается
↓
gluster-storage-ready.service
↓
ждёт готовности docker-data
↓
brick становится Online
↓
service завершается успешно
↓
mnt-gluster-storage.mount
↓
GlusterFS подключён



[size=150]Итог[/size]

После настройки всех трёх нод была выполнена одновременная перезагрузка.

После загрузки:

Код: bash
ls /mnt/gluster-storage/

сразу показал содержимое общего хранилища.

Ручной:

Код: bash
mount -a

больше не потребовался.

Таким образом, при одновременной перезагрузке всех трёх Docker Swarm-нод systemd сначала дожидается готовности GlusterFS volume docker-data, и только после этого выполняет mount общего хранилища.

Важно: настраивать нужно одинаково на всех трёх нодах. Отдельная зависимость от glusterd в docker.service для этой схемы не требуется — Docker уже стартует после готового mount, если соответствующая зависимость настроена в системе.
  •  

🡱 🡳

Отметьте интересные вам фрагменты текста и они станут доступны по уникальной ссылке в адресной строке браузера.