Используя Ceph для хранения бэкапов c помощью их S3-совместимого хранилища RadosGW, мы пришли к тому, что один radosGW не справляется с возложенной на него нагрузкой и решили, что пора бы его разбалансировать с сопутствующей отказоустойчивостью. В итоге пришли к решению балансировки с помощью GoBetween (очень лёгкий L4 балансировщик, подробнее на gobetween.io), а отказоустойчивость организовали с помощью VRRP.

Вышла такая схема:

  1. master нода vrrp получает поток данных по http(s);
  2. gobetween раскидывает весь трафик на себя же и backup ноду vrrp;
  3. radosgw в свою очередь пишут непосредственно в ceph;
  4. в случае падения master ноды vrrp, backup нода берёт всю нагрузку на себя до тех пор, пока мастер не поднимется

Нашу реализацию данного действа читайте ниже

Дано:

  1. Кластер Ceph (Jewel)
    • IP мониторов: 10.0.1.1, 10.0.1.2, 10.0.1.3
  2. Два железных сервера (CentOS)
    • Первый сервер 10.0.0.1 (назовём его gbt1.example.com)
    • Второй сервер 10.0.0.2 (gbt2.example.com)
    • Общий IP будет 10.0.0.3 (s3.example.com)
  3. Домен example.com

Задача:

Сделать балансировку с отказоустойчивостью для S3 хранилища, организованному с помощью RadosGW

Этапы:

  1. Развернуть RadosGW на двух серверах
  2. Организовать отказоустойчивость с поомщью VRRP
  3. Организовать балансировку S3 трафика с помощью GoBetween
  4. Проверить

Подготовка (на обеих машинах всё идентично)


На серверах установлен CentOS 7.4, сразу после установки ОС обновим всё:

# yum -y update

Установим весь софт, который нам потребуется по ТЗ (кроме самого ceph, ибо сначала ставится только его репозиторий):

# yum -y install keepalived centos-release-ceph-jewel wget

В данный момент у нас ещё не установлен Ceph, поэтому установим его:

# yum -y install ceph-radosgw

Сразу настроим фаерволл, окрыв нужные порты и разрешив сервисы:

# firewall-cmd --permanent --add-port=18080/tcp
# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface enp2s0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface enp2s0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# firewall-cmd --permanent --add-port=10050/tcp
# firewall-cmd --reload

Выключим SELinux (на всякий случай):

# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
# setenforce 0

Разворачиваем RadosGW


Изначально кластер Ceph уже поднят, думаю, подробностей касаться мы тут не будем, тема не этой статьи, сразу перейдём к настройке radosGW.

Конфиг приведён для примера, в вашем случае некоторые параметры могут отличаться:

# cat /etc/ceph/ceph.conf 
[global]
fsid = 01dea7f3-91f4-48d1-9d44-ba93d4a103c5
mon_host = 10.0.1.1, 10.0.1.2, 10.0.1.3
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
public_network = 10.0.1.0/24

[client]
rbd_cache = true

[client.radosgw.gateway]
rgw_frontends = civetweb port=18080
rgw_region = example
rgw_region_root_pool = .example.rgw.root
rgw_zone = example-s3
rgw_zone_root_pool = .example-s3.rgw.root
host = s3
keyring = /etc/ceph/client.radosgw.gateway
rgw_dns_name = s3.example.com
rgw_print_continue = true

Не забываем скопировать ключ /etc/ceph/client.radosgw.gateway с любой ноды кластера Ceph
Запустим radosgw:

# systemctl start ceph-radosgw@radosgw.gateway

И добавим его в автостарт:

# systemctl enable ceph-radosgw@radosgw.gateway

Разворачиваем VRRP


На master ноде (разница в опциях state и priority):

# cat /etc/keepalived/keepalived.conf
global_defs {
   notification_email {
    user@example.com
   }

   notification_email_from gbt@example.com
   smtp_server mail.example.com
   smtp_connect_timeout 30
   router_id GBT1
}

vrrp_instance VI_1 {
    state MASTER
    interface enp2s0
    virtual_router_id 33
    priority 101
    advert_int 1
    smtp_alert

    authentication {
     auth_type PASS
     auth_pass 123123123
    }

    virtual_ipaddress {
     10.0.0.3
    }
}

На backup ноде:

# cat /etc/keepalived/keepalived.conf
global_defs {
   notification_email {
    user@example.com
   }

   notification_email_from gbt@example.com
   smtp_server mail.example.com
   smtp_connect_timeout 30
   router_id GBT1
}

vrrp_instance VI_1 {
    state BACKUP
    interface enp2s0
    virtual_router_id 33
    priority 100
    advert_int 1
    smtp_alert

    authentication {
     auth_type PASS
     auth_pass 123123123
    }

    virtual_ipaddress {
     10.0.0.3
    }
}

Перезапускаем и добавляем в автостарт (обе ноды):

# systemctl restart keepalived
# systemctl enable keepalived

Разворачиваем GoBetween


Для начала скачаем и распакуем бинарник gobetween:

# wget https://github.com/yyyar/gobetween/releases/download/0.5.0/gobetween_0.5.0_linux_amd64.tar.gz

# tar -xzf gobetween_0.5.0_linux_amd64.tar.gz -C /usr/local/bin/

Пишем конфиг gobetween (для SSL соединений указываем местонахождение ключей). Конфиг на обеих нодах одинаковый:

# cat /etc/gobetween.toml
[logging]
level = "debug"   # "debug" | "info" | "warn" | "error"
output = "/var/log/gobetween.log"

[api]
enabled = true  # true | false
bind = ":8888"  # "host:port"
cors = false    # cross-origin resource sharing

[defaults]
max_connections = 0              # Maximum simultaneous connections to the server
client_idle_timeout = "0"        # Client inactivity duration before forced connection drop
backend_idle_timeout = "0"       # Backend inactivity duration before forced connection drop
backend_connection_timeout = "0" # Backend connection timeout (ignored in udp)

[servers]

[servers.sample]
 protocol = "tls"
 bind = "0.0.0.0:443"
 balance = "roundrobin"

  [servers.sample.discovery]
   kind = "static"
   static_list = [
     "10.0.0.1:18080 weight=1",
     "10.0.0.2:18080 weight=1"
    ]

  [servers.sample.tls]
   root_ca_cert_path = "/etc/exampleSSC-CA.crt"
   cert_path = "/etc/s3.example.com.crt"
   key_path = "/etc/s3.example.com.key"

  [servers.sample.healthcheck]
   fails = 1
   passes = 1
   interval = "2s"
   timeout="1s"
   kind = "ping"
   ping_timeout_duration = "500ms"

[servers.sample2]
 protocol = "tcp"
 bind = "0.0.0.0:80"
 balance = "roundrobin"

  [servers.sample2.discovery]
   kind = "static"
   static_list = [
    "10.0.0.1:18080 weight=1",
    "10.0.0.2:18080 weight=1"
   ]

  [servers.sample2.healthcheck]
   fails = 1
   passes = 1
   interval = "2s"
   timeout="1s"
   kind = "ping"
   ping_timeout_duration = "500ms"

Запуск gobetween производится следующей командой (в автостарт добавляйте любым удобным для вас способом):

# /usr/local/bin/gobetween -c /etc/gobetween.toml

Проверка


Для проверки можно использовать любой S3 клиент, например, такие, как s3cmd или DragonDisk. Вариант проверки для s3cmd будет выглядеть так (при учёте, что в конфиге уже указан в качестве сервера s3.example.com):

# s3cmd ls

Если у вас там уже есть хоть какой то bucket, то в выхлопе будет его имя, если бакетов нет, то будет пустой выхлоп.

Как это выглядит сейчас — можете увидеть на скрине снизу. Статистика за сутки (графики в гигабайтах в секунду):



Итоги


Нагрузка снизилась значительно, затупов не осталось и теперь все бекапы успевают собраться за ночь (до этого уже в разгар рабочего дня могло ещё собираться).

Надеюсь, данная хаутушка поможет вам в ускорении и уменьшении нагрузки на radosgw

Комментарии (5)


  1. onyxmaster
    11.01.2018 15:15

    Спасибо. Немного не по теме, но можете что-нибудь про железки написать, на которых у вас это работает? Надеюсь раз вы показали графики, скорее всего не будет проблемой и рассказать про сетевые карты, коммутаторы и диски.


    1. vankosa Автор
      11.01.2018 15:34

      В качестве серверов взяли какие то не очень молодые супермикры, которые особо уже не нужны были. Сетевушки соединены с коммутаторами по SFP 10G, собраны в бондинг (LACP). Диски обычные сата, на них нагрузки в данном случае нет вообще (если не считать логирование VRRP, RGW и gobetween). Можно, конечно, расширить статью описанием поднятия бондинга, но это и так уже миллион раз обсосано


      1. onyxmaster
        11.01.2018 20:57

        Спасибо. Про бондинг вопросов нет.


  1. kay
    12.01.2018 11:53

    А в чем смысл использования gobetween? Keepalived также отлично балансирует при помощи IPVS L4.


    1. vankosa Автор
      12.01.2018 12:36

      Смысл в том, что gbt сам прикидывается веб сервисом с возможностью ssl соединения, а не просто роутит трафик по разным местам