ops: 13 ГБ из 113 занятых — логи двух контейнеров без ротации; наши compose вообще без потолка #2761

Open
opened 2026-08-06 22:10:27 +00:00 by bot-backend · 3 comments
Collaborator

Найдено при починке хранения логов trade-in (#2741). Тот PR закрыл свой стек; замер попутно показал, что основной рост идёт не оттуда.

Замер (прод, 2026-08-06 22:10 UTC)

диск:  145 G всего · 113 G занято · 32 G свободно · 79 %

логи контейнеров, МБ:
  10 580   forgejo             ← ~128 МБ/сутки, ротации НЕТ
   2 470   glitchtip-worker    ← ~30 МБ/сутки, ротации НЕТ
     156   gendesign-postgres-1
      33   gendesign-site-finder-1
      21   gendesign-couchdb
       4   forgejo-runner

13 ГБ из 113 занятых — логи двух контейнеров. Оба растут без ограничения, оба вне этого репозитория.

При нынешнем темпе (~158 МБ/сутки от этой пары) 32 свободных гигабайта уходят примерно за 200 дней. Это не аврал, но это единственный процесс на машине, который гарантированно упрётся в потолок сам по себе.

Разделение: что чиним мы, что к владельцу

В репозитории (наше). Корневые docker-compose.yml и docker-compose.prod.yml не содержат секции ограничения логов вообще — то есть у всего основного стека потолка нет. Сегодня это ~210 МБ и проблемой не является, но ограничение стоит поставить сейчас, пока оно дёшево: у trade-in та же правка уже сделана (#2758, драйвер journald).

Вне репозитория (к владельцу). forgejo и glitchtip-worker управляются не отсюда — их конфигурации в этом репозитории отсутствуют (проверено: git ls-files не содержит их compose-файлов). Ограничение или ротацию для них может поставить только тот, у кого они лежат.

Отдельная деталь про GlitchTip: он и так хранит тела событий только с 01.08, то есть уже теряет данные — при 2.4 ГБ логов самого воркера. Похоже, ограничение там стоит не на том уровне, где нужно.

Побочно

Три контейнера-задачи раннера (FORGEJO-ACTIONS-TASK-…) висят 3–6 недель — утёкшие, не убранные после выполнения. Сами по себе места почти не занимают, но это признак, что уборка после задач не отрабатывает; стоит посмотреть, не растёт ли их число.

Связано: #2741, #2758.

Найдено при починке хранения логов trade-in (#2741). Тот PR закрыл свой стек; замер попутно показал, что основной рост идёт не оттуда. ## Замер (прод, 2026-08-06 22:10 UTC) ``` диск: 145 G всего · 113 G занято · 32 G свободно · 79 % логи контейнеров, МБ: 10 580 forgejo ← ~128 МБ/сутки, ротации НЕТ 2 470 glitchtip-worker ← ~30 МБ/сутки, ротации НЕТ 156 gendesign-postgres-1 33 gendesign-site-finder-1 21 gendesign-couchdb 4 forgejo-runner ``` **13 ГБ из 113 занятых — логи двух контейнеров.** Оба растут без ограничения, оба вне этого репозитория. При нынешнем темпе (~158 МБ/сутки от этой пары) 32 свободных гигабайта уходят примерно за **200 дней**. Это не аврал, но это единственный процесс на машине, который гарантированно упрётся в потолок сам по себе. ## Разделение: что чиним мы, что к владельцу **В репозитории (наше).** Корневые `docker-compose.yml` и `docker-compose.prod.yml` не содержат секции ограничения логов **вообще** — то есть у всего основного стека потолка нет. Сегодня это ~210 МБ и проблемой не является, но ограничение стоит поставить сейчас, пока оно дёшево: у trade-in та же правка уже сделана (#2758, драйвер journald). **Вне репозитория (к владельцу).** `forgejo` и `glitchtip-worker` управляются не отсюда — их конфигурации в этом репозитории отсутствуют (проверено: `git ls-files` не содержит их compose-файлов). Ограничение или ротацию для них может поставить только тот, у кого они лежат. Отдельная деталь про GlitchTip: он **и так хранит тела событий только с 01.08**, то есть уже теряет данные — при 2.4 ГБ логов самого воркера. Похоже, ограничение там стоит не на том уровне, где нужно. ## Побочно Три контейнера-задачи раннера (`FORGEJO-ACTIONS-TASK-…`) висят **3–6 недель** — утёкшие, не убранные после выполнения. Сами по себе места почти не занимают, но это признак, что уборка после задач не отрабатывает; стоит посмотреть, не растёт ли их число. Связано: #2741, #2758.
Author
Collaborator

Две ошибки в теле этой задачи — мои

1. glitchtip-worker — НЕ вне репозитория. Он наш.

Я написал, что оба гиганта управляются не отсюда, и отдал 2.59 ГБ владельцу. Проверка была неверной: я искал отдельный compose-файл и не увидел сервис внутри нашего.

docker inspect glitchtip-worker
  project      = gendesign
  config_files = /opt/gendesign/docker-compose.prod.yml   ← наш файл
.env: COMPOSE_PROFILES=glitchtip                          ← профиль активен

Это 81% всего роста стека (31.9 МБ/сутки), и починить его можно было и нужно было самим — что и сделано в PR #2762. Вне репозитория остался только forgejo (10.6 ГБ).

Урок тот же, что весь день: искал по неверному признаку (файл вместо сервиса) и получил уверенный неправильный ответ.

2. Корневой docker-compose.yml трогать было нельзя.

Задача называет оба файла. Второй — для локальной разработки: в виртуальной машине Docker Desktop journald нет, и общий anchor сломал бы запуск у всех локально. Правка ушла только в прод-файл.

Результат правки — по факту

диск: 113 → 111 ГБ занято, 32 → 34 ГБ свободно, 79% → 77%
glitchtip-worker (2470 МБ) исчез из списка растущих без потолка
5xx после деплоя: 0  (до деплоя было 10×500 + 3×502)

Проверка хранения — записью контейнера, которого больше нет: docker inspect 38e297cda702No such object, а его строки от 22:31:35 читаются в журнале.

Ловушка чтения перепроверена и жива: пользователь деплоя в группах docker,sudo без прав на журнал, голый journalctl отвечает «записей нет». Обход через docker работает, им и снят весь вывод выше. Разовая команда sudo usermod -aG adm gendesign снимет костыль.

Что действительно осталось владельцу

  • forgejo — 10.6 ГБ, ~128 МБ/сутки, ротации нет. Теперь это единственный неограниченный источник роста; лежит в /home/gendesign/forgejo/docker-compose.yml.
  • Осиротевший gendesign-site-finder-1 (33 МБ, 81 день): сервиса с таким именем в compose нет, поэтому up -d его не трогает и он остаётся на старом драйвере. Чинится флагом удаления сирот, но это меняет поведение деплоя для всего стека — решение ваше.
  • Контейнеры-задач раннера: было 3, стало 4. Подозрение подтвердилось, число растёт.
## Две ошибки в теле этой задачи — мои **1. `glitchtip-worker` — НЕ вне репозитория. Он наш.** Я написал, что оба гиганта управляются не отсюда, и отдал 2.59 ГБ владельцу. Проверка была неверной: я искал **отдельный compose-файл** и не увидел сервис **внутри нашего**. ``` docker inspect glitchtip-worker project = gendesign config_files = /opt/gendesign/docker-compose.prod.yml ← наш файл .env: COMPOSE_PROFILES=glitchtip ← профиль активен ``` Это **81% всего роста стека** (31.9 МБ/сутки), и починить его можно было и нужно было самим — что и сделано в PR #2762. Вне репозитория остался только `forgejo` (10.6 ГБ). Урок тот же, что весь день: **искал по неверному признаку** (файл вместо сервиса) и получил уверенный неправильный ответ. **2. Корневой `docker-compose.yml` трогать было нельзя.** Задача называет оба файла. Второй — для локальной разработки: в виртуальной машине Docker Desktop journald нет, и общий anchor сломал бы запуск у всех локально. Правка ушла только в прод-файл. ## Результат правки — по факту ``` диск: 113 → 111 ГБ занято, 32 → 34 ГБ свободно, 79% → 77% glitchtip-worker (2470 МБ) исчез из списка растущих без потолка 5xx после деплоя: 0 (до деплоя было 10×500 + 3×502) ``` Проверка хранения — записью контейнера, которого больше нет: `docker inspect 38e297cda702` → `No such object`, а его строки от 22:31:35 читаются в журнале. Ловушка чтения перепроверена и **жива**: пользователь деплоя в группах `docker,sudo` без прав на журнал, голый `journalctl` отвечает «записей нет». Обход через docker работает, им и снят весь вывод выше. Разовая команда `sudo usermod -aG adm gendesign` снимет костыль. ## Что действительно осталось владельцу - **`forgejo` — 10.6 ГБ, ~128 МБ/сутки, ротации нет.** Теперь это единственный неограниченный источник роста; лежит в `/home/gendesign/forgejo/docker-compose.yml`. - **Осиротевший `gendesign-site-finder-1`** (33 МБ, 81 день): сервиса с таким именем в compose нет, поэтому `up -d` его не трогает и он остаётся на старом драйвере. Чинится флагом удаления сирот, но это меняет поведение деплоя для всего стека — решение ваше. - **Контейнеры-задач раннера: было 3, стало 4.** Подозрение подтвердилось, число растёт.
Author
Collaborator

Наша половина закрыта и проверена. Половина владельца — нет, и она БОЛЬШАЯ. Задача остаётся открытой.

Замер на проде 2026-08-07 09:0x UTC.

Что сделано (наше)

Весь основной стек и trade-in переведены на journald — проверено по HostConfig.LogConfig живых контейнеров:

journald:  tradein-backend · tradein-scraper · tradein-browser · tradein-frontend
           gendesign-backend-1 · worker · postgres · glitchtip-web · glitchtip-worker

glitchtip-worker (2 470 МБ, 81% роста стека) из списка растущих без потолка исчез — его json-file больше не существует. Журнал: 2 408 МБ при потолке 4 ГБ с самовытеснением.

Что НЕ сделано (владельца) — и оно продолжает расти

forgejo   10 621 МБ   json-file, ротации нет   ← было 10 580 МБ на момент заведения задачи

За неполные сутки +41 МБ. Это единственный неограниченный источник роста на машине, и он же — 90% исходной цифры «13 ГБ». Лежит в /home/gendesign/forgejo/docker-compose.yml, вне этого репозитория.

Диск при этом ушёл в худшую сторону, а не в лучшую:

2026-08-06 22:10 (заведение задачи)   113 G занято · 32 G свободно · 79 %
2026-08-06 22:29 (сразу после #2762)  111 G занято · 34 G свободно · 77 %
2026-08-07 09:0x (сейчас)             116 G занято · 29 G свободно · 81 %

То есть эффект правки (−2 ГБ разово) уже съеден, и оценка «32 свободных гигабайта на 200 дней» из тела задачи оптимистична: рост идёт не только от логов.

Остальное из тела задачи, тоже открыто

  • Осиротевший gendesign-site-finder-1 — 33 МБ, по-прежнему json-file. Сервиса с таким именем в compose нет, up -d его не трогает. Чинится флагом удаления сирот, но это меняет поведение деплоя для всего стека — решение владельца.
  • Контейнеры-задачи раннера растут: было 3 на момент заведения, 4 в комментарии выше, сейчас 4 висящих (FORGEJO-ACTIONS-TASK-14123, -14121 по 3 недели, -8583, -7610 по 6 недель). Подозрение «уборка после задач не отрабатывает» подтверждено ростом, но причина не установлена.
  • Отдельная деталь про GlitchTip из тела задачи в силе: тела событий он хранит только с 01.08, то есть теряет данные независимо от объёма логов воркера.

Закрывать нечего: правка сняла 19% проблемы и оставила 81% там, куда мы дотянуться не можем.

## Наша половина закрыта и проверена. Половина владельца — нет, и она БОЛЬШАЯ. Задача остаётся открытой. Замер на проде 2026-08-07 09:0x UTC. ### Что сделано (наше) Весь основной стек и trade-in переведены на journald — проверено по `HostConfig.LogConfig` живых контейнеров: ``` journald: tradein-backend · tradein-scraper · tradein-browser · tradein-frontend gendesign-backend-1 · worker · postgres · glitchtip-web · glitchtip-worker ``` `glitchtip-worker` (2 470 МБ, 81% роста стека) из списка растущих без потолка **исчез** — его json-file больше не существует. Журнал: 2 408 МБ при потолке 4 ГБ с самовытеснением. ### Что НЕ сделано (владельца) — и оно продолжает расти ``` forgejo 10 621 МБ json-file, ротации нет ← было 10 580 МБ на момент заведения задачи ``` За неполные сутки +41 МБ. Это единственный неограниченный источник роста на машине, и он же — 90% исходной цифры «13 ГБ». Лежит в `/home/gendesign/forgejo/docker-compose.yml`, вне этого репозитория. Диск при этом ушёл в худшую сторону, а не в лучшую: ``` 2026-08-06 22:10 (заведение задачи) 113 G занято · 32 G свободно · 79 % 2026-08-06 22:29 (сразу после #2762) 111 G занято · 34 G свободно · 77 % 2026-08-07 09:0x (сейчас) 116 G занято · 29 G свободно · 81 % ``` То есть эффект правки (−2 ГБ разово) уже съеден, и оценка «32 свободных гигабайта на 200 дней» из тела задачи оптимистична: рост идёт не только от логов. ### Остальное из тела задачи, тоже открыто - **Осиротевший `gendesign-site-finder-1`** — 33 МБ, по-прежнему `json-file`. Сервиса с таким именем в compose нет, `up -d` его не трогает. Чинится флагом удаления сирот, но это меняет поведение деплоя для всего стека — решение владельца. - **Контейнеры-задачи раннера растут**: было 3 на момент заведения, 4 в комментарии выше, сейчас **4 висящих** (`FORGEJO-ACTIONS-TASK-14123`, `-14121` по 3 недели, `-8583`, `-7610` по 6 недель). Подозрение «уборка после задач не отрабатывает» подтверждено ростом, но причина не установлена. - Отдельная деталь про GlitchTip из тела задачи в силе: тела событий он хранит только с 01.08, то есть теряет данные независимо от объёма логов воркера. Закрывать нечего: правка сняла 19% проблемы и оставила 81% там, куда мы дотянуться не можем.
Author
Collaborator

Разбор оставшихся 81%: срочности нет, но есть скрытая зависимость

Замер 2026-08-07 10:30 UTC. Проверял, потому что в разборе прозвучало «диск ушёл с 79% на 81%, эффект правки съеден» — направление верное, но так это читается как убегающий диск, а он не убегает.

Где 117 ГБ из 145

docker (образы 20.9 + контейнеры 2.8 + тома 58.7) ~82 ГБ
/opt/gendesign 17 ГБ
/home 4.9 ГБ
/var/log 2.7 ГБ

Внутри /opt/gendesign почти всё — резервные копии, 11 ГБ. И вот главное: они ротируются правильно.

gendesign_20260801 … gendesign_20260807   ровно 7 файлов, по ~1.4 ГБ
tradein/  20260801 … 20260807             ровно 7 файлов, 1.7 ГБ суммарно

Обе задачи в cron, обе держат недельное окно. Это не свалка, а установившееся состояние.

Скорость роста и запас

Дамп основной БД вырос с 1409280222 байт (01.08) до 1436875068 (07.08) — +27 МБ за шесть суток, около 4.5 МБ/сутки в сжатом виде. При недельном окне это даёт примерно 30-40 МБ/сутки на весь каталог, что сходится с наблюдением «+41 МБ/сутки».

При 28 ГБ свободного и таком темпе запас — порядка двух лет. Рост при этом законный: он отражает рост самой базы, а не утечку.

Поэтому: 79% → 81% — факт, но вывод «стало хуже, чем при заведении» вводит в заблуждение по срочности. Правка #2762 сделала то, что должна была (наш стек на journald, glitchtip-worker убран), а оставшийся объём — это работающие резервные копии и данные, а не мусор.

Что действительно стоит поправить — и это не про место

Журнал systemd: 2.4 ГБ на диске, при этом /etc/systemd/journald.conf пуст — секция [Journal] есть, все параметры закомментированы, drop-in нет. То есть потолок не задан явно и работает по умолчанию.

Значение имеет второй умолчательный параметр, не первый. SystemKeepFree держит 15% файловой системы свободными, и при их исчерпании journald перестаёт писать. Для 145 ГБ это порог около 21.75 ГБ свободного; сейчас свободно 28 ГБ, то есть запас до порога — примерно 6 ГБ, а не 28.

Отсюда неприятное свойство: вчерашняя правка «логи переживают пересоздание контейнера» имеет необъявленную зависимость от свободного места. Когда диск подойдёт к порогу, отказ будет выглядеть не как «диск кончился», а как «логов за вчера почему-то нет» — то есть ровно тот симптом, ради устранения которого правка делалась, и в форме, которую трудно связать с причиной.

Предлагаю задать потолок явно (SystemMaxUse= + SystemKeepFree=), чтобы отказ был предсказуемым: старые записи ротируются, а не отключается запись. Это правка одной строки, но она в системной конфигурации хоста, поэтому делать не буду без вашего слова — скажите, и сделаю.

Мелочь для полноты

docker system df считает пригодным к освобождению 2.7 ГБ томов и 0.7 ГБ образов (99 висящих томов — почти все по 0-8 КБ, это следы задач раннера). Трогать не стал: выигрыш 3 ГБ против риска задеть том, который кто-то считает живым, того не стоит. Если решите чистить — docker volume prune на боевом хосте это ваше действие, не моё.

## Разбор оставшихся 81%: срочности нет, но есть скрытая зависимость Замер 2026-08-07 10:30 UTC. Проверял, потому что в разборе прозвучало «диск ушёл с 79% на 81%, эффект правки съеден» — направление верное, но так это читается как убегающий диск, а он не убегает. ### Где 117 ГБ из 145 | | | |---|---| | docker (образы 20.9 + контейнеры 2.8 + тома 58.7) | ~82 ГБ | | `/opt/gendesign` | 17 ГБ | | `/home` | 4.9 ГБ | | `/var/log` | 2.7 ГБ | Внутри `/opt/gendesign` почти всё — **резервные копии, 11 ГБ**. И вот главное: **они ротируются правильно**. ``` gendesign_20260801 … gendesign_20260807 ровно 7 файлов, по ~1.4 ГБ tradein/ 20260801 … 20260807 ровно 7 файлов, 1.7 ГБ суммарно ``` Обе задачи в cron, обе держат недельное окно. Это не свалка, а установившееся состояние. ### Скорость роста и запас Дамп основной БД вырос с **1409280222** байт (01.08) до **1436875068** (07.08) — **+27 МБ за шесть суток**, около 4.5 МБ/сутки в сжатом виде. При недельном окне это даёт примерно **30-40 МБ/сутки** на весь каталог, что сходится с наблюдением «+41 МБ/сутки». При **28 ГБ свободного** и таком темпе запас — порядка **двух лет**. Рост при этом законный: он отражает рост самой базы, а не утечку. Поэтому: 79% → 81% — факт, но вывод «стало хуже, чем при заведении» вводит в заблуждение по срочности. Правка #2762 сделала то, что должна была (наш стек на journald, `glitchtip-worker` убран), а оставшийся объём — это работающие резервные копии и данные, а не мусор. ### Что действительно стоит поправить — и это не про место Журнал systemd: **2.4 ГБ на диске**, при этом `/etc/systemd/journald.conf` пуст — секция `[Journal]` есть, все параметры закомментированы, drop-in нет. То есть потолок **не задан явно** и работает по умолчанию. Значение имеет второй умолчательный параметр, не первый. `SystemKeepFree` держит **15% файловой системы свободными**, и при их исчерпании journald **перестаёт писать**. Для 145 ГБ это порог около **21.75 ГБ свободного**; сейчас свободно 28 ГБ, то есть запас до порога — **примерно 6 ГБ**, а не 28. Отсюда неприятное свойство: вчерашняя правка «логи переживают пересоздание контейнера» имеет **необъявленную зависимость от свободного места**. Когда диск подойдёт к порогу, отказ будет выглядеть не как «диск кончился», а как «логов за вчера почему-то нет» — то есть ровно тот симптом, ради устранения которого правка делалась, и в форме, которую трудно связать с причиной. Предлагаю задать потолок явно (`SystemMaxUse=` + `SystemKeepFree=`), чтобы отказ был предсказуемым: старые записи ротируются, а не отключается запись. Это правка одной строки, но она в системной конфигурации хоста, поэтому **делать не буду без вашего слова** — скажите, и сделаю. ### Мелочь для полноты `docker system df` считает пригодным к освобождению 2.7 ГБ томов и 0.7 ГБ образов (99 висящих томов — почти все по 0-8 КБ, это следы задач раннера). Трогать не стал: выигрыш 3 ГБ против риска задеть том, который кто-то считает живым, того не стоит. Если решите чистить — `docker volume prune` на боевом хосте это ваше действие, не моё.
lekss361 added the
chore
observability
scope/devops
labels 2026-08-16 10:25:19 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2761
No description provided.