Стройте ответ вокруг владения состоянием, лимитов, отказа и восстановления. Определение становится инженерным ответом только в конкретном production-сценарии.
Вопросы и ответы
8 подробных ответов
01Спроектируйте CI/CD-пайплайн для организации с ~50 микросервисами. Пройдитесь по стадиям и компромиссам.
senior
Короткий ответ: Один общий шаблон пайплайна на все сервисы; сборка один раз → неизменяемый артефакт (образ с digest), который продвигается через окружения без пересборки; тесты ярусами от быстрых к дорогим; в прод — canary с автооткатом. Оценивают не схему, а то, как вы аргументируете компромиссы.
Подробно:
PR: lint + unit (< 5 мин, гейт мержа)
│ merge в main
▼
build ──► immutable-артефакт (image digest) ──► registry
▼
integration (контрактные тесты, моки соседей)
▼
staging: e2e + smoke ──► промоушен ТОГО ЖЕ артефакта
▼
prod: canary 5% ──► метрики ok ──► 100% (иначе автооткат)
- Build once, promote everywhere — пересборка под каждое окружение означает: тестировали один бинарь, выкатили другой. Продвигается digest, а не тег
latest. - Ярусы тестов — быстрый гейт на PR, дорогие e2e после мержа: иначе очередь на мерж растёт до часов.
- Общий шаблон — 50 сервисов × свой YAML = дрейф и зоопарк; параметризованный shared template обновляется централизованно.
- Секреты — OIDC-федерация в облачный IAM, короткоживущие токены вместо статических ключей в CI.
⚠️ Частая ошибка: перечислить стадии без компромиссов. Интервьюер слушает про «скорость vs безопасность»: какие тесты где режем, что блокирует мерж, а что — только выкатку.
02Trunk-based development или GitFlow: какая модель делает возможным continuous deployment и почему?
middle
Короткий ответ: Continuous deployment реален только при trunk-based + фиче-флаги: маленькие батчи, ветки живут часы, main всегда выкатываем. GitFlow с долгоживущими develop/release-ветками — большие батчи и merge-ад; его место — коробочный софт с версиями.
Подробно:
| Trunk-based | GitFlow | |
|---|---|---|
| Ветки | main + ветки < 1–2 дней | develop, release/, hotfix/ — долгоживущие |
| Размер батча | маленький, интеграция ежедневно | большой, интеграция в конце релиза |
| Deploy vs release | разделены фиче-флагами | склеены: релиз = мерж release-ветки |
| Подходит для | SaaS, continuous deployment | коробочный софт, несколько поддерживаемых версий |
- Флаги разделяют deploy и release — код едет в прод выключенным; включение — это конфиг, а не выкатка. Это снимает страх мержить незавершённое в main.
- Аргумент — размер батча, а не вкус: чем дольше живёт ветка, тем больше конфликтов, длиннее lead time и страшнее откат — DORA-метрики ровно об этом.
⚠️ Частая ошибка: отвечать «кому что удобнее». Это не вопрос вкуса: долгие ветки → большие батчи → длинный lead time — аргумент измеримый.
03Canary-выкатка: как автоматизировать решение «промоутить или откатывать»?
senior
Короткий ответ: Автоматический canary analysis: на каждом шаге раскатки сравниваем canary с baseline того же размера (не со всем флотом!) по SLI-метрикам — error rate, перцентили латентности — в окне 5–10 минут; выход за порог → автооткат без человека. Так работают Argo Rollouts и Flagger.
Подробно:
трафик: 1% ──► 5% ──► 25% ──► 100%
│ │ │
▼ ▼ ▼
анализ окна на каждом шаге:
canary vs BASELINE (свежие поды СТАРОЙ версии,
столько же реплик):
• error rate ≤ baseline + порог
• p99 latency ≤ baseline × 1.05
fail любого шага ──► автооткат + алерт
- Baseline того же размера — сравнивать один canary-под с 50 прогретыми старыми нечестно: другой прогрев кэшей и коннекшн-пулов. Поэтому Flagger/Argo поднимают свежий baseline из старой версии.
- Метрики = SLI, не CPU: пользователю безразлична утилизация, важны ошибки и латентность; плюс бизнес-метрика, если есть (конверсия чекаута).
- Автооткат — весь смысл: canary без автоматического решения — просто медленная выкатка, за которой кто-то обязан следить глазами.
⚠️ Частая ошибка: остановиться на определении «пускаем 5% трафика». Вопрос — про анализ: что с чем сравниваем, по каким порогам и кто нажимает откат.
04Что такое GitOps и почему pull-модель (ArgoCD/Flux) лучше, чем push из CI в кластер?
middle
Короткий ответ: GitOps: git — единственный источник желаемого состояния, а агент внутри кластера непрерывно приводит фактическое состояние к нему. Pull лучше push по двум причинам: креды кластера не покидают кластер, и есть непрерывная реконсиляция — дрейф детектируется и чинится, а не только в момент деплоя.
Подробно:
| Push (CI → кластер) | Pull (ArgoCD/Flux) | |
|---|---|---|
| Креды | admin-kubeconfig лежит в CI | агент внутри, наружу ничего не выдаём |
| Дрейф | ручной kubectl edit никто не заметит |
detect + self-heal автоматически |
| Аудит | логи CI-запусков | git log — полная история «кто что менял» |
| Откат | перезапуск старого пайплайна | git revert |
| Масштаб | каждый пайплайн знает про кластер | app-of-apps, новые кластеры декларативно |
- CI собирает, CD реконсилирует — пайплайн публикует образ и коммитит новый tag в конфиг-репозиторий; дальше агент делает всё сам.
- Отдельный конфиг-репозиторий — код и манифесты живут врозь: иначе каждый bump образа триггерит CI самого приложения.
⚠️ Частая ошибка: «GitOps = хранить YAML в гите». Без непрерывной реконсиляции и self-heal это просто конфиги в репозитории.
05Как вы обращаетесь с секретами в CI-пайплайнах и в GitOps-репозиториях?
middle
Короткий ответ: Плейнтекстом в git — никогда, даже в приватном репо: история, форки и бэкапы живут вечно. В CI — OIDC-федерация в облачный IAM: короткоживущий токен на джобу вместо хранимых ключей. В GitOps-репо — SOPS/sealed-secrets (в гите шифротекст) или external-secrets (в гите только ссылка на Vault/Secrets Manager).
Подробно:
| Слой | Решение | Почему |
|---|---|---|
| CI → облако | OIDC federation (runner → IAM role) | нет хранимых ключей; токен живёт минуты — нечего красть и ротировать |
| CI-переменные | masked/protected vars — лишь минимум | статический секрет, виден мейнтейнерам, утекает в логи (base64 обходит маску) |
| GitOps-репо | SOPS / sealed-secrets | шифротекст можно коммитить; расшифровка — только ключом в кластере |
| Ссылка вместо значения | external-secrets operator | git хранит указатель, значение в Vault; ротация не трогает git |
- Ротация — часть ответа: где секрет рождается, кто и как его меняет, что перевыкатывается после смены. Без этого «мы шифруем» — не ответ.
- Утёкший секрет скомпрометирован навсегда — git history не чистится «удалением файла»; только ревокация и выпуск нового.
⚠️ Частая ошибка: «у нас masked variables в GitLab» как весь ответ — это долгоживущий статический секрет, который никто не ротирует.
06CI-сборка идёт 40 минут. Как будете ускорять?
middle
Короткий ответ: Сначала профилировать — разбить время по стадиям и найти, где оно сидит, а не покупать раннеры. Дальше по убыванию выгоды: параллельный DAG вместо цепочки, кэш слоёв Docker (зависимости до исходников), общий remote-кэш, шардирование тестов, affected-only в монорепо. Железо — последним.
Подробно:
- Измерить — тайминги стадий уже есть в CI: обычно 80% времени сидит в 1–2 местах (тесты или docker build).
- DAG вместо цепочки — lint, unit и сборка образов независимы → параллельно; критический путь короче.
- Порядок слоёв в Dockerfile —
COPYманифеста зависимостей и install ДОCOPY . .: правка кода не инвалидирует слой с зависимостями. - Remote-кэш — эфемерные раннеры без общего кэша собирают мир с нуля каждый раз: buildx cache, кэш пакетных менеджеров.
- Шардирование тестов — сплит по историческим таймингам на N параллельных джобов.
- Affected-only — в монорепо собирать только затронутые пакеты (nx / turborepo / bazel).
- Раннеры мощнее — последними — платить железом до профилирования значит маскировать проблему.
⚠️ Частая ошибка: начинать с «купим раннеры побольше». Если 30 из 40 минут — последовательные e2e, железо даст минуты, а параллелизация и кэш — десятки.
07Как миграции базы данных вписываются в zero-downtime выкатки и откаты?
senior
Короткий ответ: Паттерн expand/contract: сначала аддитивная миграция (новая колонка/таблица), затем код, совместимый с обеими схемами, бэкфилл — и только потом contract (удаление старого) отдельным шагом. Схема и код меняются разными деплоями, каждый шаг обратно совместим на одну версию — иначе мгновенный откат кода невозможен.
Подробно:
T0 expand: ADD COLUMN new (nullable/default) — только схема
T1 деплой v2: пишет в обе колонки, читает new → fallback old
T2 бэкфилл старых строк батчами (не одним UPDATE!)
T3 деплой v3: читает и пишет только new
T4 contract: DROP COLUMN old — когда откат к v2 уже не нужен
инвариант: в любой точке версии кода N и N−1
работают с текущей схемой одновременно
- Почему не lock-step — «миграция + код одной выкаткой» ломается дважды: во время раскатки старые поды уже видят новую схему, а откат кода требует отката схемы — то есть потери данных.
- Rename — это тоже expand/contract — add → dual-write → backfill → drop; прямой
RENAME COLUMNубивает работающую версию. - Бэкфилл отдельно от миграции — гигантский UPDATE при деплое держит блокировки и кладёт прод; батчами, в фоне.
⚠️ Частая ошибка: класть DROP/RENAME в ту же выкатку, что и код. Пять скучных шагов — зато откат остаётся кнопкой, а не восстановлением из бэкапа.
08Плохой релиз доехал до прода, хотя все тесты были зелёные. Что вы меняете в системе?
middle
Короткий ответ: Признать, что тесты не ловят всё, и достроить контур ПОСЛЕ деплоя: smoke-тесты и SLI-гейты в проде, canary с автооткатом, ревизия паритета staging ↔ prod, фиче-флаги для рискованных путей. И blameless-разбор самого пайплайна: сломалась система доставки, а не инженер.
Подробно:
- Post-deploy verification — smoke-тесты и проверка SLI сразу после выкатки как шаг пайплайна; «выкатили и смотрим дашборд глазами» — это не гейт.
- Canary + автооткат — плохой релиз получает 5% трафика и откатывается за минуты: ограниченный blast radius вместо «всё или ничего».
- Паритет staging/prod — зелёные тесты на непохожем окружении ничего не доказывают: данные, конфиги, версии зависимостей, нагрузка.
- Фиче-флаги — рискованный путь выключается конфигом за секунды, без новой выкатки.
- Blameless postmortem пайплайна — вопрос «какой гейт должен был это поймать и почему его нет», а не «кто виноват».
⚠️ Частая ошибка: ответить «добавим больше тестов». Тесты живут до прода; класс багов, которые проявляются только в проде (данные, нагрузка, конфиг), ловится только контуром после деплоя.
Источники
Источники и редакционная политика
Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.
От чтения к воспроизведению
Отрепетируйте полный цикл интервью.
RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.