2 заметки с тегом

yandex

How to: Yandex Datasphere

Время чтения текста – 10 минут

Yandex DataSphere — среда для ML-разработки, которая сочетает в себе привычный интерфейс Jupyter Notebook, технологию бессерверных вычислений и возможность бесшовного использования разных конфигураций вычислительных ресурсов.

Большую часть информации, которой мы с вами поделимся, мы почерпнули из закрытого практикума, который проводила команда Яндекса, куда был также приглашен спикер Александр Волков из компании Glowbyte. В процессе работы мы опирались на запись практикума, который был посвящен нюансам работы в Yandex DataSphere, а также задавали вопросы Александру и специалистам Яндекса напрямую, когда заходили в тупик и нуждались в помощи профессионала.

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

Создание проекта и ноутбука

  1. Для начала, создаем проект DataSphere в Yandex.Cloud.
  2. В проекте создаем ноутбук.
     

     
  3. В целом, работа с ноутбуками в DataSphere будет интуитивно понятна, если вы уже сталкивались, например, с Jupyter Notebook. Стоит лишь отметить, что можно выбрать конфигурацию машины, на которой будет работать ваш ноутбук. По дефолту стоит самая простая.
     

     

Еще, в начале использования сервиса важно понимать, как происходит тарификация. Если коротко, то размер оплаты зависит от времени использования сервиса и от мощности выбранной машины. При прогоне ячеек учитывается только время, затраченное на вычисления, при развертывании — время от создания деплоя до его удаления (даже если сервис простаивает). После регистрации Yandex.Cloud предлагает пробный период, которого вполне хватит для тестовых проектов. А дальше, конечно, придется платить.

Загрузка модели

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

  1. Можно воспользоваться, например, Яндекс.Диском. Для этого надо зарегистрировать приложение в Яндекс ID, после запомнить его ID и пароль.
  2. Для безопасности пароль можно положить в “секреты проекта”.
  3. Для загрузки файлов модели можно воспользоваться следующим кодом:
    !mkdir model
    import os
    from cloud_ml.storage.api import Storage
    disk = Storage.ya_disk(application_id=<your-app-id>, 
                           application_secret=os.environ[<your-secret-name>])
    disk.get_dir(<path-to-your-model-folder-at-ydisk>, './model')
    Если же необходимые вам файлы лежат в Github-репозитории, то все еще проще — надо только выполнить в ноутбуке команду:
    !git clone ‘<github-repository-url>’

Код модели

Давайте сделаем простой генератор случайных целых чисел, принимающий на вход границы:

input_data = {'left_bound': 1, 'right_bound': 5}
from random import randint 

def generate_value(input_data):
         return {'generated_value': randint(input_data['left_bound'], 
                                            input_data['right_bound'])}

output_data = generate_value(input_data)

Первую строку вынесем в отдельную ячейку (это нужно для деплоя).
При необходимости, вы можете загрузить специальные библиотеки/версии библиотек с помощью команды %pip install...

Деплой

  1. Для начала, нужно создать Docker-образ. Стоит отметить несколько моментов:
    • Build path — это необязательное поле, но при этом его значение не выставлено по дефолту, так что советуем указать хотя бы ‘.’.
    • Docker file будет сгенерирован за вас, однако, вы можете его дополнить так: 
      • Скопировать файлы из своего проекта в Docker-образ.
        Например, команда ADD model model скопирует файлы из папки model (первый аргумент) в вашем проекте в директорию /model/ (первый слэш важен!) в Docker-образе (второй аргумент). Команду стоит прописать вне блока RUN\. 
      • Добавить установку необходимых вам библиотек с помощью команды pip install … &&\ (прописать это нужно внутри блока RUN\). 
  2. Затем нужно создать реестр для хранения Docker-образов (если у вас его еще нет). Для этого переходим в рабочий каталог в облаке, выбираем сервис Container Registry и там создаем реестр.
  3. Далее нужно провести аутентификацию в Container Registry (если вы этого еще не сделали). Это можно сделать разными способами, которые описаны в документации. Мы воспользуемся способом аутентификации через сервисный аккаунт с помощью авторизованных ключей. Не забудьте его создать дополнительно, если решите использовать тот же способ. Процесс аутентификации достаточно прост:
    • Сначала нужно сгенерировать ключи с помощью Yandex.Cloud CLI:
      yc iam key create --service-account-name <service-account-name> -o key.json
    • Затем провести авторизацию с помощью этих ключей (Docker должен быть запущен):
      cat key.json | docker login --username json_key --password-stdin cr.yandex
    • Далее нужно записать содержимое файла key.json в “секрет проекта”.
    Полезные ссылки по работе с YC CLI и сервисными аккаунтами:
    Работа с командной строкой
    Работа с сервисными аккаунтами
     
  4. После этого можно запушить Docker-образ в реестр. Для этого нужно выполнить следующую команду в ноутбуке (да-да, решетка в начале, все верно):
    #!:docker-publish <datasphere-image-name>:<datasphere-image-tag> cr.yandex/<cloud-registry-path>:<tag> 
    Где:
    <datasphere-image-name> – Репозиторий, указанный при создании Docker-образа 
    <datasphere-image-tag> – Тег, указанный при создании Docker-образа 
    <cloud-registry-path> – Идентификатор реестра, который можно посмотреть в Container Registry
    <tag> – Тег, который вы можете придумать сами
  5. Вам предложат ввести Registry username и Secret name of password. Если вы проводили аутентификацию тем способом, что был описан выше, то сначала нужно ввести json_key, а затем название секрета, в котором было сохранено содержимое файла key.json. После этого в реестре должен появиться ваш загруженный образ.
  6. Остается создать ноду из ячейки с кодом.
    Важные моменты:
    • Прогоните все необходимые ячейки с кодом перед сохранением контрольной точки. 

    • Если вам нужна определенная конфигурация машины, пропишите это в ячейке, которую будете деплоить, например #!g1.1 (иначе будет использоваться дефолтная конфигурация c1.4). 
    • Для нашего примера при создании ноды в Output variables необходимо указать name: output_data, type: dict. Аналогично для Input variables. 
    • Необходимо указать Kernel Docker Image 
      • Image path — путь до загруженного в реестр образа (можно нажать на тег образа в реестре, и путь будет скопирован). 
      • Username и Password secret — то, что мы указывали, когда пушили образ в реестр. 
    • После создания у ноды должен быть статус Active, но придется немного подождать, пока можно будет к ней обращаться — в ноде должен быть указан инстанс со статусом HEALTHY (или несколько статусов, если вы выбрали такую конфигурацию). 

Обращение к модели

  1. Обращаться к ноде можно с помощью IAM-токена или API-ключа. Пример кода для обращения к ноде можно посмотреть в GitHub Стоит отметить, что в функции call_node есть небольшой дефект: переменная data должна заполняться следующим образом:
    data = {
        "folder_id": folder_id,
        "node_id": node_id,
        "input": {'input_data': input_params}
    }
    Значение для заполнения переменной node_id можно найти сразу после имени ноды, если выбрать ее из списка на вкладке Nodes. folder_id — идентификатор каталога, в котором был создан проект.
  2. Если вам не надо менять окружение, загруженное в Docker-образ, то вы можете задеплоить другой код, т. е. повторно выполнить только пункт 6 предыдущего раздела.
 Нет комментариев    850   2021   yandex

Clickhouse в качестве consumer для Amazon MSK

Время чтения текста – 6 минут

Disclaimer: заметка носит технический характер, поэтому может быть интересна меньшему числу лиц с бизнес-бэкграундом.

В этом блоге еще ни разу не затрагивалась тема Clickhouse, одной из самых быстрых баз данных от компании Яндекс. Краткая справка без деталей: Clickhouse — наиболее эффективно написанная СУБД колоночного типа с точки зрения программного кода, информация о СУБД довольно подробно описана в документации и во множестве видео на Youtube (раз, два, три).

В своей практике последние четыре года я использовал Clickhouse в качестве аналитика и эксперта по построению аналитической отчетности. В основном для решения задачи визуализации отчетности / отчетов с параметрами / дашбордов использовался Redash как наиболее удобный интерфейс для доступа к данным Clickhouse.
Однако совсем недавно в Looker, о котором я рассказывал ранее, появилась возможность подключить Clickhouse в качестве источника данных. Следует заметить, что подключение к Clickhouse в Tableau существует уже довольно давно.

Архитектура аналитического сервиса, в основе которого лежит Clickhouse, в основном облачная. И в рассматриваемой задаче было именно так. Предположим, у вас существует выделенный instance EC2 в Amazon (на который вы установили Clickhouse) и отдельный Kafka-кластер (решение Amazon MSK).

Задача: подключить Clickhouse в качестве consumer для получения информации с брокеров вашего кластера Kafka. На самом деле, в документации на сайте Amazon MSK довольно подробно описано как именно подключаться к кластеру Kafka, не буду дублировать эту информацию. В моем случае гайд помог: топики создавались продюсером с машины, на которой установлен Clickhouse и с неё читались консюмером.

Но возникла проблема: при подключении Clickhouse к Kafka в качестве консюмера, происходила следующая ошибка:

020.02.02 18:01:56.209132 [ 46 ] {e7124cd5-2144-4b1d-bd49-8a410cdbd607} <Error> executeQuery: std::exception. Code: 1001, type: cppkafka::HandleException, e.what() = Local: Timed out, version = 20.1.2.4 (official build) (from 127.0.0.1:46586) (in query: SELECT * FROM events), Stack trace (when copying this message, always include the lines below):

Продолжительное время я искал информацию в документации Clickhouse о том, что может вызывать эту ошибку, но не смог ничего найти. Следующей мыслью стала проверка работы локального брокера Kafka с той же машины. Установил клиент Kafka, подключил Clickhouse, отправил данные в топик и Clickhouse с легкостью их прочитал, т. е. консюмер Clickhouse работает с локальным брокером, а значит и вовсе работает.

Поговорив со всеми своими знакомыми экспертами в области инфраструктуры и Clickhouse (Вася, Макс, привет!), с ходу мы не смогли определить в чем проблема. Проверили firewall, настройки сети, все было открыто. Подтверждалось также тем, что с локальной машины можно было отправить в топик удаленного брокера Kafka сообщения командой bin/kafka-console-producer.sh и прочитать оттуда же bin/kafka-console-consumer.sh.

Затем мне пришла в голову мысль обратиться к главному гуру и разработчику Clickhouse — Алексею Миловидову. Алексей с радостью постарался ответить на возникшие вопросы и предложил ряд гипотез, которые мы проверили (трассировку сетевых подключений и т. п.), однако и после более низкоуровневого аудита проблему локализовать не удалось. Тогда Алексей посоветовал обратиться к Михаилу Филимонову из компании Altinity. Михаил оказался очень отзывчивым экспертом и одну за другой предлагал гипотезы для проверки (параллельно подсказывая как именно будет лучше их проверить).

В итоге в ходе совместных усилий мы обнаружили, что проблема возникает у библиотеки librdkafka, так как другой пакет kafkacat, который использует эту же библиотеку отваливается от подключения к брокеру с той же проблемой (Local: timed out).

После изучения подключения через bin/kafka-console-consumer.sh и параметров подключения, Михаил посоветовал добавить такую строку в /etc/clickhouse-server/config.xml:

<kafka><security_protocol>ssl</security_protocol></kafka>

И, о чудо! Clickhouse подключился к кластеру и вытянул необходимые данные с брокера.

Надеюсь, этот рецепт и мой опыт позволит вам сэкономить время и силы на изучение похожей проблемы :)