Политика базовых образов: что ломается без неё
Пока единого правила нет, каждая команда берёт базовый образ оттуда, откуда удобно, и обновляет его когда вспомнит. Ночью в родительском образе меняется патч-версия — утром одна из служб поднимается с новой библиотекой и падает на несовместимом вызове, а причина не видна: тот же код, та же ветка, другой родитель. Политика базовых образов отсутствует, и сборка начинает зависеть от того, что кто-то выложил в общий реестр.
Дальше начинается расхождение сред. Стенд собран на прошлом родителе, прод — на текущем, у разработчика локально вообще образ из кэша, и баг воспроизводится на одном контуре из трёх. Параллельно копятся устаревшие зависимости: обновлять родителя страшно, потому что никто не проверял, что приедет вместе с ним, — версия живёт в проде до первого инцидента.
Теневые сборки закрывают эту боль по-своему: часть образов собирается мимо конвейера, руками, с локальных машин, и попадает в реестр без сканирования и без метаданных о составе. Так получается невоспроизводимая сборка — из одного коммита выходят разные артефакты, и откат на предыдущий образ перестаёт быть откатом.
Цена проявляется в самый неудобный момент — при плановом обновлении родителя или срочном закрытии уязвимости. Сначала приходится разбирать, что вообще собрано и на чём, и только потом что-то менять. Разбираем, как это закрывается: единый родительский образ, фиксированные теги, окно обновления и проверка на стенде до прода.
Измеримый эффект: время сборки и стабильность сред
Политика базовых образов измеряется не числом документов, а четырьмя величинами: срок выпуска релиза, доля успешных обновлений, количество ручных правок конфигурации на релиз и воспроизводимость стендов. Мы снимаем эти показатели до внедрения — по истории сборок в реестре и журналам развёртывания, — иначе эффект нечем подтвердить.
Основной сдвиг — в сроке выпуска. Когда все сервисы собираются от одного зафиксированного базового образа, а обновления безопасности приходят централизованно, команде не нужно на каждом релизе согласовывать версии библиотек и пересобирать слои вручную. Подготовка релиза сокращается в разы, а сама сборка укладывается в предсказуемое время вместо «как повезёт с кэшем».
Доля успешных обновлений растёт за счёт ухода целого класса отказов — расхождения окружений. Тестовая, предпродуктивная и продуктивная среда перестают отличаться набором системных пакетов, поэтому расхождение конфигурации исчезает как категория инцидента. Остаются ошибки в коде и логике — то, что действительно требует инженера, а не пересборки.
Ручные правки конфигурации уходят из процесса: изменение базового слоя делается в одном репозитории и проходит те же проверки, что и код. При настройке эталонного образа мы опираемся на CIS Benchmarks — требования безопасности проверяются автоматически, а не глазами дежурного.
Предсказуемость стендов становится измеримой: один и тот же дайджест образа даёт одинаковое поведение на любом узле, а откат сводится к переключению на предыдущий тег.
Режимы обновления и контроль версий образов
Политика базовых образов отвечает на один вопрос: кто и когда решает, что основа сервиса изменилась. Сбой проявляется не в момент смены — несовместимость библиотек или непропатченная уязвимость всплывают через несколько релизов, когда причина уже потеряна в истории сборок.
Ключевая развилка — жёсткое закрепление версии против плавающих меток. Закрепление по неизменяемому хешу даёт повторяемость: та же основа, тот же результат. Плавающая метка приносит свежие исправления без правок в коде, но делает обновление неуправляемым событием.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Жёсткое закрепление версии по хешу | Регулируемые сервисы, воспроизводимые сборки, аудит | Патчи не приходят сами — нужен регламент обновления |
| Плавающие метки | Внутренние сервисы, тестовые стенды | Сборка ломается в случайный момент, откат неочевиден |
| Полное пересоздание сборки | Плановое обновление, подготовка к крупному релизу | Долгий прогон проверок, нужен параллельный стенд |
| Слои надстройки | Свои патчи поверх готовой основы | Растёт число слоёв, сложнее отследить происхождение |
Дальше — совместимость версий. Ведём матрицу «версия основы × зависимости сервиса» и прогоняем по ней сборку: если библиотека требует более старую ветку, конкретный сервис остаётся на ней, остальные уходят вперёд. Слои надстройки собираем только из внутреннего репозитория — обновление основы не тянет за собой непроверенный код, а пересоздание сборки запускается по расписанию, а не по факту сбоя.
Этапы внедрения: от аудита реестра до регламента
Порядок шагов здесь не формальность: правила, написанные до инвентаризации, ломают сборки команд, чьи зависимости вы ещё не видели. Поэтому идём от фактов к регламенту — каждый этап даёт вход для следующего.
- Аудит реестра. Выгружаем образы и теги, отмечаем, что работает в продакшене, а что тянется как родительский слой. На выходе — список с датами сборки и владельцами сервисов.
- Схема зависимостей. Строим граф: сервис → базовый образ → общие слои. Видно, сколько команд затронет смена образа и какие сборки переводить первыми.
- Настройка правил сборки. Фиксируем разрешённые базовые образы и их источник, политику тегов, проверку подписи. Сборка из непроверенного источника блокируется автоматически, а не уговорами в чате.
- Проверка на стенде. Прогоняем один-два сервиса на новых правилах: системные библиотеки, сертификаты, права доступа. Конфликт дешевле поймать здесь, чем на релизе.
- Откат и исключения. Убеждаемся, что предыдущие образы доступны и откат занимает минуты, а для старого сервиса есть временное исключение с датой пересмотра.
- Передача регламента. Отдаём документ и обучаем команду: как добавить новый базовый образ, кто согласует, что делать при отклонённой сборке.
После этого правило живёт в процессе сборки, а не в инструкции: нарушение видно сразу, а не на разборе инцидента.
Регламенты обновления, схемы и карта зависимостей
Регламент — не документ ради документа, а набор артефактов, по которым ваша команда работает без нас. Каждый пункт привязан к действию: кто вправе менять базовый образ, в каком порядке сборка попадает в рабочий контур, что делать ночью, если в базовом слое нашли критическую уязвимость. Ниже — комплект, который остаётся у вас после внедрения политики базовых образов.
- Регламент обновления — периодичность пересборки, срок жизни тега и ответственный за выпуск.
- Карта зависимостей — какой сервис на каком базовом образе собран, кто владелец и какие слои он наследует; обновляется при каждой сборке.
- Политики доступа — кто публикует образ в реестр, кто только читает, кто утверждает исключения; права разведены по ролям.
- Порядок исключений — форма временного отступления: обоснование, срок, владелец, дата пересмотра; ни одно не теряется и попадает в отчёт.
- Схема окружений — какие теги разрешены в тестовом контуре, какие в рабочем, как сборка продвигается между ними.
- Инструкция дежурной смены — пошаговый порядок при критической уязвимости: оценка охвата, пересборка, откат.
- Отчётность — доля сервисов на актуальном образе, открытые исключения, время от выхода исправления до развёртывания.
Кейс: как убрали расхождения сред и ускорили выпуск
До внедрения политики базовых образов девять команд собирали базовый слой каждая по-своему: зависимости подтягивались в момент сборки, и один и тот же сервис на шести стендах получал разные системные библиотеки.
Расхождение сред стоило дороже, чем выглядело в отчётах. Примерно каждый четвёртый выкат падал на старте из-за несовпадения версий библиотек, а разбор причин занимал больше времени, чем сама сборка. Полный цикл сборки занимал около 11 минут, шесть из них уходили на установку зависимостей из внешних источников.
Зафиксировали один родительский образ с описанным составом пакетов и свели сборку и хранение артефактов в Harbor. Дочерние образы собираются только от проверенного родителя, обновление идёт пересборкой по расписанию и при появлении уязвимостей в базовых пакетах, а не правками в каждом репозитории.
После перехода стенды перестали расходиться — доля различающихся пакетов упала с трети до нуля. Сборка сократилась до трёх минут за счёт общего родителя и кэширования слоёв, размер образов уменьшился втрое после удаления лишних утилит. Класс отказов «на стенде работало, в продуктивной среде нет» ушёл, при этом откат на предыдущий тег остался доступен: старые образы хранятся в реестре и подписаны.
Чем отличается жёсткое закрепление от рекомендательного режима?
Разница проявляется в момент, когда проверка не пройдена. Жёсткое правило блокирует сборку: базовый образ не из доверенного реестра или не прошёл проверку на уязвимости — артефакт не выпускается. Рекомендательный режим фиксирует то же нарушение, но пропускает сборку: отклонение попадает в отчёт.
Жёсткие правила окупаются там, где поток сборок большой и команд много. В мягком режиме предупреждения копятся, а старые базовые слои живут месяцами — однажды уязвимость находится сразу в двадцати сервисах. Блокировка выравнивает всех: обновление базового слоя перестаёт быть доброй волей отдельной команды.
Обратная сторона — срочное исправление. Когда критическую уязвимость надо закрыть сейчас, а нужный образ ещё не прошёл полный цикл проверки, жёсткая политика встаёт поперёк: патч готов, выпустить нельзя. Инженеры идут в обход — правят политику вручную или тянут неучтённую ветку, и управляемость сборки от этого падает.
Компромисс режимов выглядит как два маршрута внутри одной политики. Общий поток идёт по жёстким правилам, а для аварийного исправления остаётся отдельный путь: рекомендательный режим с обязательной регистрацией исключения — кто выпустил, на какой срок, чем обосновал. Исключение живёт ограниченное время и затем автоматически возвращает сборку в жёсткий режим.
Политика версионируется вместе с кодом, каждая сборка знает, под какую её ревизию прошла, а число действующих исключений — измеримая величина. Растущий список исключений сам подсказывает, где правила слишком строгие, а где базовые образы обновляются реже, чем нужно командам.
Технические сомнения: сканирование, подписи, совместимость
Происхождение проверяется дважды: базовый слой фиксируется по digest, а не по плавающему тегу, и на выходе образ получает подпись и аттестацию. Перед выкатом контроль допуска в кластер сверяет подпись с ключом доверия — подменённый образ просто не доходит до развёртывания. Целостность сборки перестаёт зависеть от дисциплины, а готовые инструменты подписи вроде Sigstore закрывают эту часть без самописных скриптов.
Переход на политику делаем поэтапно, иначе первый же релиз упирается в чужую сборку. Сначала она работает в режиме аудита, затем блокирует продовые пространства имён, и только потом — все остальные. Сборка, которая пока тянет легаси-образ, получает временное исключение с владельцем и датой пересмотра.
Совместимость с текущими сборками не сломается?
Ломается только то, что тянет образы без сопровождения. Для нестандартных баз — свои среды исполнения, нативные модули — собираем минимальный слой и вносим его в список разрешённых. Приложение собирается как раньше, меняется родительский слой.
Сканирование уязвимостей не затормозит конвейер?
Сканируем дельту и кешируем отчёт по digest: тот же слой повторно не проверяется. На каждый коммит — критические уровни, полный отчёт — по расписанию.
Как откатиться, если новая база ломает релиз?
Старый образ остаётся в реестре: правило хранения держит последние сборки на тег, поэтому возврат — смена digest в манифесте, а не пересборка. Исключение из политики описано как код и откатывается вместе с ним.
Обсудим задачу: аудит реестра и план внедрения
Аудит реестра начинается не с отчёта, а с доступа к фактам: без инвентаризации образов и понимания, кто и как их собирает, любая политика базовых образов останется декларацией. Поэтому порядок старта такой — вы присылаете вводные, мы разбираем реестр и конвейеры сборки, затем возвращаемся с планом внедрения и оценкой работ по этапам.
Для оценки достаточно приложить:
- перечень базовых образов и тегов в реестре с указанием владельцев сервисов;
- несколько примеров файлов сборки из разных команд — от давних сервисов до свежих;
- настройки конвейеров сборки и правила сканирования образов на уязвимости;
- схему доступа к реестру: кто публикует, кто только читает, где лежат ключи;
- требования по безопасности и изоляции сред, которые политика должна закрыть;
- список сервисов, которые нельзя останавливать, и удобное окно для изменений.
Дальше мы сверяем факты с практикой: смотрим дубли базовых образов, дрейф тегов, срок жизни слоёв и сколько сборок обходит проверки. На выходе — план внедрения по этапам: от заморозки списка допущенных базовых образов до автоматической проверки в конвейере и отката на предыдущий образ, если правило блокирует релиз.
Обсудим задачу — опишите её в свободной форме, и мы вернёмся с оценкой работ, сроками и порядком старта.







