Гипотеза #21 — «кэши остались заводскими, суммарно на тринадцать гигабайт» — опровергнута опытом. В коробке на гигабайт ClickHouse сам понижает каждый
кэш до 512 МиБ, а на стенде без данных они пусты.
Настоящая причина — сама коробка. Праздная нода держит VmRSS 846 МиБ, из
которых 530 МиБ — страницы её собственного бинарника: файл clickhouse весит
790 МБ, ядро подгружает куски по мере обращения, а отказ по превышению
сравнивается с RSS. На работу оставалось около 350 МиБ, и двадцать прогонов
пробника их выбирали.
Второе: предел 3,4 ГБ никто не выдавал. Это была оценка расхода из спеки,
посчитанная по стенду-предшественнику до первой сборки v2 и превращённая в
жёсткий порог. Порог стал критерием приёмки каждого этапа — и дальше блокировал
бы любой рост стенда на этапах 2-9.
Что сделано
ADR 0004. Бюджета памяти у стенда нет, есть требование к машине — около
8 ГБ, доступных Docker. Ресурсный довод ADR 0001 отозван (сами решения в силе
по своим основаниям; ближайшее следствие — вопрос triggerer на этапе 5
решается по существу, а не по остатку памяти).
Нодам ClickHouse 4 ГиБ. Остальные лимиты не тронуты. Числа, выставленные
ради прежнего бюджета, названы в ADR и лишены статуса решения: кто в них
упрётся, меняет по первому свидетельству.
Проверка суммы убрана. Она мерила docker stats вместе со страничным
кэшем и с появлением настоящих данных краснела бы на здоровом стенде — ровно
тот грех, который уже осуждён в ADR 0002.
Взамен smoke спрашивает у Docker, не убивало ли ядро контейнер за память
и не включалась ли политика перезапуска. Порога нет, ответ «да или нет».
Дыра реальная: убитый контейнер Docker поднимает сам, healthcheck зеленеет, и
стенд рапортует «всё хорошо» о ноде, которая умирала.
README и спека переписаны с предела на требование к машине; README
объясняет, что такое «память, доступная Docker», и как её поднять в WSL2.
Проверка
команда
итог
make config-test
зелено
make smoke
25 из 25
make smoke-cluster
8 из 8
make smoke-guards
3 из 3, включая шаг «после восстановления стенд проходит make smoke» — тот, что падал 31 июля
На живом стенде с новой коробкой: max_server_memory_usage = 3,60 ГиБ, в
журнале Lowered mark cache size to 2.00 GiB because the system has limited RAM.
Семантика счётчиков Docker снята отдельными контейнерами: ручной restart
оставляет RestartCount = 0 (значит документированный перезапуск нод проверку
не роняет), убийство за память даёт OOMKilled = true и растущий счётчик,
убийство не за память OOMKilled не поднимает.
Что осталось за рамками
Рассуждение проходило слепое ревью свежей сессией: из десяти опорных утверждений
четыре оказались неверны и в PR не попали. Подробности — в ADR.
Closes #21
Разбор задачи #21 увёл в сторону от её собственной гипотезы, поэтому решение
записано отдельным ADR: [ADR 0004 «Ограничения ресурсов на стенде»](docs/adr/0004-resource-limits.md).
## Что выяснилось
Гипотеза #21 — «кэши остались заводскими, суммарно на тринадцать гигабайт» —
**опровергнута опытом**. В коробке на гигабайт ClickHouse сам понижает каждый
кэш до 512 МиБ, а на стенде без данных они пусты.
Настоящая причина — сама коробка. Праздная нода держит `VmRSS` 846 МиБ, из
которых 530 МиБ — страницы её собственного бинарника: файл `clickhouse` весит
790 МБ, ядро подгружает куски по мере обращения, а отказ по превышению
сравнивается с RSS. На работу оставалось около 350 МиБ, и двадцать прогонов
пробника их выбирали.
Второе: предел 3,4 ГБ никто не выдавал. Это была оценка расхода из спеки,
посчитанная по стенду-предшественнику **до первой сборки v2** и превращённая в
жёсткий порог. Порог стал критерием приёмки каждого этапа — и дальше блокировал
бы любой рост стенда на этапах 2-9.
## Что сделано
- **ADR 0004.** Бюджета памяти у стенда нет, есть требование к машине — около
8 ГБ, доступных Docker. Ресурсный довод ADR 0001 отозван (сами решения в силе
по своим основаниям; ближайшее следствие — вопрос triggerer на этапе 5
решается по существу, а не по остатку памяти).
- **Нодам ClickHouse 4 ГиБ.** Остальные лимиты не тронуты. Числа, выставленные
ради прежнего бюджета, названы в ADR и лишены статуса решения: кто в них
упрётся, меняет по первому свидетельству.
- **Проверка суммы убрана.** Она мерила `docker stats` вместе со страничным
кэшем и с появлением настоящих данных краснела бы на здоровом стенде — ровно
тот грех, который уже осуждён в ADR 0002.
- **Взамен** smoke спрашивает у Docker, не убивало ли ядро контейнер за память
и не включалась ли политика перезапуска. Порога нет, ответ «да или нет».
Дыра реальная: убитый контейнер Docker поднимает сам, healthcheck зеленеет, и
стенд рапортует «всё хорошо» о ноде, которая умирала.
- **README и спека** переписаны с предела на требование к машине; README
объясняет, что такое «память, доступная Docker», и как её поднять в WSL2.
## Проверка
| команда | итог |
| --- | --- |
| `make config-test` | зелено |
| `make smoke` | 25 из 25 |
| `make smoke-cluster` | 8 из 8 |
| `make smoke-guards` | 3 из 3, включая шаг «после восстановления стенд проходит make smoke» — тот, что падал 31 июля |
На живом стенде с новой коробкой: `max_server_memory_usage` = 3,60 ГиБ, в
журнале `Lowered mark cache size to 2.00 GiB because the system has limited RAM`.
Семантика счётчиков Docker снята отдельными контейнерами: ручной `restart`
оставляет `RestartCount` = 0 (значит документированный перезапуск нод проверку
не роняет), убийство за память даёт `OOMKilled` = true и растущий счётчик,
убийство не за память `OOMKilled` не поднимает.
## Что осталось за рамками
Рассуждение проходило слепое ревью свежей сессией: из десяти опорных утверждений
четыре оказались неверны и в PR не попали. Подробности — в ADR.
Зачем
Стенд упирался в память ноды ClickHouse: пробник валился на CREATE TABLE
ON CLUSTER, вместе с ним краснели make smoke и make smoke-guards. Причина не
та, что предполагал #21: дело не в заводских кэшах, а в коробке на гигабайт.
Около 550 МиБ RSS праздной ноды — страницы её собственного бинарника, и на
работу оставалось около 350 МиБ, которые пробник добирал за сессию.
Заодно выяснилось, откуда взялся предел 3,4 ГБ. Это была оценка расхода из
спеки, посчитанная по стенду-предшественнику до первой сборки v2 и превращённая
в жёсткий порог проверки. Порог стал критерием приёмки каждого этапа и дальше
блокировал бы любой рост стенда на этапах 2-9.
Что
- ADR 0004: бюджета памяти у стенда нет, есть требование к машине — около 8 ГБ,
доступных Docker. Ресурсный довод ADR 0001 отозван, сами решения в силе.
- Нодам ClickHouse 4 ГиБ вместо гигабайта. Остальные лимиты не тронуты: ни один
из них ни разу не сработал, а снять их скопом — то же изменение без
свидетельств, каким они были выставлены.
- Из make smoke убрана проверка суммарного потребления. Она мерила docker stats
вместе со страничным кэшем, то есть отвечала на вопрос «сколько файлов стенд
потрогал», и с появлением настоящих данных краснела бы на здоровом стенде.
Вместе с ней убрана привязанная к её сообщению проверка docs-guards.
- Взамен smoke спрашивает у Docker, не убивало ли ядро долгоживущий контейнер
за память и не включалась ли политика перезапуска. Порога у проверки нет:
убитый контейнер Docker поднимает сам, и без этого вопроса стенд отрапортует
«всё хорошо» о ноде, которая умирала.
- README и раздел «Ресурсный бюджет» спеки переписаны с предела на требование
к машине; README объясняет менти, что такое «память, доступная Docker».
Проверка
make config-test; make up; make smoke — 25 из 25; make smoke-cluster — 8 из 8;
make smoke-guards — 3 из 3, включая шаг «после восстановления стенд проходит
make smoke», который падал 31 июля.
На живом стенде с новой коробкой: max_server_memory_usage = 3,60 ГиБ, в журнале
ноды «Lowered mark cache size to 2.00 GiB because the system has limited RAM».
Семантика счётчиков Docker снята отдельными контейнерами: ручной restart
оставляет RestartCount = 0, убийство за память даёт OOMKilled = true и растущий
счётчик, убийство не за память OOMKilled не поднимает.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем
Двухосевое ревью нашло в PR фактическую ошибку и одну процессную дыру. Ошибка
того же класса, что уже снималась по ходу разбора: в ADR было записано, будто
RSS ноды полз вверх из-за страниц её бинарника. Замер на живой ноде это
опроверг.
Что
- ADR 0004: причина дрейфа переписана по замеру. За обычную сессию страницы
бинарника 523 -> 531 МиБ, то есть стоят на месте, а рабочая память
489 -> 723 МиБ. Бинарник объясняет постоянную часть расхода, а не рост;
отчего растёт рабочая память, для этого решения знать не нужно. Вывод не
меняется: одна только постоянная часть занимала больше половины гигабайтной
коробки.
- ADR 0001: ресурсный довод отозван прямо в файле — и строкой статуса, и
абзацем после самого довода. Обе оси ревью нашли это независимо друг от
друга: строка «удерживает стенд в пределе 3,4 ГБ» читалась как действующая,
хотя предела уже нет.
- stand-smoke.sh: OOMKilled поднимается и тогда, когда ядро убило процесс
внутри живого контейнера, поэтому сообщение говорит про процесс, а не про
контейнер. Флаг hurt переименован в problems и считает находки — как passed
и failed по соседству.
- Формулировки ADR 0004 упрощены: «коробка» объясняется при первом упоминании,
а метафоры «вход в самонастройку», «предохранители», «бронь», «полка» и
«бюджет в новой одежде» заменены обычными словами. Правило AGENTS.md —
сложную мысль пояснять при первом упоминании.
Проверка
make config-test — зелено. make smoke — 25 из 25, проверка выживания отработала
с новым сообщением.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем
Комментарии к правке были размером с объяснение, хотя объяснение уже лежит
в ADR 0004. В compose.yaml четыре строки на одну настройку; в stand-smoke.sh
одиннадцать новых строк там, где на весь файл до этого было две — шебанг и
одна строка про разбор подстановок. Заодно в комментариях остались метафоры
(«бронь», «предохранители»), вычищенные из ADR прошлым коммитом.
Что
- compose.yaml: одна строка вместо четырёх — почему не гигабайт и куда идти
за подробностями.
- stand-smoke.sh: две строки вместо шести — зачем проверка вообще нужна.
Комментарий про разбор `--format` убран целиком: он оправдывался перед
читателем, а не помогал ему.
- Комментарий про OOMKilled оставлен, но в одну строку: без него сообщение
«убило процесс, а не контейнер» выглядит опиской.
Проверка
make config-test — зелено.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ddmitry
merged commit c6c9e1082a into main2026-08-01 15:29:09 +03:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #21
Разбор задачи #21 увёл в сторону от её собственной гипотезы, поэтому решение
записано отдельным ADR: ADR 0004 «Ограничения ресурсов на стенде».
Что выяснилось
Гипотеза #21 — «кэши остались заводскими, суммарно на тринадцать гигабайт» —
опровергнута опытом. В коробке на гигабайт ClickHouse сам понижает каждый
кэш до 512 МиБ, а на стенде без данных они пусты.
Настоящая причина — сама коробка. Праздная нода держит
VmRSS846 МиБ, изкоторых 530 МиБ — страницы её собственного бинарника: файл
clickhouseвесит790 МБ, ядро подгружает куски по мере обращения, а отказ по превышению
сравнивается с RSS. На работу оставалось около 350 МиБ, и двадцать прогонов
пробника их выбирали.
Второе: предел 3,4 ГБ никто не выдавал. Это была оценка расхода из спеки,
посчитанная по стенду-предшественнику до первой сборки v2 и превращённая в
жёсткий порог. Порог стал критерием приёмки каждого этапа — и дальше блокировал
бы любой рост стенда на этапах 2-9.
Что сделано
8 ГБ, доступных Docker. Ресурсный довод ADR 0001 отозван (сами решения в силе
по своим основаниям; ближайшее следствие — вопрос triggerer на этапе 5
решается по существу, а не по остатку памяти).
ради прежнего бюджета, названы в ADR и лишены статуса решения: кто в них
упрётся, меняет по первому свидетельству.
docker statsвместе со страничнымкэшем и с появлением настоящих данных краснела бы на здоровом стенде — ровно
тот грех, который уже осуждён в ADR 0002.
и не включалась ли политика перезапуска. Порога нет, ответ «да или нет».
Дыра реальная: убитый контейнер Docker поднимает сам, healthcheck зеленеет, и
стенд рапортует «всё хорошо» о ноде, которая умирала.
объясняет, что такое «память, доступная Docker», и как её поднять в WSL2.
Проверка
make config-testmake smokemake smoke-clustermake smoke-guardsНа живом стенде с новой коробкой:
max_server_memory_usage= 3,60 ГиБ, вжурнале
Lowered mark cache size to 2.00 GiB because the system has limited RAM.Семантика счётчиков Docker снята отдельными контейнерами: ручной
restartоставляет
RestartCount= 0 (значит документированный перезапуск нод проверкуне роняет), убийство за память даёт
OOMKilled= true и растущий счётчик,убийство не за память
OOMKilledне поднимает.Что осталось за рамками
Рассуждение проходило слепое ревью свежей сессией: из десяти опорных утверждений
четыре оказались неверны и в PR не попали. Подробности — в ADR.