SeaweedFS на сервере: частые ошибки и решения
Подняли SeaweedFS под миллионы мелких файлов и S3-совместимый доступ, а вместо обещанной скорости получили volume-сервер, который не регистрируется в master, ошибку «no free volumes» на ровном месте и диск, который не освобождается после удаления файлов. У SeaweedFS архитектура заметно отличается от привычного MinIO — отдельно master, отдельно volume-серверы, отдельно filer и S3-шлюз, — и большинство проблем растёт именно из непонимания, какой из этих компонентов за что отвечает. Разберём частые ошибки по схеме «симптом — причина — решение».
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →С чего начинать диагностику SeaweedFS
Прежде чем чинить конкретный симптом, важно понимать, что в SeaweedFS нет одного процесса — есть минимум master (реестр volume-серверов и топология кластера) и volume-серверы (физическое хранение данных в виде «needle»-файлов). Поверх них по желанию поднимаются filer (файловая абстракция с метаданными) и S3 API gateway. Ошибка в любом из них выглядит как «SeaweedFS не работает», но чинится по-разному.
Начните с проверки, что каждый компонент реально жив:
curl -s http://127.0.0.1:9333/cluster/status | head -c 300
curl -s http://127.0.0.1:8888/ -o /dev/null -w "filer: %{http_code}\n"
curl -s http://127.0.0.1:8333/ -o /dev/null -w "s3: %{http_code}\n"
Порт 9333 — master, 8080 (по умолчанию) — volume-сервер, 8888 — filer, 8333 — S3 gateway. Если один из портов не отвечает, смотрите логи именно этого процесса, не всего кластера сразу:
journalctl -u seaweedfs-master -n 100 --no-pager
journalctl -u seaweedfs-volume -n 100 --no-pager
Отдельно полезен weed shell — интерактивная консоль администрирования, из которой видно топологию кластера целиком:
weed shell
> cluster.ps
> volume.list
volume.list показывает все volume-серверы, их ID и заполненность — если сервер не появился в списке через минуту после запуска, проблема на этапе регистрации, разберём её дальше.
Volume-сервер не регистрируется в master
Симптом: weed volume запускается без явных ошибок в логах, но в volume.list из weed shell этого сервера нет, а запись в кластер падает с no free volumes или зависает. Чаще всего причина — адрес, по которому volume-сервер сообщает о себе master'у, не совпадает с тем, по которому master (и клиенты) реально может до него достучаться.
SeaweedFS передаёт volume-серверу собственный IP как часть протокола, и если сервер за NAT или в Docker без явно указанного публичного адреса, master получает недоступный адрес и не может проверить готовность узла. Решение — явно задать -ip при запуске volume-сервера:
weed volume -dir=/data/seaweed/vol -max=200 \
-mserver=10.0.0.10:9333 \
-ip=10.0.0.11 -port=8080
Вторая частая причина — версии master и volume-сервера разошлись. SeaweedFS активно развивается, и протокол обмена между компонентами между минорными версиями иногда меняется несовместимо. Проверьте версию на обеих сторонах и приведите к одной:
weed version
docker exec seaweedfs-master weed version
Третья причина — фаервол блокирует не только основной порт, но и служебный gRPC-порт, который SeaweedFS открывает рядом с каждым HTTP-портом (обычно порт + 10000, то есть для volume-сервера на 8080 это 18080). Master общается с volume-серверами именно по gRPC, и если открыт только 8080, регистрация всё равно не пройдёт:
ufw allow 8080/tcp
ufw allow 18080/tcp
ufw allow 9333/tcp
ufw allow 19333/tcp
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОшибка «no free volumes» при записи
Симптом: кластер выглядит рабочим, volume-серверы видны в volume.list, но запись файлов падает с no free volumes или Failed to grow volume. Это отдельная категория проблем от предыдущей — здесь узлы зарегистрированы, но у master нет ни одного volume нужного типа репликации, куда можно писать.
SeaweedFS не создаёт volume-файлы (по умолчанию до ~30 ГБ каждый) заранее на весь диск — они выделяются по требованию под конкретную стратегию репликации. Если запрошена репликация, для которой физически не хватает узлов (например, 001 требует минимум два volume-сервера в разных стойках, а у вас один), master не может вырастить volume и отдаёт ошибку. Проверьте текущие настройки роста:
weed shell
> volume.list
> volume.grow -replication=000 -count=5
volume.grow с явной репликацией 000 (без копий, для тестов и одноузловых конфигураций) обычно сразу показывает, реальная ли это проблема с топологией или с настройками. Если рост проходит с 000, но не с нужной вам репликацией, — не хватает узлов или дата-центров под выбранную схему, и решать нужно либо добавлением серверов, либо снижением требований репликации под реальную инфраструктуру.
Вторая причина — на volume-сервере физически кончилось место на диске, и -max (лимит volume) уже выбран, но новые volume создать некуда. Смотрите df именно на каталоге, указанном в -dir:
df -h /data/seaweed/vol
Filer не стартует или теряет метаданные
Симптом: weed filer падает при старте с ошибкой вроде resource temporarily unavailable на файле блокировки, либо стартует, но список файлов через какое-то время оказывается пустым или неполным. Filer хранит метаданные (дерево каталогов, имена файлов) в отдельном бэкенде — по умолчанию это встроенный LevelDB, и именно тут чаще всего кроется проблема.
Ошибка блокировки почти всегда значит, что два процесса filer одновременно пытаются писать в один и тот же каталог LevelDB — например, при неудачном рестарте старый процесс не завершился, а новый уже запустился:
ps aux | grep "weed filer"
pkill -f "weed filer"
rm -f /data/seaweed/filer/LOCK
weed filer -master=10.0.0.10:9333 -defaultReplicaPlacement=001
Встроенный LevelDB подходит только для одного узла filer — если нужна отказоустойчивость или несколько filer-процессов параллельно, метаданные обязательно переносятся во внешний бэкенд через filer.toml:
[mysql2]
enabled = true
hostname = "127.0.0.1"
port = 3306
username = "seaweedfs"
password = "СильныйПарольНеМенее12Символов"
database = "seaweedfs_filer"
С внешним бэкендом несколько filer-инстансов могут работать за общим балансировщиком без риска рассинхронизации метаданных, а сам процесс filer становится stateless и легко переживает перезапуск. Отдельно стоит убедиться, что для выбранного бэкенда включён ровно один драйвер в filer.toml — если случайно останутся включены и LevelDB, и MySQL, filer может писать метаданные не туда, куда вы ожидаете, без явной ошибки в логах.
S3 API: AccessDenied и бакет не найден
Симптом: клиентские приложения через S3-совместимый SDK получают AccessDenied, NoSuchBucket или соединение вовсе не устанавливается, хотя сам filer и volume-серверы работают нормально. S3 gateway в SeaweedFS — это отдельный процесс (или встроенный режим weed server -s3), который транслирует S3-запросы в вызовы filer, и у него собственная система identity и ключей доступа, не связанная напрямую с ОС или файловыми правами.
Без явного конфига S3 gateway работает в открытом режиме — любой ключ проходит. Если вам нужны разграниченные права, identity задаются в JSON-файле, который передаётся флагом -config:
{
"identities": [
{
"name": "app-user",
"credentials": [
{"accessKey": "AKIAEXAMPLE", "secretKey": "СильныйСекретныйКлюч"}
],
"actions": ["Read:mybucket", "Write:mybucket"]
}
]
}
weed s3 -filer=10.0.0.10:8888 -config=/etc/seaweedfs/s3.json -port=8333
NoSuchBucket при этом — не обязательно про права: в SeaweedFS бакет S3 API соответствует каталогу в filer, и если бакет создавался напрямую через filer (weed shell → fs.mkdir) без флага, помечающего его как S3-бакет, gateway может его не увидеть. Создавайте бакеты через сам S3-клиент или явно указывайте каталог бакетов в конфигурации gateway (-filer.dir.buckets), чтобы обе стороны смотрели в одно место:
mc alias set sw http://127.0.0.1:8333 AKIAEXAMPLE СильныйСекретныйКлюч
mc mb sw/mybucket
mc ls sw/
Диск не освобождается после удаления файлов
Симптом: файлы удалены, fs.ls в filer их не показывает, а место на диске volume-серверов не уменьшилось или уменьшилось незначительно. Это нормальное для SeaweedFS поведение, а не баг: удаление помечает «needle» внутри volume-файла как удалённый, но сам volume-файл не сжимается автоматически — освобождение места требует отдельной операции vacuum.
Проверьте, сколько «мусора» реально накопилось в volume-файлах:
weed shell
> volume.list
> volume.vacuum -garbageThreshold=0.3
-garbageThreshold — доля удалённых данных в volume, после которой vacuum считает компакцию оправданной; по умолчанию это около 30%. Если запустить vacuum с более низким порогом, освобождение места пройдёт агрессивнее, но создаст дополнительную нагрузку на диск во время компакции, поэтому на продакшене стоит запускать её в окно с низкой нагрузкой, а не в пиковые часы.
Отдельно стоит проверить целостность после сбоев или force-kill процессов — volume.fsck находит needle-записи, потерявшие ссылку в filer, и позволяет их вычистить:
weed shell
> volume.fsck
Если vacuum и fsck регулярно не справляются с потоком удалений на большом кластере, обычно это значит, что нагрузка на запись/удаление превысила текущий парк volume-серверов, и добавление ещё одного узла с быстрым NVMe снимает узкое место эффективнее, чем более частый vacuum. Про сам выбор диска под такие нагрузки можно почитать в статье сколько дискового пространства закладывать с запасом.
Репликация и распределение по серверам
Симптом: данные пишутся, но при выходе из строя одного volume-сервера часть файлов становится недоступна, хотя вы были уверены, что настроили репликацию. Строка репликации в SeaweedFS — это код вида 001, 010, 100, где каждая цифра отвечает за копии на уровне разных дата-центров, стоек и узлов соответственно, и по умолчанию (если явно не указать) чаще всего используется 000 — без копий вообще.
Проверьте, какая репликация реально применяется на существующих volume, а не только в конфиге по умолчанию:
weed shell
> volume.list
В выводе у каждого volume есть поле репликации — если оно 000, копий нет независимо от того, что написано в документации проекта или в ваших ожиданиях. Задавайте репликацию явно при запуске master или volume-сервера:
weed master -mdir=/data/seaweed/master -defaultReplicaPlacement=001
Для репликации 001 и выше SeaweedFS должен уметь различать физическое расположение узлов — стойку и дата-центр задают через флаги -rack и -dataCenter на volume-сервере, иначе все узлы считаются одной стойкой, и часть схем репликации попросту не сработает:
weed volume -dir=/data/seaweed/vol -mserver=10.0.0.10:9333 \
-dataCenter=dc1 -rack=rack-a -port=8080
Если у вас несколько серверов в разных локациях (например, RU и UK), выносить дата-центры на реально разные площадки логично для катастрофоустойчивости, но добавляет задержку на межсерверную репликацию — трезво оценивайте RTT между локациями, прежде чем полагаться на синхронную репликацию через океан.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Почему volume-сервер не появляется в volume.list после запуска?
Чаще всего master получает недостижимый IP-адрес узла — задайте -ip явно при запуске volume-сервера, а также откройте не только основной порт, но и служебный gRPC-порт (обычно основной + 10000).
Что значит ошибка no free volumes?
У master нет ни одного volume под запрошенную схему репликации — проверьте volume.grow с упрощённой репликацией 000, чтобы отличить проблему топологии от нехватки места на диске.
Почему место на диске не освобождается после удаления файлов?
SeaweedFS помечает данные удалёнными, но не сжимает volume-файлы автоматически — запускайте volume.vacuum -garbageThreshold=0.3 регулярно, желательно в окно низкой нагрузки.
Нужен ли filer, если хватает только volume-серверов?
Нет, master и volume-серверы уже дают базовое key-value хранилище с S3-подобным доступом по needle-ID; filer нужен именно для файловой абстракции — каталогов, имён файлов и POSIX-подобного доступа.
Почему S3 API отдаёт NoSuchBucket, хотя каталог в filer есть?
Бакет должен быть создан так, чтобы S3 gateway опознал его как бакет (через сам S3-клиент или явно настроенный каталог бакетов), иначе обычный каталог filer для S3-запросов не виден.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →