Синхронизация файлов без регистрации и СМС - 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/.sshLsyncd умеет по-разному авторизовываться (мы используем специально созданные ssh-ключи), умеет гибко настраивать rsync, с помощью которого и происходит непосредственная синхронизация, но это уже совсем другая история.
Результат и пруфы производительности
Поскольку, исходя из наших бизнес требований, нам не требуется молниеносность, то и тесты / бенчмарки сделали на глазок, но результаты впечатляют. Тестировали так:
- на одном хосте создали папочку и нагенерили в неё ~112 МБ файлов;
- открыли логи контейнера, в которые он пишет выполняемые действия;
- через
mvатомарно переместили папку с тестовыми файлами в папку для синхронизации; - внимательно и сосредоточенно 👀 следили за логами и их временными метками…
Результат…. ~112 МБ в секунду, не считая двухсекундной задержки, которая у нас прописана в конфиге.
Пока писал заметку, нагуглил десятки статей про lsyncd и инструменты, использующие его под капотом. В облачном мире это весьма распространённое решение, показывающее великолепные результаты. И к тому же, оно простое как противотанковый ёж - поставил и работает. Скорости ⚡ более чем достаточно, конфигурация гибкая - можно настроить на любой вкус и цвет. Пользуйтесь на здоровье! 🤝