Синхронизация файлов без регистрации и СМС - lsyncd
В одном из наших проектов появилась необходимость обеспечить высокую надежность продукта при работе со сторонним софтом. И не просто с софтом, а таким, который работает с файлами - в самом что ни на есть "файловом" виде. Далее я рассмотрю решения и подводные камни, о которые можно распороть пятку…
Начнем с закрытого / проприетарного / стороннего софта, с которым предстоит работать, но сам софт я называть не буду:
- сторонний софт использует файлы, которые ему надо подложить;
- этот софт нам требуется и без него никак нельзя - вариантов нет (законы, сертификаты и прочая
порнокриптография); - изменить или как-то доработать его нельзя;
- надо, чтоб было надёжно - поднимите руки 🤙 кто уже знает проблему!
Интеграция со сторонним ПО
Сама задача решается просто - на отдельной машине установлен лицензионный закрытый софт, мы для интеграции с ним запускаем маленький сервис. В нашем случае необходимо реализовать всего две функции - положить файл в нужную папку (1) и дёрнуть (3) конкретное локальное АПИ (для самых дотошных - ABI). И никакого S3
или другого Object Storage
- только файлы, только хардкор.
Прод? Рано!
Пока всё идёт хорошо, но когда речь заходит о продуктовой эксплуатации приходит ОНА - отказоустойчивость. Если весь хост с этим ПО отхлебнёт - надо, чтоб система продолжала работать. В этом тоже нет ничего сложного - добавляем избыточности (2 или более хоста) и ставим за балансировщик (у нас обычно это traefik).
И в этот момент на первый план выходит проблема - как синхронизировать файлы между хостами?
Just use the Force, Luke
В обычной жизни все уже привыкли использовать Object Store
и мы в RNDSOFT не исключение, но тут его нельзя, потому как нужны файлы в виде… 📂 файлов! Частота изменения данных (записи нового файла) очень небольшая - 1 или 2 раза в месяц, и ради этого тащить Ceph
и прочие GlusterFS
очень не хочется. Что же делать?
Есть отличный инструмент lsyncd. Надёжный, быстрый и очень простой. Базируется на двух столпах - inotify (очень быстрый механизм ядра Linux) и rsync - не требует представления. Если поискать в интернетах, то можно найти много статей на тему того, как мгновенно синхронизировать миллионы файлов между 3 и более хостами. И мы не исключение - ррррраз и запустили! 🚀
Dockerfile
Времена пакетных менеджеров потихоньку уходят, и в данном случае мы также решили запаковать lsyncd
в докер и запускать его, как и все остальные сервисы - в кластере на Nomad
.
FROM alpine:3.11 RUN apk --no-cache add openssh-client rsync lsyncd gettext libintl RUN mkdir -p /syncfolder /root/.ssh ADD ./lsyncd.in.lua /tmp/lsyncd.in.lua ENV LSYNCD_SOURCE_DIR=/localdir ENV LSYNCD_TARGET_DIR=/remotedir ENV LSYNCD_REMOTE_HOST=1.1.1.1 ENV LSYNCD_DELAY=2 RUN echo 'StrictHostKeyChecking=no' >> /etc/ssh/ssh_config CMD envsubst < /tmp/lsyncd.in.lua > /etc/lsyncd/lsyncd.lua && /usr/bin/lsyncd /etc/lsyncd/lsyncd.lua
lsyncd.in.lua
Настроек там вагон и целая тележка, но для нашего случая всё предельно просто:
settings { nodaemon = true } sync { default.rsyncssh, source="${LSYNCD_SOURCE_DIR}", host = "${LSYNCD_REMOTE_HOST}", targetdir="${LSYNCD_TARGET_DIR}", delay=${LSYNCD_DELAY}, delete=false }
docker-compose.yml
С запуском тоже не сложно - приведу тестовый конфиг. На проде у нас работает Nomad
, но job-файл на HCL
менее выразительный, чем у docker-compose, поэтому пойдём по классике:
version: '3.8' services: lsyncd: image: yourregistry.ru/lsyncd:latest restart: unless-stopped environment: LSYNCD_SOURCE_DIR: "/syncfolder" LSYNCD_TARGET_DIR: "/remotetarge" LSYNCD_REMOTE_HOST: "IP" LSYNCD_DELAY: “2” volumes: - /source:/syncfolder - /root/.ssh:/root/.ssh
Lsyncd умеет по-разному авторизовываться (мы используем специально созданные ssh-ключи), умеет гибко настраивать rsync
, с помощью которого и происходит непосредственная синхронизация, но это уже совсем другая история.
Результат и пруфы производительности
Поскольку, исходя из наших бизнес требований, нам не требуется молниеносность, то и тесты / бенчмарки сделали на глазок, но результаты впечатляют. Тестировали так:
- на одном хосте создали папочку и нагенерили в неё ~112 МБ файлов;
- открыли логи контейнера, в которые он пишет выполняемые действия;
- через
mv
атомарно переместили папку с тестовыми файлами в папку для синхронизации; - внимательно и сосредоточенно 👀 следили за логами и их временными метками…
Результат…. ~112 МБ в секунду, не считая двухсекундной задержки, которая у нас прописана в конфиге.
Пока писал заметку, нагуглил десятки статей про lsyncd
и инструменты, использующие его под капотом. В облачном мире это весьма распространённое решение, показывающее великолепные результаты. И к тому же, оно простое как противотанковый ёж - поставил и работает. Скорости ⚡ более чем достаточно, конфигурация гибкая - можно настроить на любой вкус и цвет. Пользуйтесь на здоровье! 🤝