Несмотря на то, что данных сейчас много почти везде, аналитические БД все еще довольно экзотичны. Их плохо знают и еще хуже умеют эффективно использовать. Многие продолжают "есть кактус" с MySQL или PostgreSQL, которые спроектированы под другие сценарии, мучиться с NoSQL или переплачивать за коммерческие решения. ClickHouse меняет правила игры и значительно снижает порог вхождения в мир аналитических DBMS. Доклад с BackEnd Conf 2018г и он опубликован с разрешения докладчика. 
Кто я такой и почему я рассказываю о ClickHouse? Я директор по разработке в компании LifeStreet, которая использует ClickHouse. Кроме того, я основатель Altinity. Это партнер Яндекса, который продвигает ClickHouse и помогает Яндексу сделать ClickHouse более успешным. Также готов делиться знаниями о ClickHouse.   И еще я не брат Пети Зайцева. Меня часто об этом спрашивают. Нет, мы не братья.  «Всем известно», что ClickHouse: Чуть менее известно, в каких компаниях и как он используется.   Я вам расскажу, для чего, где и как используется ClickHouse, кроме Яндекса.  Расскажу, как конкретные задачи решаются при помощи ClickHouse в разных компаниях, какие средства ClickHouse вы можете использовать для своих задач, и как они были использованы в разных компаниях. Я подобрал три примера, которые показывают ClickHouse с разных сторон. Я думаю, это будет интересно.  Первый вопрос: «Зачем нужен ClickHouse?». Вроде бы вопрос достаточно очевидный, но ответов на него больше, чем один.   В ClickHouse этих проблем нет.   Где используется ClickHouse сейчас? Кроме Яндекса ClickHouse используется в куче разных бизнесов и компаний.   Причем размер не имеет значения. Есть много компаний, которые используют один маленький сервер. И он им позволяет решить их проблемы. И еще больше компаний используют большие кластера из многих серверов или десятков серверов.  И если смотреть за рекордами, то:  Географически – это тоже много. Вот эта карта показывает heatmap, где ClickHouse используется в мире. Тут ярко выделяется Россия, Китай, Америка. Европейских стран мало. И можно выделить 4 кластера. Это сравнительный анализ, тут не надо искать абсолютных цифр. Это анализ посетителей, которые читают англоязычные материалы на сайте Altinity, потому что русскоязычных там нет. И Россия, Украина, Беларусь, т. е. русскоязычная часть сообщества, это самые многочисленные пользователи. Потом идет США и Канада. Очень сильно догоняет Китай. Там полгода назад Китая почти не было, сейчас Китай уже обогнал Европу и продолжает расти. Старушка Европа тоже не отстает, причем лидер использования ClickHouse – это, как ни странно, Франция.   Зачем я все это рассказываю? Для того чтобы показать, что ClickHouse становится стандартным решением для анализа больших данных и уже очень много где используется. Если вы его используете, вы в правильном тренде. Если вы еще его не используете, то можно не бояться, что вы останетесь одни и вам никто не поможет, поэтому что уже многие этим занимаются.  Это примеры реального использования ClickHouse в нескольких компаниях.    Компания прошла долгий и тернистый путь. И я о нем рассказывал на HighLoad. Сначала LifeStreet перешла с MySQL (с небольшой остановкой на Oracle) в Vertica. И можно об этом найти рассказ.  И все было очень хорошо, но достаточно быстро стало понятно, что данные растут и Vertica – это дорого. Поэтому искались различные альтернативы. Некоторые из них здесь перечислены. И на самом деле мы сделали proof of concept или иногда performance testing почти всех баз данных, которые с 13-го по 16-ый год были доступны на рынке и примерно подходили по функциональности. И о части из них я тоже рассказал на HighLoad.  Стояла задача – мигрировать с Vertica в первую очередь, потому что данные росли. И росли они экспоненциально несколько лет. Потом они вышли на полку, но тем не менее. И прогнозируя этот рост, требования бизнеса на объем данных, по которым нужно делать какую-то аналитику, было понятно, что скоро пойдет разговор о петабайтах. А за петабайты платить уже очень дорого, поэтому искали альтернативу, куда уходить.   Куда уходить? И долгое время было совершенно не понятно, куда уходить, потому что с одной стороны есть коммерческие базы данных, они вроде бы неплохо работают. Некоторые работают почти так же хорошо, как Vertica, некоторые похуже. Но они все дорогие, ничего дешевле и лучше найти не удавалось.  С другой стороны, есть open source решения, которых не очень много, т. е. для аналитики их можно пересчитать по пальцам. И они бесплатные или дешевые, но работают медленно. И в них часто не хватает нужной и полезной функциональности. И того, чтобы совмещало то хорошее, что есть в коммерческих базах данных и все то бесплатное, что есть в open source, — ничего не было.   Ничего не было до тех пор, пока неожиданно Яндекс не вытащил, как кролика фокусник из шапки, ClickHouse. И это было решение неожиданное, до сих пор задают вопрос: «Зачем?», но тем не менее.   И сразу летом 2016-го года мы стали смотреть, что такое ClickHouse. И оказалось, что он иногда может быть быстрее Vertica. Мы тестировали разные сценарии на разных запросах. И если запрос использовал только одну таблицу, т. е. без всяких джойны (join), то ClickHouse был быстрее Vertica в два раза.  Я не поленился и посмотрел еще тесты Яндекса на днях. Там то же самое: в два раза ClickHouse быстрее Vertica, поэтому они часто об этом говорят.  Но если в запросах есть джойны (join), то все получается не очень однозначно. И ClickHouse может быть медленнее Vertica в два раза. А если чуть-чуть запрос подправить и переписать, то примерно равные. Неплохо. И бесплатно.   И получив результаты тестов, и посмотрев с разных сторон на это, LifeStreet поехал на ClickHouse.  Это 16-ый год, напоминаю. Это было как в анекдоте про мышей, которые плакали и кололись, но продолжали есть кактус. И об этом было подробно рассказано, есть об этом видео и т. д.   Я поэтому не буду подробно об этом рассказывать, расскажу только о результатах и о нескольких интересных вещах, о которых я не рассказывал тогда.  Результаты – это:  Сейчас я перехожу к практическим вещам в данном примере.  Типичный OLAP-запрос – это select. Часть колонок идет в group by, часть колонок идет в агрегатные функции. Есть where, которую можно представить как срез куба. Весь group by можно представить как проекцию. И поэтому это называется многомерным анализом данных.   И часто это моделируется в виде star-схемы, когда есть центральный факт и характеристики этого факта по сторонам, по лучам.   И с точки зрения физического дизайна, того, как это ложится на таблицу, то обычно делают нормализованное представление. Можете денормализовать, но это дорого по диску и не очень эффективно по запросам. Поэтому обычно делают нормализованное представление, т. е. таблица фактов и много-много таблиц измерений.  Но в ClickHouse это работает плохо. Есть две причины:  И выход из этого в ClickHouse есть. даже целых два:    Это не для красного словца. Это очень мощная функциональность, которая позволяет делать многие вещи очень просто и элегантно.   Типичные примеры, которые помогают решать массивы. Эти примеры простые и достаточно наглядные: Все эти задачи можно решить без массивов. Теги можно в какую-то строчку положить и регулярным выражением выбирать или в отдельную таблицу, но тогда придется делать джойны (join).  А в ClickHouse ничего не нужно делать, достаточно описать массив string для хештегов или сделать вложенную структуру для систем типа key-value. Вложенная структура – это, может быть, не самое удачное название. Это два массива, которые имеют общую часть в названии и некоторые связанные характеристики.  И по тегу искать очень просто. Есть функция has, которая проверяет, что в массиве есть элемент. Все, нашли все записи, которые относятся к нашей конференции. Поиск по subid чуть-чуть посложнее. Надо нам сначала найти индекс ключа, а потом уже взять элемент с этим индексом и проверить, что это значение такое, какое нам нужно. Но тем не менее очень просто и компактно. Регулярное выражение, которое вы бы захотели написать, если бы вы все это хранили в одной строчке, оно было бы, во-первых, корявым. А, во-вторых, работало гораздо дольше, чем два массива.   Другой пример. У вас есть массив, в котором вы храните ID. И вы можете перевести их в имена. Функция arrayMap. Это типичная лямбда-функция. Вы передаете туда лямбда-выражения. И она каждому ID из словаря вытаскивает значение имени. Аналогичным образом можно сделать и поиск. Передается функция предикат, которая проверяет чему соответствуют элементы.   Вот эти вещи сильно упрощают схему и решают кучу проблем.  Но следующая проблема, с которой мы столкнулись и о которой я хотел бы упомянуть, это эффективные запросы.  И даже в более простых случаях тоже иногда следует выполнять работу планировщика и запросы чуть-чуть переписывать.   Вот пример. В левой части запрос, который показывает топ-5 стран. И он выполняется 2,5 секунды, по-моему. А в правой части тот же запрос, но чуть-чуть переписанный. Мы вместо того, чтобы группировать по строке, стали группировать по ключу (int). И это быстрее. А потом мы к результату подключили словарь. Вместо 2,5 секунд запрос выполняется 1,5 секунды. Это хорошо.   Похожий пример с переписыванием фильтров. Здесь запрос по России. Он выполняется 5 секунд. Если мы его перепишем таким образом, что будем сравнивать снова не строку, а числа с каким-то сетом тех ключей, которые относятся к России, то это будет гораздо быстрее.   Таких трюков много. И они позволяют существенно ускорить запросы, которые вам кажется, что уже работают быстро, или, наоборот, работают медленно. Их можно сделать еще быстрее.  Есть еще другие техники, а не только те, которые я продемонстрировал. И все они позволяют иногда существенно ускорить выполнение запросов.  Переходим к следующему примеру. Компания Х из США. Что она делает?  Была задача:   В чем состоит сценарий? Обычный посетитель заходит на сайт, например, 20 раз в месяц с разных объявлений или просто так иногда приходит без всяких объявлений, потому что помнит этот сайт. Смотрит какие-то продукты, кладет их в корзину, вынимает их из корзины. И, в конце концов, что-то покупает.  Резонные вопросы: «Кому надо заплатить за рекламу, если надо?» и «Какая реклама на него повлияла, если повлияла?». Т. е. почему он купил и как сделать так, чтобы люди, похожие на этого человека, тоже покупали? Для того чтобы эту задачу решить, нужно связывать события, которые происходят на веб-сайте правильным образом, т. е. как-то между ними выстраивать связь. Потом их передавать для анализа в DWH. И на основании этого анализа строить модели, кому и какую рекламу показывать.  Рекламная транзакция – это набор связанных событий пользователя, которые начинаются от показа объявления, дальше что-то происходит, потом, может быть, покупка, а потом могут быть покупки в покупке. Например, если это мобильное приложение или мобильная игра, то обычно установка приложения бесплатно происходит, а если там что-то дальше делается, то на это могут потребоваться денежки. И чем больше человек потратит в приложении, тем он ценнее. Но для этого надо все связать.   Есть много моделей связывания.  Самые популярные – это:  И как это все работало изначально? Был Runtime и Cassandra. Cassandra использовалась как transaction storage, т. е. в ней хранились все связанные транзакции. И когда приходит какое-то событие в Runtime, например, показ какой-то страницы или что-то еще, то делался запрос в Cassandra – есть такой человек или нет. Потом доставались транзакции, которые к нему относятся. И производилось связывание. И если повезло, что в запросе есть transaction id, то это легко. Но обычно не везет. Поэтому надо было найти последнюю транзакцию или транзакцию с последним кликом и т. д.  И это все очень хорошо работало, пока связывание было к последнему клику. Потому что кликов, скажем, 10 миллионов в день, 300 миллионов в месяц, если на месяц ставить окно. И поскольку в Cassandra это должно быть все в памяти для того, чтобы работало быстро, потому что требуется Runtime ответить быстро, то требовалось примерно 10-15 серверов.  А когда захотели к показу привязывать транзакцию, то сразу получилось не так весело. А почему? Видно, что в 30 раз больше событий надо хранить. И, соответственно, нужно в 30 раз больше серверов. И получается, что это какая-то астрономическая цифра. Держать до 500 серверов для того, чтобы делать связывание, притом, что в Runtime серверов существенно меньше, то это какая-то неправильная цифра. И стали думать, что делать.   И вышли на ClickHouse. А как это делать на ClickHouse? На первый взгляд кажется, что это набор антипаттернов.  Т. е. набор антипаттернов.   Но тем не менее получилось сделать систему, которая очень хороша работала.  Что было сделано? Появился ClickHouse, в который забрасывались логи, разбитые на записи. Появился attributed сервис, который получал из ClickHouse логи. После этого для каждой записи по visit id получал транзакции, которые могли быть еще не дообработанные и плюс снапшоты, т. е. транзакции уже связанные, а именно результат предыдущей работы. Из них уже делал логику, выбирал правильную транзакцию, подсоединял новые события. Снова записывал в лог. Лог уходил обратно в ClickHouse, т. е. это постоянно цикличная система. И кроме того, уходил в DWH, чтобы там это анализировать.  Именно в таком виде это работало не очень хорошо. И чтобы ClickHouse было проще, когда шел запрос по visit id, то группировали эти запросы в блоки по 1 000-2 000 visit id и вытаскивали для 1 000-2 000 человек все транзакции. И тогда все это заработало.  Если посмотреть вовнутрь ClickHouse, то там всего 3 основных таблиц, которые все это обслуживают.  Первая таблица, в которую заливаются логи, причем логи заливаются практически без обработки. Вторая таблица. Через materialized view из этих логов выкусывались, которые еще не attributed ивенты, т. е. несвязанные. И через materialized view из этих логов вытаскивались транзакции для построения снапшота. Т. е. специальным materialized view строил снапшот, а именно последнее накопленное состояние транзакции.   Вот здесь написан текст на SQL. Я бы хотел прокомментировать в нем несколько важных вещей.  Первая важная вещь – это возможность в ClickHouse из json вытаскивать колонки, поля. Т. е. в ClickHouse есть некоторые методы для работы с json. Они очень-очень примитивные.  visitParamExtractInt позволяет из json вытаскивать атрибуты, т. е. первое попадание срабатывает. И таким образом можно вытащить transaction id или visit id. Это раз.  Второе – здесь использовано хитрое materialized поле. Что это значит? Это значит, что вы его в таблицу вставить не можете, т. е. оно не вставляется, оно вычисляется и хранится при вставке. При вставке ClickHouse делает за вас работу. И уже вытаскивается из json то, что вам потом понадобится. В данном случае materialized view – это для необработанных строк. И как раз используется первая таблица с практически сырыми логами. И что делает? Во-первых, меняет сортировку, т. е. сортировка теперь идет по visit id, потому что нам нужно быстро вытаскивать именно по конкретному человеку его транзакцию.  Вторая важная вещь – это index_granularity. Если вы видели MergeTree, то обычно по дефолту 8 192 стоит index_granularity. Что это такое? Это параметр разреженности индекса. В ClickHouse индекс разреженный, он никогда не индексирует каждую запись. Он это делает через каждые 8 192. И это хорошо, когда требуется много данных подсчитать, но плохо, когда немножко, потому что большой overhead. И если уменьшать index granularity, то мы уменьшаем overhead. Уменьшить до единицы нельзя, потому что может памяти не хватить. Индекс всегда в памяти хранится.   А снапшот использует еще некоторые интересные функции ClickHouse. Во-первых, это AggregatingMergeTree. И в AggregatingMergeTree хранится argMax, т. е. это состояние транзакции, соответствующее последнему timestamp. Транзакции все время новые генерируются для данного посетителя. И в самое последнее состояние этой транзакции мы добавили ивент и у нас появилось новое состояние. Оно снова попало в ClickHouse. И через argMax в этом материализованном представлении мы всегда можем получить актуальное состояние.   И последний пример – это финансовая компания Y, которая анализировала корреляции изменений котировок акций.  И задача стояла такая: И нужно было посчитать корреляцию изменений.   Здесь есть две акции и их котировки. Если одна идет вверх, и вторая идет вверх, то это положительная корреляция, т. е. одна растет, и вторая растет. Если одна идет вверх, как в конце графика, а вторая вниз, то это отрицательная корреляция, т. е. когда одна растет, другая падает.  Анализируя эти взаимные изменения можно делать предсказания на финансовом рынке.   Но задача сложная. Что для этого делается? У нас есть 100 миллиардов записей, в которых есть: время, акция и цена. Нам нужно посчитать сначала 100 миллиардов раз runningDifference от алгоритма цены. RunningDifference – это функция в ClickHouse, которая разницу между двумя строчками последовательно вычисляет.  А после этого надо посчитать корреляцию, причем корреляцию надо посчитать для каждой пары. Для 5 000 акций пар 12,5 миллионов. И это много, т. е. 12,5 раз надо вычислять вот такую функцию корреляции.  И если кто-то забыл, то ͞x и ͞y – это мат. ожидание по выборке. Т. е. нужно не только корни и суммы посчитать, а еще внутри этих сумм еще одни суммы. Кучу-кучу вычислений нужно произвести 12,5 миллионов раз, да еще и сгруппировать по часам надо. А часов у нас тоже немало. И успеть надо за 60 секунд. Это шутка.   Надо было успеть хоть как-то, потому что все это работало очень-очень медленно, прежде, чем пришел ClickHouse.  Они пробовали на Hadoop это посчитать, на Spark, на Greenplum. И все это было очень медленно или дорого. Т. е. можно было как-то посчитать, но потом это было дорого.   А потом пришел ClickHouse и все стало гораздо лучше.  Напоминаю, проблема у нас с локальностью данных, потому корреляции нельзя локализовать. Мы не можем сложить часть данных на один сервер, часть на другой и посчитать, у нас должны быть все данные везде.  Что они сделали? Изначально данные локализованные. На каждом из серверов хранятся данные по прайсингу определенного набора акций. И они не пересекаются. Поэтому можно параллельно и независимо посчитать logReturn, все это происходит пока параллельно и распределено.  Дальше решили эти данные уменьшить, при этом не потеряв выразительности. Уменьшить с помощью массивов, т. е. для каждого отрезка времени сделать массив акций и массив цен. Таким образом это занимает гораздо меньше места данные. И с ними несколько удобнее работать. Это почти параллельные операции, т. е. мы параллельно частично считаем и потом записываем на сервер.  После этого это можно среплицировать. Буковка «r» означает, что эти данные мы среплицировали. Т. е. у нас на всех трех серверах одинаковые данные – вот эти массивы.  И дальше специальным скриптом из этого набора 12,5 миллионов корреляций, которые надо посчитать, можно сделать пакеты. Т. е. 2 500 задач по 5 000 пар корреляций. И эту задачу вычислять на конкретном ClickHouse-сервере. Все данные у него есть, потому что данные одинаковые и он может их последовательно вычислять.   Еще раз, как это выглядит. Сначала у нас все данные есть в такой структуре: время, акции, цена. Потом мы посчитали logReturn, т. е. данные той же структуры, только вместо цены у нас уже logReturn. Потом их переделали, т. е. у нас получились время и groupArray по акциям и по прайсам. Среплицировали. И после этого сгенерировали кучу задач и скормили ClickHouse, чтобы он их считал. И это работает.   На proof of concept задача – это была подзадача, т. е. взяли меньше данных. И всего на трех серверах. Первые эти два этапа: вычисление Log_return и заворачивание в массивы заняли примерно по часу.  А вычисление корреляции где-то 50 часов. Но 50 часов – это мало, потому что раньше у них это работало неделями. Это был большой успех. И если посчитать, то 70 раз в секунду на этом кластере все считалось. Но самое главное, что эта система практически без узких мест, т. е. она масштабируется практически линейно. И они это проверили. Успешно ее отмасштабировали.    И резюмируя это небольшое выступление, можно сказать, что ClickHouse сейчас твердо занял территорию и коммерческих баз данных, и open source баз данных, т. е. именно для аналитики. Он замечательно вписался в этот ландшафт. И более того, он потихонечку начинает других вытеснять, потому что, когда есть ClickHouse, то вам не нужен InfiniDB. Вертика, может быть, скоро будет не нужна, если они сделают нормальную поддержку SQL. Пользуйтесь!  -Спасибо за доклад! Очень интересно! Были ли какие-то сравнения с Apache Phoenix? -Нет, я не слышал, чтобы кто-то сравнивал. Мы и Яндекс стараемся отслеживать все сравнения ClickHouse с разными базами данных. Потому что если вдруг что-то оказывается быстрее ClickHouse, то Леша Миловидов не может спать по ночам и начинает быстренько его ускорять. Я не слышал о таком сравнении.  (Алексей Миловидов) Apache Phoenix – это SQL-движок на Hbase. Hbase в основном предназначен для сценария работ типа key-value. Там в каждой строчке может быть произвольное количество столбцов с произвольными именами. Это можно сказать про такие системы как Hbase, Cassandra. И на них именно тяжелые аналитические запросы нормально работать не будут. Или вы можете подумать, что они работают нормально, если у вас не было никакого опыта работы с ClickHouse. Спасибо Добрый день! Я уже довольно много интересуюсь этой темой, потому что у меня подсистема аналитическая. Но когда я смотрю на ClickHouse, то у меня возникает ощущение, что ClickHouse очень хорошо подходит для анализа ивентов, mutable. И если мне нужно анализировать много бизнес-данных с кучей больших таблиц, то ClickHouse, насколько я понимаю, мне не очень подходит? Особенно, если они меняются. Правильно ли это или есть примеры, которые могут опровергнуть это? Это правильно. И это правда про большинство специализированных аналитических баз данных. Они заточены под то, что есть одна или несколько больших таблиц, которые mutable, и под много маленьких, которые медленно изменяются. Т. е. ClickHouse не как Oracle, куда можно положить все и строить какие-то очень сложные запросы. Для того чтобы ClickHouse эффективно использовать, надо схему выстраивать тем образом, который в ClickHouse хорошо работает. Т. е. избегать излишней нормализации, использовать словари, стараться делать меньше длинных связей. И если схему таким образом выстроить, то тогда аналогичные бизнес-задачи на ClickHouse могут быть решены гораздо более эффективно, чем традиционной реляционной базе данных.  Спасибо за доклад! У меня вопрос по последнему финансовому кейсу. У них была аналитика. Надо было сравнить, как идут вверх-вниз. И я так понимаю, что вы систему построили именно под эту аналитику? Если им завтра, допустим, понадобится, какой-то другой отчет по этим данным, нужно заново схему строить и загружать данные? Т. е. делать какую-то предобработку, чтобы получить запрос? Конечно, это использование ClickHouse для вполне конкретной задачи. Она более традиционно могла бы быть решена в рамках Hadoop. Для Hadoop – это идеальная задача. Но на Hadoop это очень медленно. И моя цель – это продемонстрировать то, что на ClickHouse можно решать задачи, которые обычно решаются совершенно другими средствами, но при этом сделать гораздо эффективнее. Это под конкретную задачу заточено. Понятно, что если есть задача чем-то похожая, то можно ее похожим образом решать.  Понятно. Вы сказали, что 50 часов обрабатывалось. Это начиная с самого начала, когда загрузили данные или получили результаты? Да-да. Хорошо, спасибо большое. Это на 3-х серверном кластере.  Приветствую! Спасибо за доклад! Все очень интересно. Я немножко не про функционал спрошу, а про использование ClickHouse с точки зрения стабильности. Т. е. случались ли у вас какие-то, приходилось ли восстанавливать? Как при этом себя ведет ClickHouse? И случалось ли так, что у вас вылетала и реплика в том числе? Мы, допустим, у ClickHouse сталкивались с проблемой, когда он вылезает все-таки за свой лимит и падает. Конечно, идеальных систем нет. И у ClickHouse тоже есть свои проблемы. Но вы слышали о том, чтобы Яндекс.Метрика долго не работала? Наверное, нет. Она работает надежно где-то с 2012-2013-го года на ClickHouse. Про мой опыт я тоже могу сказать. У нас никогда не бывало полных отказов. Какие-то частичные вещи могли случаться, но они никогда не были критичными настолько, чтобы серьезно повлиять на бизнес. Никогда такого не было. ClickHouse – достаточно надежен и не падает случайным образом. Можно об этом не беспокоиться. Это не сырая вещь. Это доказано многими компаниями.  Здравствуйте! Вы сказали, что нужно сразу хорошо продумать схему данных. А если это случилось? У меня данные льются-льются. Проходит полгода, и я понимаю, что так жить нельзя, мне надо перезаливать данные и что-то с ними делать.  Это зависит, конечно, от вашей системы. Есть несколько способов сделать это практически без остановки. Например, вы можете создать Materialized View, в котором сделать другую структуру данных, если ее можно однозначно смапировать. Т. е. если она допускает мапирование средствами ClickHouse, т. е. extract каких-то вещей, поменять primary key, поменять партиционирование, то можно сделать Materialized View. Туда ваши старые данные переписать, новые будут писаться автоматически. А потом просто переключиться на использование Materialized View, потом переключить запись и старую таблицу убить. Это вообще без остановки способ.  Спасибо. DevOps-инженер