Статьи

Репликация как услуга (часть первая)

[Эта статья первоначально написана  ДеВейном Филппи .]

Вступление

Поставщики облачных вычислений предоставляют различные API для развертывания и взаимодействия с предоставляемыми ими услугами. Количество этих API выросло вместе с разнообразием предлагаемых услуг. Первоначально была предоставлена ​​возможность запрашивать ресурсы облачных вычислений и манипулировать ими. Сюда вошли многие другие службы уровня инфраструктуры, такие как балансировка нагрузки, хранение, идентификация, DNS, образы и работа в сети. Оттуда API-интерфейсы перешли в сервисы уровня платформы, включая хранилище больших двоичных объектов, резервное копирование, создание очередей, кэширование, базы данных, большие данные и многое другое. В некотором смысле Cloudify объединяет некоторые из этих сервисов за декларативным (рецептурным) фасадом. Это позволяет пользователям взаимодействовать с множеством API-интерфейсов, взаимодействуя с универсальным API-интерфейсом Cloudify (в случае блочного хранилища) или портативными рецептами.Цель создания репликации как возможности службы идет не так, как стандартизация существующих API, и создание стандартизированной нейтральной к облакам (и потенциально межоблачной) службы, которая не предоставляется самими поставщиками облачных услуг. Репликация как услуга основана на недавней работе, которая принеслаGigaspaces XAP в облаке . Используя существующий рецепт xap-gateway, создание сети репликации возможно вручную. В этом и последующих статьях описывается процесс превращения этой базовой возможности в настоящую облачную службу, включающую поддержку нескольких облаков и API REST.

Начальная цель проекта

Я считаю полезным начинать такие проекты, сосредотачиваясь на опыте конечного пользователя (в случае с пользователем API), а потом позабочусь о деталях. Для репликации как службы (RAAS) я рассмотрел произвольно сложную топологию сети репликации.  Возможность репликации XAP WAN допускает произвольно сложные топологии, поэтому это идеальный инструмент для службы репликации общего назначения. Чтобы сосредоточить усилия, я решил определить и реализовать один (но сложный) вариант использования: определить и развернуть сеть с несколькими облачными репликациями, используя REST API. При ручной настройке в не облачной среде настройка сети репликации XAP является четко определенным процессом. Блоки обработки шлюза размещаются на узлах каждого сайта, которые имеют доступ к Интернету, и настраиваются с использованием адресов другого сайта. В некоторых случаях в игру вступает NAT-сопоставление, которое хорошо обрабатывает XAP (хотя для облака это не так приятно, как мы скоро увидим). Информация о разных сайтах может быть собрана заранее, а все конфигурации выполнены упорядоченно. Попытка того же в облаке требует гораздо большего динамизма.

Чтобы представить репликацию как услугу, существует одно предварительное условие для любого подхода, ориентированного на Cloudify: само Cloudify должно быть запущено на каждом сайте, который будет участвовать. Я поставил еще одно упрощающее предварительное условие: на каждом сайте должна работать одна и та же версия Cloudify. Развертывание / расширение самой Cloudify должно быть сделано вручную, хотя я полагаю, что можно представить себе «Cloudify как сервис», но это кажется одной абстракцией слишком далеко и выходит за рамки этих усилий. Еще одно уточнение необходимо; создание облачной сети репликации как службы требует развертывания самого XAP вместе с пространством, в котором хранятся данные. Один из подходов (и, следовательно, пользовательского опыта), который я рассматривал, состоял в эмуляции ручного метода на уровне API. При таком подходепользователь будет вызывать REST API на каждом сайте с соответствующей конфигурацией, указанной в рецепте шлюза. Недостатком этого подхода является то, что он связывает шлюзы pu с хостами шлюзов (напомним, что каждый рецепт сервиса Cloudify представляет собой облачную машину). Другая большая проблема заключается в том, что это невозможно сделать (по крайней мере, без DNS), потому что, когда я сначала пытаюсь развернуть сайт 1, я ничего не знаю о других сайтах в моей топологии, потому что они еще не существуют. Это привело меня к двухфазному подходу, когда узел шлюза развертывается первым (по обычному рецепту Cloudify), и для создания топологии используется специальная команда. Мы вернемся к однофазному подходу позже, так как это становится технически возможным как побочный эффект решения различных проблем. Желательно ли это, другой вопрос. Напомним, что на данный момент подход будет:

  1. Разверните Cloudify на каждом сайте.
  2. Вызовите REST API для развертывания XAP, включая узел шлюза на каждом сайте.
  3. Вызовите API REST, чтобы вызвать пользовательскую команду для развертывания пространств репликации и PU шлюза на каждом сайте.

В результате пользователь получает один вызов REST для каждого сайта для развертывания рецептов Cloudify, а затем еще один вызов для каждого сайта для развертывания фактического пространства и шлюза. Не только это, но и информация от первого вызова должна быть сохранена (вызывающим абонентом) с первого прохода для отправки на второй проход для настройки компонентов. Я мог бы использовать этот подход как «версию 1.0», но он не был правильным. Это слишком низкий уровень и слишком сложный, и потребуется DNS. Пользователь API не должен понимать XAP, шлюзы или что-то еще. Пользователь должен реплицировать данные из точки А в точку Б (и, возможно, множество других точек); остальное (без каламбура) — это детали.


Итак, возвращаясь к исходной точке и представляя планирование репликации, что я буду делать?
Я бы нарисовал круги на салфетке со стрелками между

ними, представляющими сайты. Чтобы максимально приблизиться к этому (без написания графического интерфейса), я изменил подход к одному из:
  1. Разверните Cloudify на каждом сайте. (не могу уйти от этого)
  2. Определите мою топологию (шаг, не включенный в предыдущий список, но, очевидно, обязательный).
  3. Отобразите топологию одним вызовом REST на всех сайтах.

Идея состоит в том, чтобы взять салфетку и передать ее API, чтобы беспокоиться о деталях. На языке REST, салфеткой является JSON. Чтобы один вызов REST делал все, API REST должен фактически выступать в качестве мета-облака, развертывать рецепты и вызывать пользовательские команды на всех сайтах из одного места. Это кажется чище, потому что это означает, что в самой топологии есть модель (абстракция), которая может отображаться и обновляться с течением времени без необходимости углубляться в детали реализации.

Определение топологии

Ключевой абстракцией в реализации RAAS является топология репликации, которая будет выражена в JSON для совместимости с нормами REST. Определение топологии должно содержать достаточно информации для завершения построения топологии на всех сайтах. Первым делом бизнеса является определение самих сайтов. Каждому сайту требуется символическое имя и URL-адрес, который обозначает конечную точку Cloudify на сайте (напомним, что будет зачислено несколько установок Cloudify). В JSON это выглядит примерно так:

{"cloudify-instances":[
  {"site1-name":"<some public ip>:8100", "site2-name":"<some public ip>:8100" ... } 
]}

Чтобы поддерживать несколько одновременных топологий, топологии необходимо имя для ссылки на нее. Это немного расширяет определение с помощью записи «name»:

{
  "name":"some-name",
  "cloudify-instances":[
    {"site1-name":"<some public ip>:8100", "site2-name":"<some public ip>:8100" ...  }
  ]
}

Чтобы представить направленный поток данных, я выбрал концепцию ребра из теории графов, чтобы представить однонаправленную связь между двумя сайтами. Путем перечисления всех ребер можно создать произвольно сложную топологию в виде списка из двух элементов. Например, простой край-ведущий край между сайтами ‘site1’ и ‘site2’ будет представлен в JSON как

[['site1','site2']]

.  A bidirectional connection would look like

[['site1','site2'],['site2','site1']]

.  This makes the example look like:

{
  "name":"some-name",
  "cloudify-instances":[
    {"site1-name":"<some public ip>:8100", "site2-name":"<some public ip>:8100" ...  }
  ],
  "edges":[["site1","site2"],["site2","site1"]]
}

 Это охватывает основы. Одним (из многих) ограничений этой первоначальной попытки является игнорирование проблем безопасности в облаке (т. Е. Групп безопасности). В настоящее время предполагается, что такие проблемы решаются извне (либо вручную, либо путем переопределения базовых рецептов Cloudify). В любом случае, одной из особенностей контейнеров XAP, на которых размещаются шлюзы репликации, является то, что они должны запускаться с портами, используемыми для репликации. Поскольку REST API запускает эти контейнеры, для каждого сайта должны быть определены номера портов, определенные в определении топологии. Они могут иметь какие-то значения по умолчанию, но порты должны быть открыты как в контейнере, так и в Интернете. Для этого в JSON есть еще один раздел, называемый «порты», который определяет порты для каждого сайта. Добавив это, JSON почти завершен:

{
  "name":"some-name",
  "cloudify-instances":[
    {"site1-name":"<some reachable ip>:8100", "site2-name":"<some reachable ip>:8100" ...  }
  ],
  "edges":[["site1","site2"],["site2","site1"]],
  "ports:{
    "site1":{"discovery":"10000","data","10001"},
    "site2":{"discovery":"10000","data","10001"}
  }
}

В значительной степени охватывает определение топологии. Существуют и другие параметры, связанные с настройкой производительности репликации (например, размер пакета, интервал отправки и т. Д.), Но сейчас я не буду углубляться в них, чтобы не запачкать воду.

Конечная точка REST

Поскольку цель ограничена только вариантом использования «создание сети репликации», в REST API пока только один глагол. REST API реализован с помощью Spring MVC. API определяет единственный метод, который принимает действие POST с именем сети топологии в качестве переменной пути, например:

http://<host>:<port>/rest/repl/topology/my-topo

Это одно действие, которое делает довольно много, поэтому стоит пройти логику на высоком уровне. Вся информация о топологии включена в тело POST, как описано выше. Для вызова REST, который стремится сделать так много (и потенциально это может занять много времени), проверка запроса является критической. В более общем смысле, провал быстро (или как можно быстрее) является критическим. Это было реализовано в ограниченном объеме, но это определенно область, которая может быть расширена. Как только запрос подтвержден, каждый участвующий сайт связывается одновременно, когда это возможно, чтобы минимизировать задержку вызова. Я свободно использую термин «минимизировать», потому что любой отдельный вызов, который раскручивает несколько виртуальных машин на нескольких облаках (потенциально), не будет быстрым. Выполнение вызова REST вызывает следующие действия:

  1. Запросить подтверждение. Синтаксис запроса проверен. Проверяется наличие обязательных полей и правильность скалярных записей.
  2. Подтверждение участника. С каждым участвующим сайтом Cloudify связываются для проверки доступности. Каждый сайт проверяется, чтобы убедиться, что топология с тем же именем еще не запущена.
  3. XAP развернут на каждом сайте. Это включает в себя менеджер, контейнер (ы) и шлюз. Контейнер шлюза запускается с правильными портами, открытыми в соответствии с определением топологии. Шлюз развертывается с помощью настраиваемого преобразователя NAT, который допускает динамическую настройку (в отличие от стандартной версии). Контейнеры данных и контейнеры шлюзов развернуты в отдельных зонах, чтобы можно было правильно ориентировать будущие развертывания шлюза и пространства. Эта операция выполняется параллельно на всех сайтах.
  4. Пространства для хранения данных репликации создаются и развертываются на каждом сайте. Пространство имеет то же имя, что и топология. Особенности пространства, такие как разделы и резервные копии, взяты из определения топологии. Пространство развернуто с именем локального шлюза, взятым из топологии, и пустым блоком целей для последующего динамического введения цели . Эта операция выполняется параллельно на всех сайтах.
  5. Шлюзы репликации развернуты. Блок обработки шлюза создается на каждом сайте и разворачивается, а цель пространства обновляется. Делегаторы и приемники являются производными от определения топологии (ребра). Поиски создаются на основе предыдущих шагов в процессе развертывания, где назначаются необходимые IP-адреса. Таблица динамического преобразования NAT обновляется на основе частной / общедоступной информации IP, собранной на предыдущем этапе развертывания шлюза. Эта операция выполняется параллельно на всех сайтах.

Когда все это завершается (частичные сбои вызывают полный откат), система начинает репликацию.