
Со временем в каждой крупной IT-компании накапливается критическая масса однотипных решений для рутинных задач, а также сервисы и библиотеки, написанные на разных языках. Сначала кажется, что это круто: каждый волен выбирать инструменты под себя и свою задачу. А потом становится очевидно, что разнообразие — это хорошо, но не для поддержки и развития десятков, а то и сотен сервисов. Мы ВКонтакте остро ощутили это сейчас, когда масштабно перестраиваемся и переходим к сервисной архитектуре.
Отвечая на этот вызов, мы создали внутреннюю платформу разработки. Это набор стандартов, библиотек, шаблонов и решений по автоматизации. Он позволит командам не тратить время на одни и те же технические вопросы, а взять всё «из коробки» и сосредоточиться на задачах.
Меня зовут Олег Сабрян, я руководитель отдела разработки PaaS ВКонтакте. В этой статье я расскажу, как мы строили внутреннюю платформу разработки, какие грабли собрали, какие принципы выработали и почему это не только про код, но и про людей.
Как всё начиналось: от хаоса к осознанности
Платформа — это не чек-лист, а эволюция инженерной культуры внутри компании. В какой-то момент разнообразие сервисов достигает критической массы, в нашем случае это коснулось деплоя сервисов. Мы выпустили первую версию внутреннего SDK, но колоссального роста T2M не получили.
Новый сервис можно сделать за один-два дня, но чтобы дотащить его до прода, уходили недели. Необходимо было согласовать Sentry, дождаться, пока создадут CI/CD-пайплайны, подготовят helm-чарты для k8s и т.д. Проходя этот длинный путь, мы решили создать портал по принципу единого окна, где всё необходимое для запуска и поддержки сервиса будет доступно за пару кликов.
Как устроена внутренняя платформа разработки?
Платформа строится вокруг собственного SDK: это библиотеки и шаблоны, которые интегрированы в инфраструктуру. Разработчик, подключая библиотеку, получает телеметрию на дашбордах и рабочую конфигурацию «из коробки», а взаимодействие с инфраструктурой сведено к минимуму.
Команда PaaS сопровождает коллег на всех этапах их задач: от идеи до продакшена, помогая с архитектурой и выбором инструментов. Все шаблоны интегрированы с CI/CD: сервисы собираются и выкатываются буквально по кнопке, а стабильность процессов обеспечивается в сотрудничестве с DevOps.
Автоматизация инфраструктуры избавила от рутинных операций: например, получение DSN Sentry теперь происходит автоматически, без бюрократии. Observability & Monitoring реализованы через нашу систему Argos, которая отслеживает аномалии метрик и сигнализирует о проблемах.
За три года с момента появления PaaS мы запустили более 150 сервисов на разных языках: Go, Python, TS.

Что входит в хорошую платформу разработки:
Стандарты. Платформа начинается со стандартов. Даже если они неидеальны — это лучше, чем их отсутствие. Стандарты избавляют от холиваров по поводу выбора фреймворка, базы данных, очереди и других компонентов. Они экономят время и делают наём проще: если все пишут по одним правилам, легче находить и обучать новых сотрудников.
Процессы. Создать сервис легко, а вот обеспечить его быстрый и безопасный запуск в продакшен гораздо сложнее. Если процессы не отлажены, деплой может занять недели. Платформа должна стандартизировать и автоматизировать все этапы жизненного цикла сервиса.
Автоматизация. Ручные операции — зло. Если для доступа к Sentry или базе данных нужно идти к человеку, писать таску и ждать неделю — это тормозит бизнес. Всё, что можно автоматизировать, должно быть автоматизировано.
Унификация и поддержка. Стандарты и шаблоны позволяют DevOps-инженерам и администраторам эксплуатировать сервисы без постоянного участия разработчиков. Всё прозрачно: где логи, где метрики, как менять параметры.
Стандарты: как перестать спорить и начать работать
Стандарты нужны, чтобы раз и навсегда прекратить бесконечные споры о том, какой инструмент или технологию выбрать для очередного сервиса. Стандарты можно внедрять по таким этапам:
Выбор базовой операционной системы. Вдаваться в детали выбора здесь не буду — всё-таки основной акцент сейчас на разработке, а не на сравнении дистрибутивов.
Инфраструктурные компоненты. Всё фиксируется заранее: например, Kafka — для одних задач, RabbitMQ — для других, Redis и Memcached — для своих сценариев. В итоге появляется простая и понятная таблица: слева название движка, справа область его применения. То же касается языков и фреймворков. Это снимает массу вопросов и экономит время всей команды. Условно, это можно назвать техрадаром.
-
Телеметрия и мониторинг. Соберите по максимуму всю самую важную информацию по рантайму приложения: потребление памяти, работа GC, CPU и т. д. Чем больше вы соберёте на старте, тем проще будет работать с приложениями в будущем. Главное — помнить, что нет ненужных метрик по рантайму.
У вас годами может не возникать проблем, к примеру, с GC. Но одна допущенная ошибка — и перформанс приложения упадёт, а потребление ресурсов вырастет. Отловить это поможет готовая метрика на дашборде.
SDK и шаблоны. SDK обеспечивает быстрый старт, интеграцию с инфраструктурой и предсказуемое поведение сервисов вне зависимости от среды — будь то Bare Metal, Kubernetes или своё кастомное облако. Хороший SDK снимает головную боль с логами, метриками и администрированием: всё уже реализовано, не нужно каждый раз изобретать велосипед или писать свою библиотеку для сбора метрик. Всё это должно быть заложено в базовый шаблон приложения.
Практика и наш опыт: как строить SDK и шаблоны
Постарайтесь сформировать общий шаблон приложения с готовой структурой, в котором всё необходимое будет уже на старте. Разложим по полочкам, на чём стоит сконцентрироваться в первую очередь:
-
Конфигурация приложения. Важно продумать, как будет устроена конфигурация приложения — именно с этим вы столкнётесь при первом деплое в продакшен. Часто в компании уже есть для этого сервисы, и проще всего — предоставить единую библиотеку для работы с конфигами. Определитесь с форматом: это может быть YAML-файл, отдельный .env-файл, параметры запуска или что-то ещё. Также продумайте, как именно эти конфиги будут доставляться до приложения и кто за это станет отвечать.
Например, ВКонтакте мы реализовали «слоёный пирог». Сначала считывается YAML-файл — он используется для локальной разработки. Всё остальное — уже для продакшена. Разработчик запускает приложение, и оно везде работает одинаково:
сначала читается YAML;
подтягиваются переменные окружения;
обрабатываются аргументы запуска;
всё это маппится на структуры данных, которые и представляют собой конфиги.
Такая схема позволяет работать с сервисами где угодно — локально, в облаке или на Bare Metal — и быть уверенными, что конфигурация всегда будет предсказуемой.
-
Секреты и безопасность. Очень важно заранее продумать, как вы будете доставлять секреты в сервисы. Просто прописывать секреты в конфигурационных файлах — небезопасно. ВКонтакте мы используем vault:
разработчики передают свои секреты администраторам через систему одноразового просмотра ссылки и данных внутри, те размещают их в vault;
дальше агентом автоматически подтягиваются секреты в контейнеры приложений.
В момент запуска приложение считывает их из файла и подгружает в конфиги приложения. Всё работает «из коробки», и разработчику не нужно думать, как получить требуемый секрет: для него это прозрачно и реализовано на уровне платформы.
-
Структура приложения. Когда у вас уже есть проработанная система конфигураций, можно переходить к следующему шагу — организовывать структуру приложения. Здесь важно пообщаться с коллегами:
узнать, как сейчас устроены проекты;
какие структуры уже используются и насколько они распространены.
Бывает, что большинство сервисов написаны одной командой и у них свой внутренний стандарт. Логично взять его за основу, чтобы не ломать привычные процессы. А если предлагаете что-то новое — главное, чтобы это решение принималось совместно.
Учитывайте и уровень экспертности, и опыт команд. Нередко выбранный фреймворк диктует структуру приложения. Но в идеале архитектура должна быть максимально абстрактной и не зависеть от конкретных технологий — чтобы отражать архитектурную логику, а не особенности реализации.
ВКонтакте мы проектируем платформу близко к принципам чистой архитектуры, но не ограничиваем разработчиков рамками. На старте мы генерируем шаблон приложения с необходимыми файлами и структурой, которые можно дорабатывать под свои нужды. Главное для платформенной команды — чтобы основные файлы оставались на своих местах. Это упрощает поддержку и позволяет быстро вносить изменения во все проекты.
-
Телеметрия. Для сбора метрик определите подход: push- или pull-модель, формат данных и хранилище. Решите, какие метрики будут писаться по умолчанию, — это позволит подготовить типовые дашборды и быстро реагировать на сбои первых сервисов. Мы рекомендуем фиксировать базовые показатели:
CPU;
GC;
память (heap, stack);
числа потоков и goroutines — чтобы сразу отслеживать типичные ошибки, например избыточное создание goroutines.
Стоит предусмотреть и продуктовые метрики. Лучше, если у разработчика будет возможность использовать уже существующую общую метрику, а не изобретать свою. Так проще строить сквозные графики и автоматические алерты. Не забывайте и о метриках железа:
CPU;
RAM;
LAN.
Советуем закладывать запас по ресурсам, чтобы сервисы выдерживали сбои дата-центров.
У нас для агрегации метрик используется собственная разработка VK — Statshouse по push-модели, которая собирает более миллиарда событий со всей инфраструктуры. Мы заранее готовим общие дашборды: метрики можно фильтровать по сервисам, окружениям и даже по отдельным подам. Дополнительно используем инструменты фильтрации и очистки лишних данных, чтобы дашборды оставались информативными и не перегруженными.
-
Инфраструктурные библиотеки. Когда вы реализовали первые библиотеки для записи метрик и определились с инфраструктурой, следующий шаг — создать общие библиотеки для работы с инфраструктурными компонентами:
базами данных;
ingress/egress;
интерфейсами взаимодействия (например, HTTP).
Важно, чтобы все эти стандартные библиотеки автоматически писали метрики в выбранном формате.
Если в компании начинается миграция, например с Memcached на Redis, удобно использовать промежуточную библиотеку, которая по конфигу переключает драйверы. Это позволяет постепенно переводить сервисы на новую технологию без стресса: сначала часть трафика идёт на Redis, вы проверяете корректность работы и только потом полностью отключаете старое решение.
Главная задача — абстрагировать инфраструктуру от приложения, чтобы смена технологий проходила максимально безболезненно. Как только такие библиотеки и подходы внедрены, можно отдавать их в продуктовые команды для интеграции в свои сервисы.
-
Кодогенерация. Мы используем Cookiecutter: у нас есть несколько базовых шаблонов, каждый из которых можно параметризировать. Сначала мы думали сделать один универсальный шаблон с множеством опций, где разработчик отвечал бы на вопросы: нужен ли Swagger, требуется ли RPC-сервер, нужны ли фоновые «демоны» и так далее. Но поняли, что количество параметров может стать неконтролируемым. Поэтому мы разбили всё на отдельные базовые шаблоны — например, backend, админка, бот или ML-сервис. И уже внутри каждого реализуем нужную параметризацию, учитывая специфику.
Такой подход помогает избежать копипаста: разработчики не переносят чужой код с непонятными зависимостями, а получают актуальный шаблон, адаптированный под задачу. Конечно, есть и минусы: усложняется поддержка общих библиотек. Если меняется интерфейс библиотеки, приходится обновлять все шаблоны, а у нас их уже с десяток на разных языках. Это добавляет дедкода: иногда сгенерированные компоненты оказываются невостребованными разработчиками в рамках нового сервиса, поэтому просто остаются в приложении до лучших времён.
При выборе и проектировании шаблонов важно обсуждать с командами их реальные задачи и проблемы, чтобы шаблоны максимально соответствовали основным сценариям использования. Всё это делается для продуктовых команд, которым потом предстоит работать с ними в повседневной разработке.
Мультиязычность: как поддерживать разные стеки
Мультиязычность — одна из самых интересных и сложных тем при построении платформы. ВКонтакте используетс сразу несколько языков: у нас есть Go, Python (чаще для ML-задач), есть Node.js и другие. Изначально для каждого языка формировалась отдельная платформа — со своей спецификой и правилами. Со временем стало понятно, что поддерживать несколько разрозненных платформ неудобно. Они начинают расходиться:
по конфигурации базовых компонентов: http-сервер, логгер, клиенты к базам и т. д.;
по логированию: может быть разный формат записи данных;
по метрикам: приложения могли писать одну и ту же метрику по-разному.
В итоге даже такие базовые вещи, как мониторинг или система логов, перестают быть универсальными — и для каждого языка нужны свои отдельные решения.
Мы пришли к выводу, что нужен единый стандарт для всех фреймворков, и, что важно, — необходимо абстрагироваться от языка приложения.
Как мы к этому пришли? Было много споров внутри команды. В какой-то момент приняли решение: при создании ключевых библиотек (например, логгера или клиента для работы с популярной базой данных) мы сначала описываем конфигурацию и интерфейс взаимодействия с библиотекой на псевдокоде, а потом реализуем это на всех языках, которые нам нужны.
Плюс подхода в том, что конфигурация библиотек становится одинаковой для всех языков. Админы, работая с сервисами на Go или Python, не сталкиваются с неожиданностями — всё работает и настраивается одинаково. Разработчикам тоже проще: при переходе с одного языка на другой всё выглядит знакомо, поведение и конфиги схожи.
Минус — сложные обсуждения на старте, когда приходится договариваться о стандартах для всех языков. Но спустя время профит очевиден: поддержка становится проще, а внедрение новых инструментов — быстрее.
Получается такой roadmap для SDK:
Configs. Формируем конфигурацию, затем отдаём её разработчикам.
Template. Делаем базовые шаблоны, прорабатываем структуру приложений.
Observability. Внедряем стандарты для записи метрик и логов.
Infra packages. Абстрагируем инфраструктуру в общих библиотеках.
Product packages. Делаем продуктовые библиотеки. Иногда, если одна и та же модель пользователя нужна в разных сервисах, её выносят в отдельную.
Codegen. Занимаемся кодогенерацией.
Multilanguage. Подгоняем под стандарты другие фреймворки в компании.
Процессы и автоматизация: как избавиться от бюрократии
Когда речь заходит о платформе, важно помнить: написать код — это только часть дела, ещё нужно уметь выкатывать и сопровождать. Раньше, чтобы зарелизить один новый сервис, нужно было ставить восемь задач на разных Jira-досках и взаимодействовать с командами. А любая ошибка — не туда поставил задачу или заполнил не так поле в шаблоне задачи — приводила к пинг-понгу таски, и это могло затянуться надолго. По итогу на заполнение тасок могла уйти неделя-полторы.
Какие изменения мы внесли:
Описали процессы и участников. Мы зафиксировали всех участников процесса раскатки новых сервисов и подробно описали, какие этапы проходит сервис на пути в продакшен. Особое внимание уделили SLA: если инфраструктурные команды не дают чётких сроков, сервис может застрять на этапе выката на месяц.
Единая Jira-задача и базовая автоматизация. Вместо множества разрозненных досок сделали одну общую Jira-таску для PaaS-команды. Разработчики заполняли все необходимые данные в ней, а дальше информация автоматически подтягивалась на другие доски. Это исключило хождение по разным командам и ускорило движение задач. Теперь это делала автоматика, а разработчик уже мог видеть в закрепе связанные таски и при необходимости дополнять их.
Перераспределение ответственности. Пересмотрели распределение задач между командами. Некоторые задачи, которые раньше выполняли админы или DevOps-инженеры, взяла на себя команда платформы. Например, мы стали помогать с настройкой CI/CD, объяснять разработчикам, как заводятся пайплайны, и брать на себя часть саппорта. При этом профильные команды продолжали контролировать процесс.
Автоматизация рутины. Мы упростили рутинные задачи с помощью простых скриптов. Например, реализовали автоматическое создание алертов. После этого приступили к более серьёзной работе: развернули собственный сервис, который принимает хуки из Jira и при необходимости создаёт или перемещает нужные задачи. Типичная ситуация: сервис мог зависнуть на этапе деплоя на десять дней просто из-за того, что никто не перевёл задачу в нужный статус. Автоматизация этого процесса с помощью скрипта сразу улучшила Time to Market. Как только мы автоматизировали общий workflow в Jira и наладили процессы, стали постепенно избавляться от ручных операций.
Например, у нас изначально были подготовленные шаблоны для CI/CD в TeamCity. Но чтобы использовать их для конкретного сервиса, нужно было создать задачу для DevOps-команды и ждать. Чтобы улучшить процесс, мы действовали так:
настроили автоматическое создание MR в репозиторий с TeamCity DSL, оставив за человеком только проверку и принятие изменений;
реализовали автоматическое слияние созданного merge request;
исключили соответствующую задачу из общего workflow в Jira.
По итогу получили первое упрощение и ускорение процесса, когда создаётся новый сервис.
Платформа продолжает активно развиваться. Все небольшие скрипты, которые мы внедряли на ранних этапах, стали основой для новой платформы разработки. Теперь создание сервиса — это полноценный автоматизированный пайплайн с реконсиляцией, и он позволяет не только ускорить взаимодействие с инфраструктурой, но и с людьми. Даже если в процессе всё ещё требуется завести таску, теперь это делает не человек, а робот. И это значительно упрощает общий поток задач.
Итоги: платформа — это не только про технологии, но и про людей
Главный вывод, который мы сделали: успех платформы невозможен без постоянного общения. Да, для команды платформы важна экспертность в технологиях, глубокое понимание баз данных, движков, кешей и умение создавать качественные библиотеки. Но не менее значимо — развивать софт-скиллы и уметь разговаривать с людьми.
Ваши заказчики — это разработчики самого разного уровня: от джунов до сеньоров, а иногда и менеджеры. Важно находить общий язык, объяснять решения, слушать обратную связь и быть готовыми к спорам и даже к хейту. Не все будут довольны стандартами и инструментами, кто-то захочет работать по-своему, кто-то будет сравнивать ваши решения с опытом из других компаний. Важно не просто отстаивать свою позицию, но и аргументировать, показывать преимущества, обучать, поддерживать и принимать фидбэк.
В итоге команда платформы — это те, кто решает проблемы, а не создаёт их. И хотя приходится сталкиваться и с критикой, благодарность от коллег — лучшая награда.
Если вы разделяете наш подход и хотите работать над сложными инженерными задачами в команде, где ценят открытость и инициативу, присоединяйтесь к нам! Мы ищем Go-разработчиков, которым интересно расти и влиять на развитие технологий ВКонтакте. Получить офер можно за один день, откликайтесь на сайте.
P. S. Пишите в комментариях, о чём хотели бы узнать подробнее, — обязательно расскажем в следующих статьях.