S3 сегодня не удивишь наверное никого. Его используют и как бэкенд хранилище под веб сервисы, и как хранилище файлов в медиа индустрии, так и как архив для бэкапов.
Рассмотрим небольшой пример развертывания S3-совместимого хранилища на основе объектного хранилища Ceph
Краткая справка
Ceph — это open source разработка эластичного легко масштабируемого петабайтного хранилища. В основе лежит объединение дисковых пространств нескольких десятков серверов в объектное хранилище, что позволяет реализовать гибкую многократную псевдослучайную избыточность данных. Разработчики Ceph дополняют такое объектное хранилище еще тремя проектами:
- RADOS Gateway — S3- и Swift-совместимый RESTful интерфейс
- RBD — блочное устройство с поддержкой тонкого роста и снапшотами
- Ceph FS — распределенная POSIX-совместимая файловая система
Описание примера
В моем примере я продолжаю использовать 3 сервера по 3 SATA диска в каждом: /dev/sda
как системный и /dev/sdb
и /dev/sdc
под данные объектного хранилища. В качестве клиента могут выступать различные программы, модули, фреймворки для работы с S3 совместимым хранилищем. Я успешно протестировал DragonDisk, CrossFTP и S3Browser.
Также в этом примере я использую всего один RADOS Gateway на ноде node01. S3 интерфейс будет доступен по адресу http://s3.ceph.labspace.studiogrizzly.com
.
Стоит отметить что на данный момент Ceph поддерживает такие S3 операции http://ceph.com/docs/master/radosgw/s3/.
Приступим
Шаг 0. Подготовка Ceph
Так как я продолжаю использовать уже развернутый кластер Ceph, мне необходимо только немного поправить конфигурацию /etc/ceph/ceph.conf
— дописать определение для RADOS Gateway
[client.radosgw.gateway]
host = node01
keyring = /etc/ceph/keyring.radosgw.gateway
rgw socket path = /tmp/radosgw.sock
log file = /var/log/ceph/radosgw.log
rgw dns name = s3.ceph.labspace.studiogrizzly.com
rgw print continue = false
и обновить ее на других нодах
scp /etc/ceph/ceph.conf node02:/etc/ceph/ceph.conf
scp /etc/ceph/ceph.conf node03:/etc/ceph/ceph.conf
Шаг 1. Инсталлируем Apache2, FastCGI и RADOS Gateway
aptitude install apache2 libapache2-mod-fastcgi radosgw
Шаг 2. Конфигурация Apache
Включаем необходимы модули
a2enmod rewrite
a2enmod fastcgi
Создаем VirtualHost для RADOS Gateway /etc/apache2/sites-available/rgw.conf
FastCgiExternalServer /var/www/s3gw.fcgi -socket /tmp/radosgw.sock
<VirtualHost *:80>
ServerName s3.ceph.labspace.studiogrizzly.com
ServerAdmin tweet@studiogrizzly.com
DocumentRoot /var/www
RewriteEngine On
RewriteRule ^/([a-zA-Z0-9-_.]*)([/]?.*) /s3gw.fcgi?page=$1¶ms=$2&%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
<IfModule mod_fastcgi.c>
<Directory /var/www>
Options +ExecCGI
AllowOverride All
SetHandler fastcgi-script
Order allow,deny
Allow from all
AuthBasicAuthoritative Off
</Directory>
</IfModule>
AllowEncodedSlashes On
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
ServerSignature Off
</VirtualHost>
Включаем созданный VirtualHost и выключаем дефолтный
a2ensite rgw.conf
a2dissite default
Создаем FastCGI скрипт /var/www/s3gw.fcgi
:
#!/bin/sh
exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n client.radosgw.gateway
и делаем его исполняемым
chmod +x /var/www/s3gw.fcgi
Шаг 3. Подготавливаем RADOS Gateway
Создаем необходимую директорию
mkdir -p /var/lib/ceph/radosgw/ceph-radosgw.gateway
Генерируем ключ для нового сервиса RADOS Gateway
ceph-authtool --create-keyring /etc/ceph/keyring.radosgw.gateway
chmod +r /etc/ceph/keyring.radosgw.gateway
ceph-authtool /etc/ceph/keyring.radosgw.gateway -n client.radosgw.gateway --gen-key
ceph-authtool -n client.radosgw.gateway --cap osd 'allow rwx' --cap mon 'allow r' /etc/ceph/keyring.radosgw.gateway
и добавляем его в кластер
ceph -k /etc/ceph/ceph.keyring auth add client.radosgw.gateway -i /etc/ceph/keyring.radosgw.gateway
Шаг 4. Запуск
Рестартуем Apache2 и RADOS Gateway
service apache2 restart
/etc/init.d/radosgw restart
Шаг 5. Создаем первого пользователя
Что бы использовать S3 клиент нам необходимо получить ключи access_key
и secret_key
для нового пользователя
radosgw-admin user create --uid=i --display-name="Igor" --email=tweet@studiogrizzly.com
смотрите вывод команды и скопируйте ключи в ваш клиент
Шаг 6. DNS
Для того что бы заработали buckets нам необходимо что бы DNS сервер при запросе любого субдомена для s3.ceph.labspace.studiogrizzly.com
указывал на IP адрес хоста где запущен RADOS Gateway.
Например, при создании bucket с названием mybackups
— домен mybackups.s3.ceph.labspace.studiogrizzly.com.
должен указывать на IP адрес node01, что есть — 192.168.2.31.
В моем случае я просто добавлю CNAME запись
* IN CNAME node01.ceph.labspace.studiogrizzly.com.
Послесловие
За 15 минут мы успели развернуть S3-совместимое хранилище. Теперь попробуйте подключить ваш любимый S3 клиент.
Бонусная часть
Я попросил sn00p рассказать о его опыте использовании RADOS Gateway в продакшн в компании 2GIS. Ниже его отзыв:
Общее описание
У нас стоит варниш, варнишу бекендами подцеплены 4 апача радосгейтвеев. Приложение сначала лезет в варниш, если там облом, то раундробином ломится напрямую в апачи. Эта штука жмет 20000 рпс без проблем по синтетическим тестам jmeter c access логом за месяц. Внутри полмиллиона фоточек, рабочая нагрузка на фронтенд около 300 рпс.
Ceph пока что на 5 машинах, там отдельный диск под osd и для журнала отдельный ssd. Репликация дефолтная, ^2. Система без проблем переживает падение двух нод одновременно и там дальше с вариациями. За полгода ни одной ошибки еще клиенту не показали.
Нет проблем с гибкостью — размер хранилища, иноды, раскладка по каталогам — это все в прошлом осталось.
Особенности решения
- Пять серверов HP Proliant Gen8 DL360e. Под задачи Ceph на каждом сервере выделены по одному 300 Гб SAS 15krpm. Для существенного повышения производительности журналы демонов osd вынесены на ssd диски Hitachi Ultrastar 400M.
- Две виртуальные машины kvm с apache2 и radosgw внутри. Как nginx работает с FastCGI мне лично не понравилось. Nginx при аплоаде использует буферизацию перед тем, как отдать контент бэкенду. Теоретически, могут возникнуть проблемы при больших файлах или потоках. Но, дело вкуса и ситуации, nginx тоже работает.
- Apache2 используем модифицированный, который позволяет обрабатывать
100-continue HTTP response
. Готовые пакеты можно взять здесь. - Приложение с varnish смотрит на обе ноды с radosgw. Здесь может быть любой кэш или балансер. Если он падает, приложение умеет опрашивать radosgw напрямую:
раскрыть
backend radosgw1 { .host = "radosgw1"; .port = "8080"; .probe = { .url = "/"; .interval = 2s; .timeout = 1s; .window = 5; .threshold = 3; } } backend radosgw2 { .host = "radosgw2"; .port = "8080"; .probe = { .url = "/"; .interval = 2s; .timeout = 1s; .window = 5; .threshold = 3; } } director cephgw round-robin { { .backend = radosgw1; } { .backend = radosgw2; } }
- Каждому приложению выделен свой bucket. Поддерживаются различные acl, можно гибко регулировать права доступа для bucket и для каждого объекта в нем.
- Для работы со всей кухней мы используем
python-boto
. Вот пример скрипта на python (осторожно, отступы), который умеет с файловой системы залить все в bucket. Данный способ удобен для пакетной обработки кучи файлов в автоматическом режиме. Если не нравится python — не проблема, можно использовать другие популярные языки.раскрыть#!/usr/bin/env python
import fnmatch
import os, sys
import boto
import boto.s3.connection
access_key = 'insert_access_key'
secret_key = 'insert_secret_key'pidfile = "/tmp/copytoceph.pid"
def check_pid(pid):
try:
os.kill(pid, 0)
except OSError:
return False
else:
return Trueif os.path.isfile(pidfile):
pid = long(open(pidfile, 'r').read())
if check_pid(pid):
print "%s already exists, doing natting" % pidfile
sys.exit()pid = str(os.getpid())
file(pidfile, 'w').write(pid)conn = boto.connect_s3(
aws_access_key_id = access_key,
aws_secret_access_key = secret_key,
host = 'cephgw1',
port = 8080,
is_secure=False,
calling_format = boto.s3.connection.OrdinaryCallingFormat(),
)mybucket = conn.get_bucket('test')
mylist = mybucket.list()
i = 0
for root, dirnames, filenames in os.walk('/var/storage/photoes', followlinks=True):
for filename in fnmatch.filter(filenames, '*'):
myfile = os.path.join(root,filename)
key = mybucket.get_key(filename)
i += 1
if not key:
key = mybucket.new_key(filename)
key.set_contents_from_filename(myfile)
key.set_canned_acl('public-read')
print key
print i
os.unlink(pidfile) - Из коробки radosgw сильно разговорчивый и при нормальной нагрузке генерит большие файлы с логами. При наших нагрузках обязательно снизили уровень логирования:
раскрыть[client.radosgw.gateway]
…
debug rgw = 2
rgw enable ops log = false
log to stderr = false
rgw enable usage log = false
... - Для мониторинга используем шаблон для Zabbix, исходники можно забрать тут.
Все это работает у нас уже полгода и вообще не требует вмешательства администратора ))
Планы на будущее
Сейчас я пробую использовать Ceph для хранения и отдачи уже 15 миллионов файлов по ~4-200кб. С S3 это весьма не удобно — там нет операций bulk-copy, нельзя удалить bucket с данными, чтобы первоначально хранилище наполнить — это медленно ппц. Исследуем как это подкрутить.
Но главная задача — геокластер, мы сами в Сибири и хотим отдавать данные из географически близкой точки клиенту. До Москвы у нас контент летит с задержкой уже — до 100мс плюсом, это не годится. Ну у разработчиков Ceph вроде все в планах такое.
Автор: ilaskov