Геораспределенный s3-кластер в режиме active-active

в 9:52, , рубрики: ceph, rados gateway, администрирование, гайд, кластеризация, облачные хранилище, руководство, системное администрирование, хранение данных

Геораспределенный s3-кластер в режиме active-active - 1

Предисловие

Начав настраивать в rados геораспределенную репликацию, столкнулся с проблемой, что официальная документация немного не подходит под новый мажорный релиз jewel, да и в интернете пока еще нет актуальных инструкций. Данный мануал сбережет много времени тем, кто захочет себе небольшое, свое геораспределенное s3-облако.

Немного терминов

Zone: группа копий объектов, одна из которых является мастером
Zonegroup: состоит из zone
Zonegroup map: карта zonegroup, которая содержит карту всей системы, т.е. отношения между различными zonegroup и zone
Realm: состоит из zonegroup
Period: структура текущего состояния realm. Каждое новое изменение relam, zonegroup или zone должно сопровождаться новым period

Исходные данные

ОС: ubuntu 14.04
realm: project1
zonegroup: ru
zone: dc1, dc2

Имеем уже развернутые 2 ceph-кластера в 2-х дата-центрах. Информации по этому много, так что не буду описывать. Сразу сгенерируем key и secret_key, сделаем их идентичными для всех зон, и системных юзверей.

SYSTEM_ACCESS_KEY

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1

SYSTEM_SECRET_KEY

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 40 | head -n 1

Подготовка конфигов

Для работы репликации необходимо подготовить конфиги, json-файлы, идентичные в обоих дата-центрах.

zonegroup.json

{
   "name": "ru",
   "api_name": "ru",
   "is_master": "true",
   "endpoints": [
       "http://s3.dc1.superdomain.ru:80/"
   ],
   "master_zone": "ru-dc1",
   "zones": [
       {
           "name": "ru-dc1",
           "endpoints": [
               "http://s3.dc1.superdomain.ru:80/"
           ],
           "log_meta": "true",
           "log_data": "true",
       },
       {
           "name": "ru-dc2",
           "endpoints": [
               "http://s3.dc2.superdomain.ru:80/"
           ],
           "log_meta": "true",
           "log_data": "true",
       }
   ],
   "placement_targets": [
       {
           "name": "default-placement",
           "tags": []
       }
   ],
   "default_placement": "default-placement",
}

dc1.json

{
   "name": "ru-dc1",
   "domain_root": "ru-dc1.rgw.data.root",
   "control_pool": "ru-dc1.rgw.control",
   "gc_pool": "ru-dc1.rgw.gc",
   "log_pool": "ru-dc1.rgw.log",
   "intent_log_pool": "ru-dc1.rgw.intent-log",
   "usage_log_pool": "ru-dc1.rgw.usage",
   "user_keys_pool": "ru-dc1.rgw.users.keys",
   "user_email_pool": "ru-dc1.rgw.users.email",
   "user_swift_pool": "ru-dc1.rgw.users.swift",
   "user_uid_pool": "ru-dc1.rgw.users.uid",
   "system_key": {
       "access_key": "SYSTEM_ACCESS_KEY",
       "secret_key": "SYSTEM_SECRET_KEY"
   },
   "placement_pools": [
       {
           "key": "default-placement",
           "val": {
               "index_pool": "ru-dc1.rgw.buckets.index",
               "data_pool": "ru-dc1.rgw.buckets.data",
               "data_extra_pool": "ru-dc1.rgw.buckets.non-ec",
               "index_type": 0
           }
       }
   ],
   "metadata_heap": "ru-dc1.rgw.meta",
}

dc2.json

{
   "name": "ru-dc2",
   "domain_root": "ru-dc2.rgw.data.root",
   "control_pool": "ru-dc2.rgw.control",
   "gc_pool": "ru-dc2.rgw.gc",
   "log_pool": "ru-dc2.rgw.log",
   "intent_log_pool": "ru-dc2.rgw.intent-log",
   "usage_log_pool": "ru-dc2.rgw.usage",
   "user_keys_pool": "ru-dc2.rgw.users.keys",
   "user_email_pool": "ru-dc2.rgw.users.email",
   "user_swift_pool": "ru-dc2.rgw.users.swift",
   "user_uid_pool": "ru-dc2.rgw.users.uid",
   "system_key": {
       "access_key": "SYSTEM_ACCESS_KEY",
       "secret_key": "SYSTEM_SECRET_KEY"
   },
   "placement_pools": [
       {
           "key": "default-placement",
           "val": {
               "index_pool": "ru-dc2.rgw.buckets.index",
               "data_pool": "ru-dc2.rgw.buckets.data",
               "data_extra_pool": "ru-dc2.rgw.buckets.non-ec",
               "index_type": 0
           }
       }
   ],
   "metadata_heap": "ru-dc2.rgw.meta",
}

Подготовка первого датацентра

  1. Генерирем ключи для radosgw:
    ceph auth get-or-create client.rgw.ru-dc1 osd 'allow rwx' mon 'allow rwx' -o /etc/ceph/ceph.client.radosgw.keyring
    

  2. Добавляем секцию, описывающую наш radosgw в /etc/ceph/ceph.conf:

    [client.rgw.ru-dc1]
    rgw_zonegroup = ru
    rgw_zone = ru-dc1
    log_file = /var/log/ceph/client.rgw.dc1.log
    keyring = /etc/ceph/ceph.client.radosgw.keyring
    rgw_dns_name = s3.dc1.superdomain.ru
    rgw_socket_path = /tmp/rgw.ru-dc1.sock
    host = ceph1

  3. Просматриваем командой ceph osd pool ls, какие пулы в данный момент созданы, и удаляем все, кроме rbd, в этом нам поможет команда ceph osd pool delete $pool $pool --yes-i-really-really-mean-it (да, именно 2 раза), где $pool — название пула.

    У меня это было:

    ceph osd pool delete default.rgw.control default.rgw.control --yes-i-really-really-mean-it
    ceph osd pool delete default.rgw.data.root default.rgw.data.root --yes-i-really-really-mean-it
    ceph osd pool delete default.rgw.gc default.rgw.gc --yes-i-really-really-mean-it
    ceph osd pool delete default.rgw.log default.rgw.log --yes-i-really-really-mean-it
    

  4. А теперь создаем нужные:
    ceph osd pool create .rgw.root 8
    ceph osd pool create ru-dc1.rgw.control 8
    ceph osd pool create ru-dc1.rgw.data.root 8
    ceph osd pool create ru-dc1.rgw.gc 8
    ceph osd pool create ru-dc1.rgw.log 8
    ceph osd pool create ru-dc1.rgw.intent-log 8
    ceph osd pool create ru-dc1.rgw.usage 8
    ceph osd pool create ru-dc1.rgw.users.keys 8
    ceph osd pool create ru-dc1.rgw.users.email 8
    ceph osd pool create ru-dc1.rgw.users.swift 8
    ceph osd pool create ru-dc1.rgw.users.uid 8
    ceph osd pool create ru-dc1.rgw.buckets.index 8
    ceph osd pool create ru-dc1.rgw.buckets.data 128 128
    ceph osd pool create ru-dc1.rgw.meta 8
    

  5. Создаем директорию для нашего radosgw клиента и правим владельца:
    mkdir  /var/lib/ceph/radosgw/ceph-rgw.ru-dc1
    chown ceph:ceph /var/lib/ceph/radosgw/ceph-rgw.ru-dc1
    

  6. Удаляем realm, zonegroup и zone, которые были по умолчанию. Просмотреть их можно командой radosgw-admin (realm|zonegroup|zone) list, у меня это было так:
    radosgw-admin zonegroup delete --rgw-zonegroup=default
    radosgw-admin zone delete --rgw-zone=default
    

  7. Создаем наши realm, zonegroup, zone, новый period:
    radosgw-admin realm create --rgw-realm=project1 --default
    radosgw-admin zonegroup set --rgw-realm=project1 --rgw-zonegroup=ru --default < zonegroup.json
    radosgw-admin zone set --rgw-realm=project1 --rgw-zonegroup=ru --rgw-zone=ru-dc1 --default < dc1.json
    radosgw-admin zone set --rgw-realm=project1 --rgw-zonegroup=ru --rgw-zone=ru-dc2 < dc2.json
    radosgw-admin period update --commit
    

  8. Ставим и настраиваем apache2 на работу с нашим облаком. Для этого нужен сам apache2 и libapache2-mod-fastcgi. Репликация c версией из стандартного репозитория ubuntu у меня нормально не заработала, но команда ceph позаботились об этом, и его можно взять в отдельной репе.
    echo “deb http://gitbuilder.ceph.com/libapache-mod-fastcgi-deb-trusty-x86_64-basic/ref/master trusty main” > /etc/apt/sources.list.d/ceph-fastcgi.list
    apt-key adv --keyserver keyserver.ubuntu.com --recv-key 6EAEAE2203C3951A
    apt-get update
    apt-get install apache2 libapache2-mod-fastcgi
    a2enmod rewrite
    

  9. Сам конфиг апача:
    FastCgiExternalServer /var/www/s3gw.fcgi -socket /tmp/rgw.ru-dc1.sock
    <VirtualHost *:80>
           ServerName s3.dc1.superdomain.ru
           ServerAlias *.s3.dc1.superdomain.ru
           DocumentRoot /var/www
           RewriteEngine On
           RewriteRule  ^/(.*) /s3gw.fcgi?%{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 vhost_combined
           ServerSignature Off
     
    </VirtualHost>
    

  10. Апач рестартуем:
    service apache2 restart
    

  11. Создаем скрипт /var/www/s3gw.fcgi
    #!/bin/sh
    exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n ceph-rgw.ru-dc1
    

  12. правим права:
    chmod +x /var/www/s3gw.fcgi
    

  13. И, наконец, стартуем radosgw:
    start radosgw id=rgw.ru-dc1
    

  14. Создаем системного пользователя:
    radosgw-admin user create --uid=zone.user --display-name="ZoneUser" --access-key=SYSTEM_ACCESS_KEY --secret=SYSTEM_SECRET_KEY --system
    

На этом мы настроили 1-й дц, и переходим ко 2-му.

Дц №2

Все пункты проводим аналогичным образом и для второго кластера, просто заменив dc1 на dc2.

Еще чуть-чуть

На текущем этапе мы получаем репликацию данных в ведрах, но, чтобы синкать сам список ведер и пользователей, нужен radosgw-agent.

  1. Ставим его в первый дата-центр:
    apt-get install radosgw-agent
    

  2. Делаем конфиг /etc/ceph/radosgw-agent/default.conf:
    src_zone: ru-dc1
    source: http://s3.dc1.superdomain.ru:80
    src_access_key: SYSTEM_ACCESS_KEY
    src_secret_key: SYSTEM_SECRET_KEY
    destination: http://s3.dc2.superdomain.ru:80
    dest_access_key: SYSTEM_ACCESS_KEY
    dest_secret_key: SYSTEM_SECRET_KEY
    log_file: /var/log/ceph/sync.dc1-dc2.log
    dest_zone: ru-dc2
    

  3. И запускаем его:
    /etc/init.d/radosgw-agent start
    

Что в итоге?

А в итоге мы получаем active-active геораспределенное s3-облако. Все операции записи/удаления объектов будут производиться асинхронно, с задержкой в пару десятков секунд. Единственное ограничение — это невозможность создания ведер во втором дата-центре.

Автор: zayas

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js