Files
admin/.wiki/concepts/books-vds-memory-optimize-runbook.md

103 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "books VDS — оптимизация памяти (mongo wiredTiger / ES heap / CI-остатки)"
type: concept
tags: [runbook, books, vds, mongo, elasticsearch, oom, memory, backup, admin]
related: [concepts/runbooks-index.md, concepts/gitea-project-create-runbook.md]
updated: 2026-08-28
---
# books VDS — оптимизация памяти (OOM → ECONNREFUSED)
> **⚙️ СЛУЖЕБНЫЙ РАНБУК — только для администратора проекта `.admin`.**
> Применять/выполнять шаги может только **`.admin`** (оператор проекта admin). Другим проектам/агентам — читать по запросу, не выполнять.
> Из проекта не выносить: не копировать в другие вики, не пересказывать, не публиковать.
> Нужен деплой или прод-операция по этому ранбуку — **поставить задачу админу (`.admin`) и написать письмо**. Админ выполняет, остальные верифицируют.
## Scope
Остановить **OOM-цикл** на books VDS (`89.253.255.133`, host4g VPS, CentOS 7), который
вызывает `[sched:slovo] sync.failed: ECONNREFUSED 172.20.0.5:27017`. Причина — дефицит ОЗУ:
хост 3.9GB RAM, free ~136MB, **swap 100%**, OOM-kill `mongod` (dmesg `Out of memory: Kill
process (mongod) score ~114`). Симптом-задача — «ozon fbs products syncronization» (books-sched, прод slovo).
## Артефакты
- **Хост:** `89.253.255.133` (books VDS). SSH: `ssh -i ~/.ssh/id_ed25519_books_ops root@89.253.255.133`.
- **Креды:** `<из pass books-vds/full-env>` (`BOOKS_DB_*`, `BOOKS_MONGO_*`, `BOOKS_PORTAINER_*`).
- **mongo (БД sched):** `books-job-scheduler-mongo` = `172.20.0.5:27017`, image `mongo:4.2`,
БД `agendaDb` (sched-задачи: `sched_tasks`, `sched_schedules`, `sched_runs`). Source-of-truth compose:
`/usr/docker/books-job-scheduler/docker-compose.yml` (**files-based**, НЕ Portainer-kzntsv).
- **ES:** `elasticsearch` (стек 33, `/usr/docker/elasticsearch/docker-compose.yml`, `ES_JAVA_OPTS=-Xmx256m`),
`bookva-es` (**Portainer стек 37, endpoint 1**; `ES_JAVA_OPTS` урезан 512m→`-Xmx256m`).
- **CI-остатки:** `buildx_buildkit_builder-*` (`moby/buildkit:buildx-stable-1`), удалены.
## Диагностика (как понять, что это OOM)
```bash
ssh root@89.253.255.133 '
free -m; dmesg | grep -iE "oom|killed process" | tail; # free ~136MB, swap 100%, Killed (mongod)
docker stats --no-stream --format "{{.MemUsage}}\t{{.Name}}" | sort -rh | head; # кто жрёт
'
```
Кто жрёт (на 2026-08-28): `books-job-scheduler-mongo` 715MiB (главный), `minio` 248+140, `elasticsearch` 242, `bookva-es` 223.
## Шаги (по порядку эффекта)
### 1. Урезать `books-job-scheduler-mongo` wiredTiger (главный фикс, ~+450MB)
```bash
cd /usr/docker/books-job-scheduler
cp docker-compose.yml docker-compose.yml.bak
# вставить после " restart: always" в сервисе books-job-scheduler-mongo:
# command: ["mongod", "--wiredTigerCacheSizeGB", "0.25"]
docker compose up -d books-job-scheduler-mongo
```
Verify: `docker logs books-job-scheduler-mongo | grep -i "cache_size"``cache_size=256M`;
`docker exec books-job-scheduler-mongo mongo --quiet --eval "db.runCommand({ping:1}).ok"` = 1.
### 2. Снести CI-остатки `buildx_buildkit_builder-*` (сироты от CI)
```bash
docker rm -f buildx_buildkit_builder-1ba06752-bf56-4b50-88c5-ce1b48f44a4e0 buildx_buildkit_builder-f61c259c-48e3-4401-b2ca-2404c5cd76070
```
### 3. Урезать ES heap (вторично; elasticsearch уже 256m)
`bookva-es``ES_JAVA_OPTS=-Xms512m -Xmx512m``-Xms256m -Xmx256m`.
Сделано: Portainer PUT стека 37 (`PUT /api/stacks/37?endpointId=1` с реконструированным compose). Verify: `docker logs bookva-es | grep heap``heap size [256mb]`.
### 4. `minio` / `bookva-minio` / `books-ops-mcp` — cgroup-потолки памяти
Реконструкция compose вслепую рискованна (данные minio-тома, files-секреты, сеть) → `docker update --memory` (без пересоздания):
```bash
docker update --memory 512m --memory-swap 512m minio
docker update --memory 384m --memory-swap 384m bookva-minio
# books-ops-mcp (Node) — 'memory.memsw.limit_in_bytes: device or resource busy' (cgroup v1) — не применилось.
```
Потолки (защита от раздувания в пик; не освобождают текущие буферы).
## Verify / smoke
- `free -m` — free растёт, swap падает (mongo cache_size=256M).
- Нет новых `Out of memory: Kill (mongod)` в dmesg на следующем окне (~06:06).
- `docker stats``books-job-scheduler-mongo` ≪715MiB.
- sched-задачи (`ozon fbs products syncronization`) больше не дают `ECONNREFUSED 172.20.0.5:27017`.
## Rollback
- mongo: `git checkout`-возврат `command` в compose (или `cp docker-compose.yml.bak docker-compose.yml`) → `docker compose up -d books-job-scheduler-mongo`.
- ES: вернуть `ES_JAVA_OPTS`.
## Gotchas
1. **OOM ежедневно ~06:06** — пик в бэкап-окно (mongodump+mariadb-dump+ES snapshot в 06:00 MSK). Урезка снижает, но ХОСТ обделён (3.9GB) — радикальный фикс = апгрейд RAM или Manticore вместо ES.
2. **Книги-стеки — через `portainer.kzntsv.site` endpoint 1 (= books VDS)**: `GET /api/stacks` показывает id 2251 (books/web/api/ntfy/ops-mcp/chrome/proxy/imgproxy/minio/mongo/db/elasticsearch + bookva-*). Часть из них — **files-based** `/usr/docker/*/docker-compose.yml` (напр. books-job-scheduler-mongo урезан файлом + `docker compose up -d`). При правке стека держать Portainer-источник и файл синхронными, не плодить расхождения.
3. **`com.docker.compose.project.config_files=/data/compose/22`** (label) — старый путь Portainer; `/data/compose/*` на диске НЕ существует. Реальный источник — `/usr/docker/*/docker-compose.yml`.
4. **compose-файлы в CRLF** (`\r\n`) — python-патч учитывать line-ending (иначе needle не матчит).
5. **`bookva-es`** — **Portainer стек 37 (endpoint 1)**. Доступ есть: `BOOKS_PORTAINER_URL` + `BOOKS_PORTAINER_API_KEY` из `pass books-vds/full-env`. НО `GET /api/stacks/:id` НЕ отдаёт `stackFileContent` (в этой версии Portainer), поэтому compose реконструируется из `docker inspect` и обновляется через `PUT` стека. Не менять вслепую без этих данных.
6. **mongo warning XFS** — предупреждение, не ошибка (данные на ext4).
7. **`command` массив** в compose: `command: ["mongod", "--wiredTigerCacheSizeGB", "0.25"]` — строку тоже можно, но список надёжнее.
## Будущее направление — замена ES → Manticore
ES в стеке книг — источник перегруза (Java JVM). **Manticore Search** — без Java, легче
(сотни MB против 500+MB), быстрее на полнотекстовом поиске. Оправдано, если ES используется
для полнотекстового поиска товаров/книг (не анализа/DSL-агрегаций). Тогда урезать оба ES,
переписать поиск на Manticore-протокол (SphinxQL/HTTP) и бэкапы. Отдельная задача/ранбук.