Привет! Я хочу поговорить о том, почему крупные технологические корпорации одержимы созданием собственных решений для своей инфраструктуры. Ответ кажется очевидным: это не что иное, как синдром НИЗ. Но этот ответ далеко не полный, не говоря уже об объективном.
Я технический директор команды разработки платформ Яндекса, и наша цель — помочь инженерам выстроить весь цикл разработки, от написания кода до эксплуатации сервисов, чтобы сделать его более эффективным. Сюда входит оптимизация процессов: мы не только разрабатываем предложения как услугу, но и помогаем их внедрять внутри компании. Это работает в масштабах Яндекса: нашими услугами пользуются тысячи разработчиков по всей компании.
Для решения проблемы мы часто разрабатываем собственные инструменты, а не внедряем готовые. Например, еще будучи программистом в команде, я работал над системой количественного мониторинга на C++ и Python и помогал масштабировать ее до десятков миллиардов обрабатываемых метрик. Итак, исходя из собственного опыта, я знаю, какие мотивации и пути развития приводят к появлению in-house инструментов: ниже я попытаюсь выявить фундаментальные причины их создания на примерах наших решений.
Постановка задачи. Цель нашего внутреннего Runtime Cloud (RTC) — предоставить внутренним пользователям простые инструменты развертывания и управления трафиком. Пользователи РТК — это те же инженеры, которые разрабатывают сервисы Яндекса. И им нужно где-то запускать десятки тысяч созданных ими приложений, отправлять туда пользовательские запросы, балансировать нагрузку, разбираться с инцидентами в том числе.
Потребность во внутреннем облаке возникла в начале 2010-х годов, когда количество сервисов исчислялось уже сотнями, а общее количество выделяемых ядер росло на десятки процентов в год. Наличие выделенных серверов для каждой службы стало непомерно дорогим, и нам потребовались инструменты, которые позволили бы нам запускать приложения из нескольких служб на одном сервере. Изначально у нас было несколько требований к этим инструментам:
По сути, нам нужен был Kubernetes (и со временем RTC подошел очень близко). Но вот в чем загвоздка: K8s был анонсирован только в 2014 году. Apache Mesos существовал в то время, но находился в зачаточном состоянии.
Реализация основных функций. Мы начали решать задачу с своеобразного MVP — простого набора инструментов, который больше напоминал набор строительных блоков, автоматизирующих рутинные действия, например:
Со временем стало возможным собрать из этих строительных блоков полноценный граф компоновки сервиса (аналогично непрерывной доставке). После определенного количества итераций в 2013 году появилась Nanny — система управления работающими в РТЦ сервисами.
Еще одним фундаментальным аспектом Nanny стала реализация изоляции приложений на основе потребления ресурсов. Изначально мы запускали приложения из разных сервисов без изоляции ресурсов, что приводило к большому количеству операционных проблем и инцидентов.
На тот момент единственными готовыми решениями были LXC, который к тому времени прекратил разработку, и Docker, который не мог использовать только IPv6 и перезапускал все контейнеры при обновлении dockerd, что делало невозможным обновление dockerd без ущерба для пользователя. В результате мы начали развивать нашу
Решение проблем с использованием. В то время управление ресурсами во внутреннем облаке осуществлялось посредством фиксации в репозитории. Однако это замедляло развитие Яндекса и вступало в противоречие с задачей увеличения загрузки: для ее решения нам нужно было разместить нашу систему уменьшения карт в облаках, а именно
Чтобы перенести YTsaurus в RTC, требовалась возможность управлять модулями динамически, а не посредством фиксации в репозитории. Поэтому в 2018 году мы создали
Новые боли роста. За тот же период k8s превратился в гораздо более зрелое решение, став одним из сервисов AWS в 2017 году. Но оно по-прежнему не отвечало всем нашим требованиям:
YTsaurus активно использовал возможность создания вложенных контейнеров Porto вместо создания единого планировщика. Конечно, мы могли бы сами добавить поддержку того же двойного стека в k8s. Однако опыт разработки ядра Linux показал, что не все можно отправить в открытый исходный код, и мы стремимся свести отклонение от вышестоящего ядра к минимуму, чтобы упростить обновление до новых версий.
Наше решение сегодня. Архитектура RTC очень похожа на архитектуру Kubernetes. Пользователь декларативно описывает свой сервис в виде некоторой спецификации, описывающей, как запустить указанное приложение и в каких центрах обработки данных. В каждом дата-центре есть своя установка Яндекс Планировщика, который с одной стороны служит базой данных для всех объектов кластера, а с другой — планировщиком подов. На каждом сервере в дата-центре работает агент, который получает спецификации модулей из Яндекс Планировщика и запускает их с помощью нашей собственной системы контейнеризации Porto.
В настоящее время RTC запустила десятки тысяч сервисов, распределив более 5 миллионов ядер на более чем 100 000 серверов. Ежедневно в спецификации услуг вносится более 100 000 изменений.
Планы. Что, если k8s справится с нашим масштабом? Тем более, что экосистема k8s в какой-то момент начала превосходить нас по функциональности. Не лучше ли перейти на k8s и надеяться, что готовые инструменты со временем дадут тот объем, который нам нужен? На практике мы продолжаем оставаться нишевым потребителем k8s, потому что лишь небольшой процент компаний работает в таких больших масштабах, каждая из которых имеет свои собственные облачные решения.
Еще один важный момент, о котором следует помнить, — это проблема миграции. По данным июля 2018 г.
В 2021 году мы прикинули, сколько будет стоить переход с одной системы развертывания на другую при выборе стратегии развития. Переход Яндекса на vanilla k8s будет чрезвычайно дорогостоящей задачей, требующей сотен человеко-лет.
Таким нехитрым образом у нас получилось наше внутреннее облако, от которого мы вряд ли сможем отказаться в ближайшие 5 лет, даже если поставим такую цель.
Что делать с отсутствием внутреннего облачного функционала по сравнению с к8с? На практике наши клиенты могут использовать Managed Kubernetes в Яндекс Облаке. Этот вариант в первую очередь используется для проектов, где необходимо соблюдать строгие требования соответствия — это небольшая доля команд, менее 1%. По указанным выше причинам остальная часть населения не видит особой выгоды в переезде.
При этом мы активно присматриваемся к k8s и думаем, как приблизиться к общепринятым стандартам. Мы уже активно экспериментируем с k8s в некоторых задачах, например облачная загрузка или организация IaaC в масштабе всего Яндекс. В идеале мы хотели бы повторно использовать интерфейс k8s, сохраняя при этом собственную реализацию, максимально адаптированную к нашим потребностям. Остаётся только придумать, как это сделать на практике.
Проблемы и требования к решению . Наш монорепозиторий Arcadia преследует ту же основную цель, что и наше внутреннее облако: предоставить удобные инструменты разработки. В случае репозитория это включает в себя всю экосистему разработки:
Аркадия появилась примерно в то же время, что и внутреннее облако Яндекса. Одной из причин создания монорепозитория стала необходимость повторного использования кода внутри Яндекса. В то время этому препятствовало наличие нескольких систем сборки. Для работы в масштабе всего Яндекса требовалась единая система с поддержкой эффективных распределенных сборок. Он также должен быть стабильным и удобным в использовании.
Реализация единой системы сборки. Наша собственная система сборки ya make дебютировала в 2013 году, когда она предназначалась только для кода C++. Перед созданием мы использовали CMake, но его скорость не позволяла масштабироваться до масштабов монорепозитория. Фирменный ya make работал с Аркадией гораздо быстрее. Других вариантов с открытым исходным кодом, которые могли бы решить нашу проблему, не было: например, Bazel вышел гораздо позже, в 2015 году.
Масштабирование системы контроля версий. Ранее Яндекс использовал SVN в качестве системы контроля версий. Хотя SVN имела большую емкость, она все еще была ограничена и сложна в обслуживании. Более того, мы осознавали, что в конечном итоге столкнёмся с ограничениями возможностей и удобства SVN. Например, эвристика использовалась для реализации возможности загрузки только необходимой части репозитория или выборочной выдачи. В результате в 2016 году мы начали экспериментировать с другими системами контроля версий, помимо SVN.
Mercurial был первым выбором. Но главной проблемой, с которой мы столкнулись, была скорость. Полтора года мы пытались запустить Mercurial в производство, но результаты были неутешительными. Например, нам в конечном итоге пришлось переписать части Mercurial для поддержки FUSE, иначе нам пришлось бы переносить весь репозиторий на ноутбук каждого разработчика.
В конце концов оказалось, что дешевле написать собственное решение с нуля, и в 2019 году появился Arc — новая система контроля версий для пользователей Arcadia с git-подобным UX. В основе Arc лежит FUSE (файловая система в пространстве пользователя), а не выборочное извлечение. Кроме того, YDB действует как масштабируемая база данных, что значительно упрощает работу Arc по сравнению с Mercurial.
Нас часто спрашивают, почему мы не использовали git. Потому что у него также есть ограничения по масштабу и функциональности: если мы импортируем только ствол Arcadia в git, статус git в этом масштабе займет несколько минут. При этом стабильной реализации FUSE, построенной поверх git, не было: VFS для Git больше не разрабатывается, а EdenFS со временем превратили в Sapling, но произошло это гораздо позже.
Текущее состояние решения и планы на будущее. Чтобы начать разработку, внутреннему пользователю просто нужно создать папку в нашем монорепозитории, написать код и рассказать вам, как собрать свое приложение, добавив манифест сборки. В результате пользователь получает запросы на включение, конфигурацию CI и возможность повторно использовать любой код в компании.
По масштабу в данный момент транк содержит 10 миллионов файлов, репозиторий в целом превышает 2 ТиБ, а каждую неделю делается более 30 тысяч коммитов.
В результате в созданной нами экосистеме многие компоненты приходится создавать с нуля. Однако сейчас она движется в сторону соответствия мировым стандартам. Arc, например, поддерживает работу с Git для предопределенного набора проектов.
Так почему же крупным технологическим компаниям приходится изобретать собственные решения и почему их нельзя заменить решениями, которые соответствуют общепринятому стандарту?
Инновации. Крупным корпорациям часто приходится разрабатывать решения проблем, которые станут обычным явлением только в будущем. Именно так могут появиться инновационные решения, способные стать рыночными стандартами.
Не всегда проблема, решаемая компанией, стоит перед кем-то, кроме самой компании. Иногда опыт крупных технологических компаний в решении конкретной проблемы помогает всей отрасли избежать этой проблемы, выбрав совершенно другой путь развития. Не всегда возможно предсказать развитие рынка, и в результате разные примеры запатентованных решений имели совершенно разные результаты.
ClickHouse — пример по-настоящему успешного инновационного проекта, значительно обогатившего сферу онлайн-аналитической обработки (OLAP). Однако это касается не всех проектов. Porto, который начинался как проект с открытым исходным кодом, не смог набрать обороты по ряду причин. Хотя некоторые его возможности, такие как возможность создания вложенных контейнеров, остаются уникальными.
Шкала. Этот пункт в чем-то похож на предыдущий, ведь не каждая компания сталкивается с проблемой масштабируемости. Было время, когда 640 кбайт было более чем достаточно для всех, не так ли?
Фактически экспоненциальный рост нагрузки на систему стал одной из важнейших причин развития Аркадии и внутреннего облака. Именно поэтому были разработаны Arc и Yandex Planner. Arc был создан в ответ на потребность в удобной для пользователя системе контроля версий, которая позволит пользователям без затруднений работать с монорепозиторием, содержащим десятки миллионов файлов в транке. Yandex Planner был создан в ответ на необходимость эффективной работы с кластерами из десятков тысяч узлов и миллионов подов.
Публичные инструменты по-прежнему имеют проблемы с масштабированием (ведь это относительно редкий сценарий, и вкладывать в него зачастую просто невыгодно).
Инерция. Рассмотрим внутренний инструмент, который решает проблему внутри компании. Компания, которая активно использует этот инструмент, будет выделять ресурсы на то, чтобы лучше адаптировать его к своим потребностям, в конечном итоге превратив его в узкоспециализированный инструмент. Этот процесс может длиться годами.
Теперь рассмотрим возможность того, что в какой-то момент появится общепринятый стандарт решения этой конкретной проблемы. В этом случае специализация по-прежнему может быть важным фактором при выборе собственного решения. Рассмотрим системы сборки. Мы в Аркадии используем ya make, хотя есть Bazel от Google. Концептуально они схожи, но если вникнуть в детали, многие важные сценарии реализуются по-разному, поскольку шаблоны нагрузки для каждой рабочей нагрузки могут существенно различаться. В результате уже затраченные ресурсы почти наверняка придется реинвестировать для адаптации нового общепринятого стандарта.
Миграции. Если в предыдущем разделе был рассмотрен вопрос адаптации проекта под пользователей, то теперь займемся вопросом миграции самих пользователей. На мой взгляд, миграцию следует назвать следующей по значимости проблемой в сфере технологий после названия. Если мы предположим, что у нас уже есть собственный инструмент компании и мы хотим заменить его стандартизированным, нам неизбежно потребуется миграция.
Мы знаем множество примеров миграций из нашего опыта разработки внутреннего облака. Крупномасштабные миграции требуют времени, поэтому оба инструмента должны поддерживаться одновременно в течение продолжительных периодов времени. Если в этом процессе участвует большое количество пользователей, проблемы управления неизбежны. Конечно, стоит попробовать выполнить миграцию без участия пользователя, но это не всегда возможно.
Непрерывность бизнеса. Честно говоря, в последнее время этот момент приобрел достаточное значение. Раньше гораздо меньшее количество компаний относилось к этому серьезно из-за опасений по поводу привязки к поставщику. Доверять критические процессы поставщику, который может прекратить сотрудничество в любой момент, рискованно. JetBrains является ярким примером этого, ограничив использование своих IDE определенными компаниями. Еще один показательный пример — Github Enterprise, который начал блокировать учетные записи российских пользователей.
Внутренние решения обычно невосприимчивы к этой проблеме. С одной стороны, все еще существуют решения с открытым исходным кодом. С другой стороны, нет никаких гарантий, что модель с открытым исходным кодом будет с вами на протяжении всего пути: например, Corona, собственная разработка Facebook для программного обеспечения планирования Hadoop MapReduce, появилась в первую очередь из-за невозможности коммитить исправления, необходимые для масштабирования Hadoop вверх по течению.
При этом юридическая сторона вопроса затрагивает open source: например, коммиты в golang или k8s требуют подписания CLA. Будет ли это оставаться проблемой?
НАЦИОНАЛЬНЫЕ ИНСТИТУТЫ ЗДРАВООХРАНЕНИЯ США. Да, помимо объективных причин, возможно, принятые решения не прагматичны. Это синдром NIH во всей красе.
Например, пытаясь устранить влияние пакетной обработки на вычисления, мы попытались создать собственный планировщик в ядре Linux. На практике ничего хорошего из этого не вышло; можно было бы обойтись существующими возможностями ядра Linux. Однако чем выше затраты на рабочую силу, тем больше усилий затрачивается на разработку и решение проблемы и тем ниже вероятность возникновения синдрома NIH.
Подводя итог , как видите, крупным компаниям часто требуются собственные решения. Большинство из них в будущем сольются с еще не созревшими унифицированными глобальными стандартными решениями, а остальные уйдут в историю. В любом случае выбор между собственным решением и готовым остается сложным вопросом, на который невозможно ответить без предварительного понимания контекста и оценки стоимости такого проекта.