LLM-релиз — не только git SHA. Поведение создаёт связка кода, prompt-а, модели, инструментов, policy, индекса, памяти и runtime-настроек. Откат контейнера не откатывает то, что живёт снаружи.
Код откатили, поведение — нет
После релиза ассистент вызывает refund без обязательного подтверждения. Команда возвращает прошлый образ, но ошибка остаётся: gateway всё ещё отдаёт новую tool schema, managed model указывает на новый snapshot, а RAG читает переиндексированные документы. «Версия приложения» не описывала приложение.
Behavioral release manifest
Manifest — неизменяемый документ, из которого можно воспроизвести поведение или честно сказать, что воспроизведение невозможно.
release_id: support-assistant/2026-08-17.3
created_from: git:7c1e...
code:
image: registry.example/assistant@sha256:...
prompts:
triage: {uri: git:prompts/triage.md, sha256: "..."}
model:
provider: example
model_id: model-x
snapshot: model-x-2026-07-01
parameters: {temperature: 0.2, max_output_tokens: 600}
tools:
schema_bundle_sha256: "..."
implementations: {refund: refund-api/v3}
policy:
bundle: policy/2026-08-10
sha256: "..."
retrieval:
index_alias: kb-green
index_build_id: kb/2026-08-16.2
corpus_snapshot: s3://.../manifest.json
embedding_model: embed-x@2026-05
chunker: chunker/v4
memory:
schema: memory/v2
read_policy: rp/4
write_policy: wp/3
evals:
dataset: golden/38@sha256:...
judge_manifest: judge/39@sha256:...
report: eval-run/01J...
compatibility:
api_contract: assistant-response/v3
min_client: 5.4.0
memory_reads: [memory/v1, memory/v2]
memory_writes: memory/v2
provenance:
builder: ci/workflow@sha256:...
created_at: 2026-08-17T10:30:00ZВсе идентификаторы и даты здесь — пример, не норматив. Секреты в manifest не кладут. URI должен вести на immutable artifact; тег latest, плавающий model alias и перезаписываемый файл воспроизводимость уничтожают. Manifest подпишите или хотя бы храните digest и provenance рядом с deployment record.
На каждом запросе логируйте release_id, а для асинхронной задачи сохраняйте его в payload. Иначе job, поставленный старой версией, исполнится новой без следа.
Совместимость — матрица, а не SemVer
SemVer полезен для API, но не доказывает behavioral compatibility. Проверяйте границы компонентов:
producer -> artifact -> consumer -> правило
app v3 -> tool args v2 -> refund API v3 -> validate + contract tests
indexer4 -> index build4 -> retriever3 -> запрещено
memory1 -> records v1 -> app v2 -> read-compatible
app v2 -> records v2 -> app v1 rollback-> dual-write или migration requiredМинимальный набор проверок кандидата:
def verify_release(m):
verify_digests_and_signature(m)
validate_manifest_schema(m)
assert model_snapshot_available(m.model)
contract_test_tools(m.tools)
contract_test_api(m.compatibility.api_contract)
smoke_test_retrieval(m.retrieval.index_build_id)
read_old_memory_write_new_test(m.memory)
run_eval_report(m.evals)
dry_run_rollback(m)Изменение считается несовместимым, если старый consumer не может безопасно прочитать новый artifact или rollback начинает интерпретировать его иначе. Особо опасны:
- удаление/переименование enum в structured output;
- изменение единиц, timezone или значения
null; - новая tool schema при старой реализации;
- смена embedding model без полного rebuild индекса;
- изменение chunker/ACL-фильтра при прежнем alias;
- новая memory schema, которую старый код не читает;
- policy update, меняющий разрешённые действия без новых adversarial evals.
Blue-green для индекса
Индекс нельзя «обновлять на месте», если нужен быстрый rollback. Стройте green рядом с обслуживающим blue:
corpus snapshot
-> build green
-> validate count/ACL/schema
-> fixed query set: recall + forbidden-document checks
-> shadow reads and latency
-> atomic alias switch blue -> green
-> keep blue read-only through rollback windowЗапрос должен видеть один index_build_id от начала до конца. Cache key включает build ID. При переключении не смешивайте embeddings старой и новой модели. Rollback — возврат alias, а не срочная ночная переиндексация.
Для memory/data migration применяйте expand/contract: сначала новый код читает старое и новое, затем backfill/dual-write, затем переключение чтения, и только после истечения rollback window удаляется старый формат.
Release gate и расследование
CI собирает manifest из артефактов, запрещает mutable references, проверяет compatibility и прикрепляет eval report. CD разворачивает manifest digest, а не набор независимых параметров. Runtime endpoint /version возвращает release ID и безопасные component IDs.
При инциденте ответьте одним запросом:
request_id -> release_id -> exact prompt/model/tool/policy/index/memory/evalЕсли цепочка рвётся, root cause останется гипотезой.
Failure modes:
- manifest создан после деплоя и не соответствует факту;
- prompt загружается из UI и меняется без нового release ID;
- provider alias обновился незаметно;
- rollback образа оставил новую БД, memory или index alias;
- eval report относится к другому digest;
- старый blue удалён сразу после переключения;
- manifest содержит версии, но не content digests.
Правило главы
Единица релиза — behavioral manifest. Версионируйте и связывайте всё, что меняет ответ или действие системы. Откат считается готовым только после проверки совместимости состояния и внешних артефактов.
Практическая проверка
- Manifest включает code, prompt, model snapshot/params, tool schema+implementation, policy, index/corpus/embedding/chunker, memory и eval report.
- Все ссылки immutable и проверяются digest-ом; секретов нет.
- Request/job содержит
release_id. - Contract tests покрывают предыдущего и нового producer/consumer.
- Индекс переключается blue-green атомарным alias; старый сохранён для rollback.
- Memory migration допускает откат старого кода.
- Выполнен rehearsal: deploy candidate → smoke/eval → rollback → повторная проверка.
Первичные источники
- Kubernetes Deployments: rollout, revision и rollback
- Kubernetes API deprecation guide: правила совместимости API
- SLSA Provenance