«1. Обзор

Обычно мы развертываем различные приложения на одном и том же кластере машин. Например, в настоящее время принято иметь распределенный механизм обработки, такой как Apache Spark или Apache Flink, с распределенными базами данных, такими как Apache Cassandra, в одном кластере.

Apache Mesos — это платформа, позволяющая эффективно распределять ресурсы между такими приложениями.

В этой статье мы сначала обсудим несколько проблем распределения ресурсов в приложениях, развернутых в одном кластере. Позже мы увидим, как Apache Mesos обеспечивает лучшее использование ресурсов между приложениями.

2. Совместное использование кластера

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

    Статическое разбиение кластера и запуск приложения в каждом разделе Выделение набора машин для приложения

Хотя эти подходы позволяют приложениям работать независимо друг от друга, это не t добиться высокой степени использования ресурсов.

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

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

Apache Mesos помогает с динамическим распределением ресурсов между приложениями.

3. Apache Mesos

При обоих рассмотренных выше подходах к совместному использованию кластера приложения знают только о ресурсах определенного раздела или машины, на которой они работают. Однако Apache Mesos предоставляет приложениям абстрактное представление обо всех ресурсах в кластере.

Как мы вскоре увидим, Mesos действует как интерфейс между машинами и приложениями. Он предоставляет приложениям доступные ресурсы на всех машинах в кластере. Эта информация часто обновляется, чтобы включить ресурсы, высвобождаемые приложениями, достигшими состояния завершения. Это позволяет приложениям принимать наилучшие решения о том, какую задачу выполнять на какой машине.

Чтобы понять, как работает Mesos, давайте взглянем на его архитектуру:

Это изображение является частью официальной документации Mesos (источник). Здесь Hadoop и MPI — это два приложения, которые совместно используют кластер.

Мы поговорим о каждом показанном здесь компоненте в следующих нескольких разделах.

3.1. Mesos Master

Master является основным компонентом в этой настройке и хранит текущее состояние ресурсов в кластере. Кроме того, он действует как оркестратор между агентами и приложениями, передавая информацию о таких вещах, как ресурсы и задачи.

Поскольку любой сбой в мастере приводит к потере состояния ресурсов и задач, мы развертываем его в конфигурации высокой доступности. Как видно на диаграмме выше, Mesos развертывает резервные основные демоны вместе с одним лидером. Эти демоны полагаются на Zookeeper для восстановления состояния в случае сбоя.

3.2. Агенты Mesos

Кластер Mesos должен запускать агент на каждой машине. Эти агенты периодически сообщают о своих ресурсах мастеру и, в свою очередь, получают задачи, запланированные для выполнения приложением. Этот цикл повторяется после завершения или потери запланированной задачи.

В следующих разделах мы увидим, как приложения планируют и выполняют задачи на этих агентах.

3.3. Mesos Frameworks

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

Платформа Mesos состоит из двух подкомпонентов:

    Планировщик — позволяет приложениям планировать задачи на основе доступных ресурсов на всех агентах. Исполнитель — работает на всех агентах и ​​содержит всю информацию, необходимую для выполнения. любая запланированная задача на этом агенте

Весь процесс изображается следующим потоком:

«

«Сначала агенты сообщают о своих ресурсах мастеру. В этот момент мастер предлагает эти ресурсы всем зарегистрированным планировщикам. Этот процесс известен как предложение ресурса, и мы подробно обсудим его в следующем разделе.

Затем планировщик выбирает лучшего агента и выполняет на нем различные задачи через Мастера. Как только исполнитель завершает назначенную задачу, агенты повторно публикуют свои ресурсы мастеру. Мастер повторяет этот процесс совместного использования ресурсов для всех фреймворков в кластере.

Mesos позволяет приложениям реализовывать собственный планировщик и исполнитель на различных языках программирования. Java-реализация планировщика должна реализовывать интерфейс планировщика:

public class HelloWorldScheduler implements Scheduler {
 
    @Override
    public void registered(SchedulerDriver schedulerDriver, Protos.FrameworkID frameworkID, 
      Protos.MasterInfo masterInfo) {
    }
 
    @Override
    public void reregistered(SchedulerDriver schedulerDriver, Protos.MasterInfo masterInfo) {
    }
 
    @Override
    public void resourceOffers(SchedulerDriver schedulerDriver, List<Offer> list) {
    }
 
    @Override
    public void offerRescinded(SchedulerDriver schedulerDriver, OfferID offerID) {
    }
 
    @Override
    public void statusUpdate(SchedulerDriver schedulerDriver, Protos.TaskStatus taskStatus) {
    }
 
    @Override
    public void frameworkMessage(SchedulerDriver schedulerDriver, Protos.ExecutorID executorID, 
      Protos.SlaveID slaveID, byte[] bytes) {
    }
 
    @Override
    public void disconnected(SchedulerDriver schedulerDriver) {
    }
 
    @Override
    public void slaveLost(SchedulerDriver schedulerDriver, Protos.SlaveID slaveID) {
    }
 
    @Override
    public void executorLost(SchedulerDriver schedulerDriver, Protos.ExecutorID executorID, 
      Protos.SlaveID slaveID, int i) {
    }
 
    @Override
    public void error(SchedulerDriver schedulerDriver, String s) {
    }
}

Как видно, он в основном состоит из различных методов обратного вызова для связи, в частности, с мастером.

Точно так же реализация исполнителя должна реализовывать интерфейс Executor:

public class HelloWorldExecutor implements Executor {
    @Override
    public void registered(ExecutorDriver driver, Protos.ExecutorInfo executorInfo, 
      Protos.FrameworkInfo frameworkInfo, Protos.SlaveInfo slaveInfo) {
    }
  
    @Override
    public void reregistered(ExecutorDriver driver, Protos.SlaveInfo slaveInfo) {
    }
  
    @Override
    public void disconnected(ExecutorDriver driver) {
    }
  
    @Override
    public void launchTask(ExecutorDriver driver, Protos.TaskInfo task) {
    }
  
    @Override
    public void killTask(ExecutorDriver driver, Protos.TaskID taskId) {
    }
  
    @Override
    public void frameworkMessage(ExecutorDriver driver, byte[] data) {
    }
  
    @Override
    public void shutdown(ExecutorDriver driver) {
    }
}

Мы увидим рабочую версию планировщика и исполнителя в следующем разделе.

4. Управление ресурсами

4.1. Предложения ресурсов

Как мы обсуждали ранее, агенты публикуют информацию о своих ресурсах для мастера. В свою очередь мастер предлагает эти ресурсы платформам, работающим в кластере. Этот процесс известен как предложение ресурса.

Предложение ресурсов состоит из двух частей – ресурсов и атрибутов.

Ресурсы используются для публикации информации об оборудовании машины агента, такой как память, ЦП и диск.

Для каждого агента есть пять предопределенных ресурсов:

    cpu gpus mem disk ports

Значения для этих ресурсов могут быть определены в одном из трех типов:

    Scalar — используется для представления числовой информации использование чисел с плавающей запятой для разрешения дробных значений, таких как 1,5 ГБ памяти. Диапазон — используется для представления диапазона скалярных значений — например, диапазона портов. Набор — используется для представления нескольких текстовых значений

По умолчанию , агент Mesos пытается обнаружить эти ресурсы с компьютера.

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

Например, мы можем запустить наш агент со следующими ресурсами:

--resources='cpus:24;gpus:2;mem:24576;disk:409600;ports:[21000-24000,30000-34000];bugs(debug_role):{a,b,c}'

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

В дополнение к ресурсам агенты могут публиковать атрибуты ключ-значение для мастера. Эти атрибуты действуют как дополнительные метаданные для агента и помогают структурам в планировании решений.

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

--attributes='rack:abc;zone:west;os:centos5;level:10;keys:[1000-1500]'

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

4.2. Роли ресурсов

Многие современные операционные системы поддерживают несколько пользователей. Точно так же Mesos также поддерживает несколько пользователей в одном кластере. Эти пользователи называются ролями. Мы можем рассматривать каждую роль как потребителя ресурсов в кластере.

Благодаря этому агенты Mesos могут распределять ресурсы по разным ролям на основе разных стратегий распределения. Более того, фреймворки могут подписываться на эти роли внутри кластера и иметь детальный контроль над ресурсами в рамках разных ролей.

Например, рассмотрим кластер, в котором размещаются приложения, обслуживающие разных пользователей в организации. Таким образом, разделяя ресурсы на роли, каждое приложение может работать изолированно друг от друга.

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

Например, предположим, что у нас есть два приложения в кластере с именами производитель и потребитель. Здесь производитель записывает данные в постоянный том, который впоследствии может прочитать потребитель. Мы можем оптимизировать потребительское приложение, поделившись объемом с производителем.

«Поскольку Mesos позволяет нескольким приложениям подписываться на одну и ту же роль, мы можем связать постоянный том с ролью ресурса. Кроме того, платформы как для производителя, так и для потребителя будут подписываться на одну и ту же роль ресурса. Таким образом, приложение-потребитель теперь может запускать задачу чтения данных на том же томе, что и приложение-производитель.

4.3. Резервирование ресурсов

Теперь может возникнуть вопрос, как Mesos распределяет ресурсы кластера по разным ролям. Mesos распределяет ресурсы посредством резервирования.

Существует два типа резервирования:

    Статическое резервирование. Динамическое резервирование.

Статическое резервирование похоже на выделение ресурсов при запуске агента, которое мы обсуждали в предыдущих разделах. теперь агент Mesos резервирует восемь процессоров и 4096 м памяти для роли с именем baeldung.

 --resources="cpus:4;mem:2048;cpus(baeldung):8;mem(baeldung):4096"

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

Mesos выделяет все ресурсы без какой-либо роли в роль по умолчанию с именем (*). Master предлагает такие ресурсы для всех фреймворков, независимо от того, подписаны они на него или нет.

4.4. Веса ресурсов и квоты

Как правило, мастер Mesos предлагает ресурсы, используя стратегию справедливости. Он использует взвешенную доминантную справедливость ресурсов (wDRF) для определения ролей, которым не хватает ресурсов. Затем мастер предлагает больше ресурсов платформам, подписавшимся на эти роли.

Событие, хотя справедливое распределение ресурсов между приложениями является важной характеристикой Mesos, оно не всегда необходимо. Предположим, в кластере размещаются приложения, которые требуют мало ресурсов, а также те, которые требуют больших ресурсов. В таких развертываниях мы хотели бы распределять ресурсы в зависимости от характера приложения.

Mesos позволяет фреймворкам требовать больше ресурсов, подписываясь на роли и добавляя более высокое значение веса для этой роли. Следовательно, если есть две роли, одна с весом 1, а другая с весом 2, Mesos выделит вдвое большую справедливую долю ресурсов для второй роли.

Как и в случае с ресурсами, мы можем настраивать веса через конечные точки HTTP.

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

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

5. Реализация фреймворка

Как мы обсуждали в предыдущем разделе, Mesos позволяет приложениям предоставлять реализации фреймворка на выбранном ими языке. В Java инфраструктура реализуется с использованием основного класса, который действует как точка входа для процесса фреймворка, и реализации Scheduler и Executor, обсуждавшихся ранее.

5.1. Основной класс Framework

Перед реализацией планировщика и исполнителя мы сначала реализуем точку входа для нашего каркаса, которая:

Регистрирует себя в мастере Предоставляет агентам информацию о времени выполнения исполнителя Запускает планировщик

    Мы’ Сначала добавим зависимость Maven для Mesos:

Затем мы реализуем HelloWorldMain для нашей структуры. Первое, что мы сделаем, это запустим процесс-исполнитель на агенте Mesos:

<dependency>
    <groupId>org.apache.mesos</groupId>
    <artifactId>mesos</artifactId>
    <version>0.28.3</version>
</dependency>

Здесь мы сначала настроили двоичное расположение исполнителя. Агент Mesos загружал этот бинарный файл при регистрации фреймворка. Затем агент выполнит данную команду, чтобы запустить процесс-исполнитель.

public static void main(String[] args) {
  
    String path = System.getProperty("user.dir")
      + "/target/libraries2-1.0.0-SNAPSHOT.jar";
  
    CommandInfo.URI uri = CommandInfo.URI.newBuilder().setValue(path).setExtract(false).build();
  
    String helloWorldCommand = "java -cp libraries2-1.0.0-SNAPSHOT.jar com.baeldung.mesos.executors.HelloWorldExecutor";
    CommandInfo commandInfoHelloWorld = CommandInfo.newBuilder()
      .setValue(helloWorldCommand)
      .addUris(uri)
      .build();
  
    ExecutorInfo executorHelloWorld = ExecutorInfo.newBuilder()
      .setExecutorId(Protos.ExecutorID.newBuilder()
      .setValue("HelloWorldExecutor"))
      .setCommand(commandInfoHelloWorld)
      .setName("Hello World (Java)")
      .setSource("java")
      .build();
}

Далее мы инициализируем наш фреймворк и запустим планировщик:

Наконец, мы запустим MesosSchedulerDriver, который регистрируется в Мастере. Для успешной регистрации мы должны передать IP Мастера в качестве аргумента программы args[0] этому основному классу:

FrameworkInfo.Builder frameworkBuilder = FrameworkInfo.newBuilder()
  .setFailoverTimeout(120000)
  .setUser("")
  .setName("Hello World Framework (Java)");
 
frameworkBuilder.setPrincipal("test-framework-java");
 
MesosSchedulerDriver driver = new MesosSchedulerDriver(new HelloWorldScheduler(),
  frameworkBuilder.build(), args[0]);

«

int status = driver.run() == Protos.Status.DRIVER_STOPPED ? 0 : 1;

driver.stop();

System.exit(status);

«В классе, показанном выше, CommandInfo, ExecutorInfo и FrameworkInfo являются Java-представлениями сообщений protobuf между мастером и платформами.

5.2. Реализация планировщика

Начиная с Mesos 1.0, мы можем вызывать конечную точку HTTP из любого Java-приложения для отправки и получения сообщений мастеру Mesos. Некоторые из этих сообщений включают, например, регистрацию платформы, предложения ресурсов и отклонения предложений.

Для Mesos 0.28 или более ранней версии нам необходимо реализовать интерфейс планировщика:

По большей части мы сосредоточимся только на методе resourceOffers планировщика. Давайте посмотрим, как планировщик получает ресурсы и инициализирует задачи на их основе.

Сначала посмотрим, как планировщик распределяет ресурсы для задачи:

@Override
public void resourceOffers(SchedulerDriver schedulerDriver, List<Offer> list) {

    for (Offer offer : list) {
        List<TaskInfo> tasks = new ArrayList<TaskInfo>();
        Protos.TaskID taskId = Protos.TaskID.newBuilder()
          .setValue(Integer.toString(launchedTasks++)).build();

        System.out.println("Launching printHelloWorld " + taskId.getValue() + " Hello World Java");

        Protos.Resource.Builder cpus = Protos.Resource.newBuilder()
          .setName("cpus")
          .setType(Protos.Value.Type.SCALAR)
          .setScalar(Protos.Value.Scalar.newBuilder()
            .setValue(1));

        Protos.Resource.Builder mem = Protos.Resource.newBuilder()
          .setName("mem")
          .setType(Protos.Value.Type.SCALAR)
          .setScalar(Protos.Value.Scalar.newBuilder()
            .setValue(128));

Здесь мы выделили 1 ЦП и 128 МБ памяти для нашей задачи. Далее мы будем использовать SchedulerDriver для запуска задачи на агенте:

        TaskInfo printHelloWorld = TaskInfo.newBuilder()
          .setName("printHelloWorld " + taskId.getValue())
          .setTaskId(taskId)
          .setSlaveId(offer.getSlaveId())
          .addResources(cpus)
          .addResources(mem)
          .setExecutor(ExecutorInfo.newBuilder(helloWorldExecutor))
          .build();

        List<OfferID> offerIDS = new ArrayList<>();
        offerIDS.add(offer.getId());

        tasks.add(printHelloWorld);

        schedulerDriver.launchTasks(offerIDS, tasks);
    }
}

Кроме того, планировщику часто приходится отклонять предложения ресурсов. Например, если планировщик не может запустить задачу на агенте из-за нехватки ресурсов, он должен немедленно отклонить это предложение:

schedulerDriver.declineOffer(offer.getId());

5.3. Реализация Executor

Как мы обсуждали ранее, компонент executor платформы отвечает за выполнение задач приложения на агенте Mesos.

Мы использовали конечные точки HTTP для реализации планировщика в Mesos 1.0. Точно так же мы можем использовать конечную точку HTTP для исполнителя.

В предыдущем разделе мы обсуждали, как фреймворк настраивает агент для запуска процесса-исполнителя:

java -cp libraries2-1.0.0-SNAPSHOT.jar com.baeldung.mesos.executors.HelloWorldExecutor

Примечательно, что эта команда рассматривает HelloWorldExecutor как основной класс. Мы реализуем этот основной метод для инициализации MesosExecutorDriver, который соединяется с агентами Mesos для получения задач и обмена другой информацией, такой как статус задачи: агент. Информация для запуска любой задачи содержится в HelloWorldExecutor:

public class HelloWorldExecutor implements Executor {
    public static void main(String[] args) {
        MesosExecutorDriver driver = new MesosExecutorDriver(new HelloWorldExecutor());
        System.exit(driver.run() == Protos.Status.DRIVER_STOPPED ? 0 : 1);
    }
}

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

public void launchTask(ExecutorDriver driver, TaskInfo task) {
 
    Protos.TaskStatus status = Protos.TaskStatus.newBuilder()
      .setTaskId(task.getTaskId())
      .setState(Protos.TaskState.TASK_RUNNING)
      .build();
    driver.sendStatusUpdate(status);
 
    System.out.println("Execute Task!!!");
 
    status = Protos.TaskStatus.newBuilder()
      .setTaskId(task.getTaskId())
      .setState(Protos.TaskState.TASK_FINISHED)
      .build();
    driver.sendStatusUpdate(status);
}

В некоторых случаях исполнители также могут отправлять данные обратно планировщику:

6. Заключение

String myStatus = "Hello Framework";
driver.sendFrameworkMessage(myStatus.getBytes());

В этой статье мы кратко обсудили совместное использование ресурсов между приложениями, работающими в одном кластере. Мы также обсудили, как Apache Mesos помогает приложениям достичь максимального использования с абстрактным представлением ресурсов кластера, таких как ЦП и память.

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

Наконец-то мы увидели реализацию фреймворка Mesos на Java.

Как обычно, все примеры доступны на GitHub.

«