Duolingo → Codespaces: от часов настройки до трёх минут
Как Duolingo перенёс разработку в облако и сократил онбординг с дней до минут через GitHub Codespaces и Tailscale
Первоисточник
How we made developer onboarding a breeze with GitHub CodespacesDuolingo Engineering, 2023
Контекст: монолит, микросервисы и сотни окружений
Duolingo — приложение для изучения языков с сотнями миллионов пользователей. Инженерная команда компании мигрировала с монолитной архитектуры на микросервисы, и количество репозиториев и окружений быстро росло. Один разработчик в течение недели переключался между тремя-четырьмя сервисами, каждый из которых требовал своих зависимостей, своих версий языков и своих инструментов.
Duolingo хостит код на GitHub. Инженеры пишут в VS Code. Инфраструктура живёт в AWS.
Проблема: «ритуал посвящения» вместо онбординга
Настройка рабочего окружения занимала у новых инженеров от нескольких часов до нескольких дней. Процесс выглядел так: установить зависимости, сконфигурировать инструменты, найти и исправить несовместимости, несколько раз обратиться к коллегам за помощью. Каждый новый разработчик проходил через этот цикл заново. Каждый раз всплывали новые поломки, потому что инструкции устаревали быстрее, чем кто-то успевал их обновлять.
Локальная машина инженера превращалась в свалку конфликтующих рантаймов: Python 3.8 для одного сервиса, Python 3.11 для другого, специфические версии Node.js, Go, Java. Разработчик тратил время на борьбу с окружением вместо написания кода.
Переключение между проектами усугубляло проблему. Инженер, который работал над сервисом на Go, хотел внести правку в Python-сервис. Ему нужно было настроить локальное окружение для Python-проекта, что занимало часы и грозило сломать уже работающее Go-окружение.
Решение: GitHub Codespaces + Tailscale + duo CLI
Платформенная команда Duolingo выбрала GitHub Codespaces для переноса разработки в облако. Выбор определили три фактора: код на GitHub, команда в VS Code, а Codespaces позволяет описать окружение через devcontainer.json и развернуть его за минуты.
Архитектурная проблема: сеть
Codespaces запускают окружения в Azure, а сервисы Duolingo живут в AWS. Разработчикам нужен доступ к внутренним AWS-ресурсам: базам данных, API, staging-средам. Duolingo интегрировал Tailscale для решения этой задачи.
Архитектура работает так. Duolingo запускает Tailscale relay node в своём VPC в AWS. Внутри каждого codespace при старте поднимается Tailscale-клиент. Разработчик запускает команду duo vpn (обёртку вокруг tailscale up), проходит аутентификацию через Google SSO и получает доступ ко всем внутренним ресурсам. Соединение сохраняется между запусками codespace: на следующий день разработчик открывает окружение, и VPN уже работает. Команда Duolingo отмечает, что эта схема работает надёжнее их обычного корпоративного VPN.
Многослойная автоматизация
Duolingo построил систему hook-скриптов на базе lifecycle commands из спецификации Dev Containers. Каждый репозиторий содержит devcontainer.json, в котором postStartCommand указывает на bash-скрипт из базового образа. Этот скрипт вызывает соответствующую команду из duo CLI, а duo CLI в свою очередь выполняет repo-специфичный скрипт .devcontainer/postStart, если он есть.
duo CLI — внутренний инструмент, который Duolingo написал для своих инженеров. Ключевая деталь: CLI обновляется при каждом запуске codespace. Когда платформенная команда меняет процесс настройки, все разработчики получают обновление при следующем запуске, без ручных действий и без пулл-реквестов в сотни репозиториев.
Скрипты устанавливают зависимости, поднимают Tailscale, настраивают переменные окружения, подключают нужные сервисы. Весь процесс занимает около восьми минут для основного монолитного репозитория.
Результаты
Один инженер из команды Content Tooling описал свой опыт: «Получил новый ноутбук и через три минуты мог разрабатывать». Три минуты ушли на открытие браузера, переход на GitHub и запуск codespace. Настройка самого окружения заняла ещё несколько минут в фоне, но разработчик мог заниматься другими задачами первого дня, пока codespace разворачивался.
Сравнение: раньше часы на установку, дни на отладку, постоянные обращения к коллегам. Теперь восьмиминутный автоматический процесс.
Дополнительные выигрыши:
- Переключение между проектами стало тривиальным. Инженер создаёт новый codespace для другого сервиса и через несколько минут работает в чистом окружении без конфликтов зависимостей.
- Feedback loop сократился до секунд, потому что облачные машины мощнее среднего ноутбука.
- Привязка к устройству исчезла. Любое устройство с браузером стало рабочим.
- Дрейф конфигурации прекратился. Платформенная команда обновляет
duoCLI в одном месте, и все инженеры получают актуальную настройку.
Уроки
Сеть решайте первой. Облачные окружения живут за пределами вашего периметра. Без доступа к внутренним сервисам codespace бесполезен для бэкенд-разработчиков. Duolingo решил задачу через Tailscale. Другие компании используют VPN-шлюзы, SSH-туннели или service mesh. Но решить эту задачу нужно до того, как вы предложите codespaces инженерам, иначе первый опыт оставит негативное впечатление.
devcontainer.json — правильная точка входа. Duolingo использовал открытую спецификацию Dev Containers вместо проприетарного формата. Если завтра компания решит перейти с Codespaces на DevPod или Gitpod Flex, devcontainer.json останется рабочим. Ставка на открытый стандарт снижает vendor lock-in.
Автообновление инструментов обязательно. Setup-скрипт, который нужно обновлять вручную в каждом репозитории, устаревает через месяц. Duolingo вынес логику настройки в duo CLI с автоматическим обновлением. Платформенная команда меняет процесс в одном месте, и изменение доходит до всех.
Начните с измерения. Метрика time-to-first-commit покажет, сколько времени сейчас занимает настройка окружения у вас. Замерьте, запишите. Потом автоматизируйте и замерьте снова. Разница между «днями» и «минутами» — аргумент, который поймёт любой руководитель.