Compare commits
2 Commits
3bc9992350
...
3adbe839f2
| Author | SHA1 | Date | |
|---|---|---|---|
| 3adbe839f2 | |||
| 9a92ff0b87 |
@@ -1,44 +1,54 @@
|
|||||||
---
|
---
|
||||||
_last_updated_: 2026-07-05T09:15:00Z
|
_last_updated_: 2026-07-05T11:45:00Z
|
||||||
session_id: 2026-07-05-snolla-0-42-1-tirazh-live-redeploys
|
session_id: 2026-07-05-snolla-tirazh-mem-limits
|
||||||
---
|
---
|
||||||
|
|
||||||
# Next session handoff
|
# Next session handoff
|
||||||
|
|
||||||
## Итог сессии: тираж snolla 0.42.1 — 3 live-prod in-place редеплоя ЗАКРЫТЫ + зафиксированы в вике
|
## Итог сессии: метрики тиража snolla + mem_limit 512m всем 5 стекам
|
||||||
Оператор дал отмашку «хуярь деплой + пуш». Три уже-боевых на VDS сайта обновлены **in-place** на движке 0.42.1 (order-tag фикс liquid 0.10.2), каждый — acceptance на НОВОМ образе С VDS против прод-оракула ДО подмены, затем env-preserving swap тега → live-smoke GREEN. Все три прога квитированы (Notify=сам сайт). Пропуск по вике (таски просили using-wiki) закрыт в конце сессии.
|
|
||||||
|
|
||||||
| Сайт | Стек | Новый образ | Было | Rollback-тег |
|
Начали со съёма health-метрик тиража (user: «не распухает ли память, не жрут ли ЦПУ»). Вывод: все snolla-сайты здоровы — CPU ~0.5% одного ядра в среднем, RAM 100–206 MB, нет reclaim-трэша / OOM-давления. На машину (13 GiB, 6 vCPU) влияние в пределах шума; главный едок RAM на боксе — `mssql` (2.1 GB).
|
||||||
|---|---|---|---|---|
|
|
||||||
| labtools.ru | 17 | `labtools:566d41c` | 0.28.2 | `labtools:43e28ba` |
|
|
||||||
| emspb.ru | 18 | `emspb:95a5c42` | 0.28.4 | `emspb:b6e361a` |
|
|
||||||
| labtools.pro | 19 | `labtools-pro:0610432` | 0.28.7 | `labtools-pro:7bd9fae` |
|
|
||||||
|
|
||||||
Рецепт (durable): [`concepts/snolla-live-prod-inplace-image-bump.md`](../.wiki/concepts/snolla-live-prod-inplace-image-bump.md) — build→throwaway-staging-acceptance-С-VDS→`put-stack.js` PUT→live-smoke. Пер-сайт секции «0.42.1 bump» в трёх deploy-рунбуках.
|
**Нашёл дыру:** ни один snolla-стек не нёс `mem_limit` → cgroup-cap = вся память хоста (12.9 GiB). Течь в любом контейнере могла съесть весь бокс. По просьбе user'а выставил **`mem_limit: 512m`** всем пяти (env-preserving Portainer PUT, секреты вернул verbatim) + синхронизировал source-of-truth compose в репо.
|
||||||
|
|
||||||
|
| Стек | Id | limit | статус |
|
||||||
|
|---|---|---|---|
|
||||||
|
| labtools.ru | 17 | 512 MiB ✓ | healthy |
|
||||||
|
| emspb | 18 | 512 MiB ✓ | healthy |
|
||||||
|
| labtools.pro | 19 | 512 MiB ✓ | healthy (200 внешним smoke) |
|
||||||
|
| tandemmebel | 20 | 512 MiB ✓ | healthy (ещё staging-хост) |
|
||||||
|
| kupimknigi | 21 | 512 MiB ✓ | healthy |
|
||||||
|
|
||||||
|
Проверено: `ops.docker.stats` → `limit`=536870912 на всех. Пересоздание = секунды простоя, теги не поехали (`pullImage:false`).
|
||||||
|
|
||||||
|
**Durable-правило закреплено** (user: «дальше не забывать выставлять лимиты»):
|
||||||
|
- вики-канон [`portainer-stack-management-vds § Convention`](../.wiki/concepts/portainer-stack-management-vds.md) — app-стек обязан нести mem_limit;
|
||||||
|
- [`snolla-live-prod-inplace-image-bump`](../.wiki/concepts/snolla-live-prod-inplace-image-bump.md) step 6 — пункт чеклиста;
|
||||||
|
- авто-память `vds-app-stacks-need-mem-limit`.
|
||||||
|
|
||||||
## Recent commits
|
## Recent commits
|
||||||
- `8e3e5b43` wiki(snolla-0.42.1): рецепт + 3 рунбука + index/log
|
- `9a92ff0b` chore(vds): mem_limit 512m всему тиражу snolla (5 стеков + compose + вики)
|
||||||
- `0fd1c695` fix(labtools.pro): press-forms счётчик 13→12
|
- `3bc99923` meta(handoff): тираж 0.42.1 закрыт
|
||||||
- `bcb4dc36` deploy(labtools.pro): LIVE 0.42.1 (стек 19)
|
- `8e3e5b43` wiki(snolla-0.42.1): рецепт + 3 рунбука
|
||||||
- `<earlier>` deploy(labtools.ru+emspb): LIVE 0.42.1 (стеки 17/18)
|
|
||||||
- `78f23a65` cutover(kupimknigi): LIVE на VDS
|
|
||||||
|
|
||||||
## Open треки
|
## Open треки
|
||||||
| Трек | Готовность | Entry-point |
|
| Трек | Готовность | Entry-point |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **tandemmebel.ru cutover** (последний из тиража) | staging GREEN, стек 20 `tandemmebel:ed96b18` (0.42.0), ждёт DNS | Триггер = **владелец флипает reg.ru `tandemmebel.ru`+www→89.253.255.94**. Порядок в STATUS.md-блоке `[tandemmebel-web-vds-deploy]`: verify авторит.NS (`Resolve-DnsName -Server ns1.reg.ru`) → ТОЛЬКО ПОТОМ боевой `Host()` в стек 20 (LE-порядок критичен) → live-smoke (gallery-DoD 12/12). Если origin уехал — пересобрать HEAD, ре-DoD. |
|
| **tandemmebel.ru cutover** (последний из тиража) | staging GREEN, стек 20 `tandemmebel:ed96b18` (0.42.0), mem_limit стоит, ждёт DNS | Триггер = **владелец флипает reg.ru `tandemmebel.ru`+www→89.253.255.94**. Порядок в STATUS.md-блоке `[tandemmebel-web-vds-deploy]`: verify авторит.NS → ТОЛЬКО ПОТОМ боевой `Host()` в стек 20 (LE-порядок критичен) → live-smoke (gallery-DoD 12/12). Если origin уехал — пересобрать HEAD, ре-DoD. К cutover можно сразу бампнуть до 0.42.1. |
|
||||||
| morethencms-s3-filestorage-provider | 🟡 ждёт `.dll` от прога MoreThenCms | STATUS.md-блок |
|
| morethencms-s3-filestorage-provider | 🟡 ждёт `.dll` от прога MoreThenCms | STATUS.md-блок |
|
||||||
| fix-nl-vds-reality-pq-dest | 🟡 ждёт client-side (user меняет SNI) | STATUS.md-блок |
|
| fix-nl-vds-reality-pq-dest | 🟡 ждёт client-side (user меняет SNI) | STATUS.md-блок |
|
||||||
| harden-books-vds-exposed-ports / kreknin-self-backup | ⚪ backlog | STATUS.md-блоки |
|
| harden-books-vds-exposed-ports / kreknin-self-backup | ⚪ backlog | STATUS.md-блоки |
|
||||||
|
|
||||||
## Спроси user'а
|
## Спроси user'а
|
||||||
- **Версии тиража разъехались:** kupimknigi (стек 21) + tandemmebel (стек 20) на **0.42.0**, три сегодняшних на **0.42.1** (order-фикс). Добампить kupimknigi/tandemmebel до 0.42.1 для единого пина, или оставить? (Пока не просили; tandemmebel всё равно пересобирать к cutover — там можно сразу 0.42.1.)
|
- **Версии тиража разъехались:** kupimknigi (21) + tandemmebel (20) на **0.42.0**, три остальных на **0.42.1** (order-фикс). Добампить оба до 0.42.1 для единого пина, или оставить? tandemmebel всё равно пересобирать к cutover — там сразу 0.42.1.
|
||||||
|
- Опционально: поставить периодический снапшот RAM трёх свежих (17/18/19) на пару суток, чтобы поймать дрейф во времени (одним снимком течь за дни не доказать). Не просили — предложение висит.
|
||||||
|
|
||||||
## Не делать (preemptive guards)
|
## Не делать (preemptive guards)
|
||||||
- **tandemmebel:** НЕ трогать стек 20 / НЕ вставлять боевой Host ДО подтверждённого DNS-флипа на **обоих** авторит.NS (иначе LE HTTP-01 упадёт на RUVDS → сожжём rate-limit). Флип делает владелец, не мы.
|
- **tandemmebel:** НЕ трогать стек 20 / НЕ вставлять боевой Host ДО подтверждённого DNS-флипа на **обоих** авторит.NS (иначе LE HTTP-01 упадёт на RUVDS → сожжём rate-limit). Флип делает владелец.
|
||||||
- **RUVDS IIS 80.64.31.36** — НЕ декоммишн (rollback-путь всех мигрированных сайтов). Биндинги labtools.ru/pro оставлены как rollback (в отличие от emspb, снятого 07-02).
|
- **RUVDS IIS 80.64.31.36** — НЕ декоммишн (rollback всех мигрированных). Биндинги labtools.ru/pro оставлены как rollback.
|
||||||
- Отмашка «хуярь деплой» этой сессии = только тираж 0.42.1 live-редеплоев. На новые боевые apply — спрашивать заново (needs-human класс).
|
- Новые app-стеки / правки существующих — **всегда с `mem_limit`** (см. вики-конвенцию), синхронно в Portainer И compose-копию.
|
||||||
- Смоук snolla-доменов гнать **С VDS** (воркстейшн ловит LAN-DNS-перехват прод-доменов).
|
- Смоук snolla-доменов гнать **С VDS** (воркстейшн ловит LAN-DNS-перехват прод-доменов).
|
||||||
|
|
||||||
## Memory updates за сессию
|
## Memory updates за сессию
|
||||||
- Нового в `~/.claude/.../memory/` не писал (рецепт ушёл в durable вику-concept, не в память). Существующие релевантные: `workstation-lan-dns-serves-local-cms-copy`, `operator-dns-flip-verify-domain-before-cutover`, `ps51-iso8859-corrupts-portainer-stackfile`, `smoke-crawl-real-pages-not-two-routes` — все подтвердились на практике этой сессии.
|
- Новая: `vds-app-stacks-need-mem-limit` (durable-правило про лимиты).
|
||||||
|
- Подтвердились: `ps51-iso8859-corrupts-portainer-stackfile` (обошёл PS-грабли, PUT слал UTF-8-байтами), `workstation-lan-dns-serves-local-cms-copy` (smoke через `--resolve`).
|
||||||
|
|||||||
@@ -68,6 +68,22 @@ curl -ksS -X POST "$PORTAINER_URL/api/stacks/create/standalone/string?endpointId
|
|||||||
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" --data "$PAYLOAD"
|
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" --data "$PAYLOAD"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Convention: `mem_limit` на app-стеках (обязательно)
|
||||||
|
|
||||||
|
**Каждый app/site-стек несёт `mem_limit`.** Без него cgroup-`limit` = вся память хоста (12.9 GiB) →
|
||||||
|
одна течь в контейнере может съесть весь бокс, а не упереться в свой потолок. С `restart: unless-stopped`
|
||||||
|
упор в лимит = OOM-kill контейнера + авто-подъём (изоляция вместо каскада на всю машину).
|
||||||
|
|
||||||
|
- **standalone-стек (не swarm) → ключ `mem_limit`**, НЕ `deploy.resources.limits.memory` (тот игнорится вне swarm).
|
||||||
|
- Значение = ~2.5–5× наблюдаемого пика. snolla-сайты (Node SSR, baseline ~100–200 MB) → **`512m`**.
|
||||||
|
Прочерк-пример: owncloud oCIS → `1g`.
|
||||||
|
- Ставить в момент создания/правки стека — не откладывать. Проверка постфактум: `ops.docker.stats <name>`
|
||||||
|
поле `limit` == заданному (512m = 536870912), не 13890813952.
|
||||||
|
- **Синхронизировать обе копии**: боевой стек в Portainer (PUT) И source-of-truth compose в
|
||||||
|
`admin/host-stacks/vds-kzntsv/<img>.compose.yml`. Иначе следующий redeploy из гита откатит лимит.
|
||||||
|
|
||||||
|
Применено 2026-07-05 ко всему тиражу snolla (labtools.ru/17, emspb/18, labtools.pro/19, tandemmebel/20, kupimknigi/21) → все `512m`.
|
||||||
|
|
||||||
## Gotchas
|
## Gotchas
|
||||||
|
|
||||||
1. **`env_file: .env` ломает Portainer string-mode** — Portainer не материализует `.env` файл в `/data/compose/<id>/`. Compose pull fails: `env file /data/compose/<id>/.env not found`. Fix: `sed '/^\s*env_file:/d'` + передавать env через API `env` array.
|
1. **`env_file: .env` ломает Portainer string-mode** — Portainer не материализует `.env` файл в `/data/compose/<id>/`. Compose pull fails: `env file /data/compose/<id>/.env not found`. Fix: `sed '/^\s*env_file:/d'` + передавать env через API `env` array.
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ META=/tmp/st<ID>.json node put-stack.js <stackId> <endpointId=1> <oldTag> <newTa
|
|||||||
|
|
||||||
### 6. Закрытие
|
### 6. Закрытие
|
||||||
Compose source-of-truth (`admin/host-stacks/vds-kzntsv/<img>.compose.yml`) — обновить тег + коммент rollback.
|
Compose source-of-truth (`admin/host-stacks/vds-kzntsv/<img>.compose.yml`) — обновить тег + коммент rollback.
|
||||||
|
**Проверить `mem_limit`** на стеке (обязателен для всех app-стеков — см. [[portainer-stack-management-vds]] § Convention).
|
||||||
|
snolla → `512m`; если стек его ещё не несёт (старые до 2026-07-05) — добавить в этот же PUT и в compose-копию.
|
||||||
Борд-таска 🟢, отчёт прогу (Notify=сам сайт, минуя workshop), rollback-тег остаётся в registry.
|
Борд-таска 🟢, отчёт прогу (Notify=сам сайт, минуя workshop), rollback-тег остаётся в registry.
|
||||||
|
|
||||||
## put-stack.js (env-preserving Portainer stack PUT)
|
## put-stack.js (env-preserving Portainer stack PUT)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ services:
|
|||||||
container_name: emspb
|
container_name: emspb
|
||||||
image: registry.kzntsv.site/emspb:95a5c42 # git-sha victor/emspb.ru master (snolla 0.42.1, bump 2026-07-05; prev b6e361a=0.28.4=rollback)
|
image: registry.kzntsv.site/emspb:95a5c42 # git-sha victor/emspb.ru master (snolla 0.42.1, bump 2026-07-05; prev b6e361a=0.28.4=rollback)
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only).
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: Europe/Moscow
|
TZ: Europe/Moscow
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ services:
|
|||||||
container_name: kupimknigi
|
container_name: kupimknigi
|
||||||
image: registry.kzntsv.site/kupimknigi:9608ff6 # git-sha victor/kupimknigi.spb.ru (snolla 0.42.0 / core 0.24.0 / data 0.14.1)
|
image: registry.kzntsv.site/kupimknigi:9608ff6 # git-sha victor/kupimknigi.spb.ru (snolla 0.42.0 / core 0.24.0 / data 0.14.1)
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only).
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: Europe/Moscow
|
TZ: Europe/Moscow
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ services:
|
|||||||
container_name: labtools-pro
|
container_name: labtools-pro
|
||||||
image: registry.kzntsv.site/labtools-pro:0610432 # git-sha victor/labtools.pro master (snolla 0.42.1, bump 2026-07-05; prev 7bd9fae=0.28.7=rollback)
|
image: registry.kzntsv.site/labtools-pro:0610432 # git-sha victor/labtools.pro master (snolla 0.42.1, bump 2026-07-05; prev 7bd9fae=0.28.7=rollback)
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only).
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: Europe/Moscow
|
TZ: Europe/Moscow
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ services:
|
|||||||
container_name: labtools
|
container_name: labtools
|
||||||
image: registry.kzntsv.site/labtools:566d41c # git-sha victor/labtools.ru master (snolla 0.42.1, bump 2026-07-05; prev 43e28ba=0.28.2=rollback)
|
image: registry.kzntsv.site/labtools:566d41c # git-sha victor/labtools.ru master (snolla 0.42.1, bump 2026-07-05; prev 43e28ba=0.28.2=rollback)
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only).
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: Europe/Moscow
|
TZ: Europe/Moscow
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ services:
|
|||||||
container_name: tandemmebel
|
container_name: tandemmebel
|
||||||
image: registry.kzntsv.site/tandemmebel:ed96b18 # git-sha victor/tandemmebel.ru master (snolla 0.42.0 / core 0.24.0 / data 0.14.1 — viewmodel-graph + blog-archive)
|
image: registry.kzntsv.site/tandemmebel:ed96b18 # git-sha victor/tandemmebel.ru master (snolla 0.42.0 / core 0.24.0 / data 0.14.1 — viewmodel-graph + blog-archive)
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
mem_limit: 512m # guardrail от runaway: snolla baseline ~100-200M; OOM в контейнере → restart:unless-stopped поднимет. standalone-compose → mem_limit (НЕ deploy.resources — то swarm-only).
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: Europe/Moscow
|
TZ: Europe/Moscow
|
||||||
|
|||||||
Reference in New Issue
Block a user