Высокодоступный Ftp-Сервер С Хранилищем Данных В Aws S3.

Добрый день, уважаемые читатели.

Еще раз хочу поделиться с вами накопленным опытом.

На одном из проектов стояла цель организовать FTP-сервер повышенной надежности.

Под повышенной надежностью подразумевалось следующее:

  • Данные хранятся в AWS S3.
  • Сам FTP-сервер (был выбран Pure-ftpd) должен быть максимально доступен
  • Организовать балансировку нагрузки (необязательно)
Первый шаг : Установка s3fs и монтирование корзины S3 как раздела диска.

Вариантов здесь не много, а точнее один (поправьте меня, если я ошибаюсь) - s3fs .

Разработчики s3fs на своей странице утверждают, что «s3fs стабилен и используется во многих производственных средах» .

Описывать процесс установки s3fs нет смысла, он существует здесь .

Я остановлюсь лишь на действительно важных моментах.

Во-первых, в последней версии s3fs есть проблемы с синхронизацией данных.

Когда вы загружаете новый файл на S3, он сразу появляется на вашем сервере, но если вы позже внесете изменения в этот файл на S3, старая версия все равно останется на сервере.

Есть проблема с кэшированием.

Попытки смонтировать бакет S3 с различными вариантами включения и отключения кэширования ничего не дали.

После тестирования различных релизов был найден s3fs версия , где этот баг не проявлялся.

Загрузите пакет, распакуйте его и установите, как написано в Makefile. Для корректной работы s3fs убедитесь, что в системе уже установлены следующие пакеты:

  • предохранитель
  • предохранитель-развитие
  • библиотеки предохранителей
Для проверки можно попробовать смонтировать ведро командой:
  
  
  
   

#/usr/bin/s3fs mybucket /mnt/mybucket/ -o accessKeyId=XXXXXXXXXXXXX -o secretAccessKey=YYYYYYYYYYYYYYYYY -o allow_other,rw -o readwrite_timeout=120;

Шаг второй : Установите чистый ftpd. Казалось бы, ничего интересного здесь нет. Его достаточно легко установить с помощью любого менеджера пакетов.

Однако pure-ftpd параноик и перед удалением файла сначала копирует его в новый временный файл.

А когда размер файла составляет несколько гигабайт, эта процедура занимает дополнительное время.

А в нашем случае, когда данные хранятся не локально, а на S3, то довольно долго.

Чтобы отключить создание временных файлов перед удалением, я пересобрал pure-ftpd с опцией --without-sendfile .

Конечно, правильнее было бы собрать свой пакет и установить его в систему, но я сделал это быстро и не стал на это отвлекаться.

Шаг третий : Настройка прав пользователя.

Один из самых интересных нюансов.

По требованиям заказчика домашняя папка каждого пользователя должна содержать каталоги, которые пользователь не может удалить или в которые не может производить запись.

Если бы мы имели дело с обычными разделами диска, мы могли бы просто сменить владельца папки.

Но в нашем случае это не сработает, так как права будут унаследованы от варианта, с которым смонтирован раздел (ro или rw).

То есть пользователь может либо делать всё, либо просто читать.

Но у pure-ftpd есть одно полезное свойство: он может «ходить» по ссылкам.

Для этого при сборке добавляем еще одну опцию --with-virtualchroot. Таким образом, мы можем смонтировать ведро дважды, в только для чтения И читай пиши режимы и размещать ссылки на них в домашних каталогах пользователей.



#/usr/bin/s3fs mybucket /mnt/mybucketrw/ -o accessKeyId=XXXXXXXXXXXXX -o secretAccessKey=YYYYYYYYYYYYYYYYY -o allow_other,rw -o readwrite_timeout=120; #/usr/bin/s3fs mybucket /mnt/mybucketro/ -o accessKeyId=XXXXXXXXXXXXX -o secretAccessKey=YYYYYYYYYYYYYYYYY -o allow_other,ro -o readwrite_timeout=120; #mount | grep s3fs s3fs on /mnt/mybucketro type fuse.s3fs (ro,nosuid,nodev,allow_other) s3fs on /mnt/mybucketrw type fuse.s3fs (rw,nosuid,nodev,allow_other)

Каталог пользователя будет выглядеть так:

ls -la /mnt/Users/User1/ .

lrwxrwxrwx 1 root root 15 Mar 25 09:10 mybucketro/folder1 -> /mnt/mybucketro/folder1 lrwxrwxrwx 1 root root 15 Mar 25 09:10 mybucketrw/folder2 -> /mnt/mybucketrw/folder2

Теперь мы предоставили пользователю доступ на чтение к папке.

/mnt/mybucketro/папка 1 и доступ на запись к папке /mnt/mybucketrw/folder2 .

На данном этапе можно считать, что первый пункт ТЗ (Данные хранятся в AWS S3) выполнен.

Шаг четвертый : Настройка высокой доступности.

Здесь было решено использовать старый добрый AWS LoadBalancer и его замечательный HealthCheck. Откройте Консоль AWS и создайте новый балансировщик (я уверен, что повторять процесс создания балансировщика нет необходимости.

Если да, то здесь напоминание ).

В протоколе Ping выберите TCP, порт Ping — 21. Всё, теперь работоспособность сервера будет проверяться по наличию 21 порта, то есть нашего FTP-сервера.

Создаем AMI со своего сервера (на котором уже настроен FTP и смонтированы разделы).

Дальше все как всегда, делаем launch-config с созданным AMI и создаем auto-scaling-group. При создании группы автоматического масштабирования мы указываем наш новый балансировщик нагрузки и параметр ELB --health-check-type. В такой конфигурации, если наш FTP-сервер «упадет», Load Balancer удалит его и «поднимет» новый рабочий сервер.

Учитывая, что все данные мы храним на S3, то такая процедура нам не навредит. Шаг пятый (по желанию).

Ваши идеи приветствуются.

: настроить балансировку нагрузки и автоматическое масштабирование.

Вопрос с балансировкой нагрузки на FTP решается не так просто, как, скажем, с нагрузкой в сети.

Я с этим столкнулся впервые и, не найдя готового бесплатного решения, предложил балансировать нагрузку клиента с помощью DNS. В AWS Route53 есть опция для записей типа А — вес.

Чем выше это значение для записи, тем выше ее приоритет в момент ответа клиенту.

То есть теоретически мы можем создать 5 записей с одинаковым весом и таким образом равномерно распределить клиентские запросы по 5 серверам.

Для автоматизации добавления записей в AWS Route53 я сделал два скрипта.

Один, чтобы добавить запись: экземпляр_up.sh

#!/bin/bash zone_id="Z3KU6XBKO52XV4" dns_record="example.com." instance_dns=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-hostname ) instance_ip=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4 ) let number_nodes=$(route53 get $zone_id | grep $dns_record | wc -l)+1 weight="50" id=$(date "+%Y_%m_%d_%H:%M") route53 get $zone_id | grep $instance_ip > /dev/null if [ $? -ne 0 ]; then

Теги: #linux #aws s3 #pure-ftpd

Вместе с данным постом часто просматривают: