{ "uid": "gendesign-host", "title": "Хост и контейнеры", "description": "CPU, память, диск и контейнеры обоих хостов. Метка host: infra = Beget (Forgejo, GlitchTip, мониторинг), apps = Poincare (Птица и МЕРА).", "tags": ["gendesign", "infra"], "timezone": "browser", "editable": false, "schemaVersion": 39, "refresh": "1m", "time": { "from": "now-6h", "to": "now" }, "templating": { "list": [ { "name": "host", "type": "query", "datasource": { "type": "prometheus", "uid": "prometheus" }, "query": "label_values(node_uname_info, host)", "refresh": 1, "includeAll": true, "multi": true, "current": { "text": "All", "value": "$__all" } } ] }, "panels": [ { "type": "row", "title": "Сводка", "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 } }, { "type": "stat", "title": "Свободно на корневом разделе", "description": "Место, оставшееся на /. При заполнении диска Postgres останавливается — это не «медленно», а полная остановка записи.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 5, "w": 6, "x": 0, "y": 1 }, "targets": [ { "refId": "A", "expr": "node_filesystem_avail_bytes{mountpoint=\"/\", host=~\"$host\"}", "legendFormat": "{{host}}" } ], "fieldConfig": { "defaults": { "unit": "bytes", "thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null }, { "color": "orange", "value": 10737418240 }, { "color": "green", "value": 32212254720 } ] } }, "overrides": [] }, "options": { "colorMode": "value", "graphMode": "area", "textMode": "auto" } }, { "type": "stat", "title": "Доступно памяти", "description": "MemAvailable — то, что ядро реально может отдать под новую нагрузку. Отличается от «free»: кэш страниц отдаётся по требованию и в нехватку не считается.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 5, "w": 6, "x": 6, "y": 1 }, "targets": [ { "refId": "A", "expr": "node_memory_MemAvailable_bytes{host=~\"$host\"}", "legendFormat": "{{host}}" } ], "fieldConfig": { "defaults": { "unit": "bytes", "thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null }, { "color": "orange", "value": 1073741824 }, { "color": "green", "value": 3221225472 } ] } }, "overrides": [] }, "options": { "colorMode": "value", "graphMode": "area", "textMode": "auto" } }, { "type": "stat", "title": "Загрузка (load1 на ядро)", "description": "Нормировано на число ядер: 1.0 означает «занято ровно столько, сколько есть». Без нормировки число несравнимо между хостами с разным CPU.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 5, "w": 6, "x": 12, "y": 1 }, "targets": [ { "refId": "A", "expr": "node_load1{host=~\"$host\"} / count by (host) (node_cpu_seconds_total{mode=\"idle\", host=~\"$host\"})", "legendFormat": "{{host}}" } ], "fieldConfig": { "defaults": { "unit": "short", "decimals": 2, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 0.8 }, { "color": "red", "value": 1.5 } ] } }, "overrides": [] }, "options": { "colorMode": "value", "graphMode": "area", "textMode": "auto" } }, { "type": "stat", "title": "Аптайм", "description": "Время с последней загрузки. Внезапное обнуление — перезагрузка, о которой стоит знать.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 5, "w": 6, "x": 18, "y": 1 }, "targets": [ { "refId": "A", "expr": "time() - node_boot_time_seconds{host=~\"$host\"}", "legendFormat": "{{host}}" } ], "fieldConfig": { "defaults": { "unit": "s", "decimals": 0 }, "overrides": [] }, "options": { "colorMode": "none", "graphMode": "none", "textMode": "auto" } }, { "type": "row", "title": "Ресурсы во времени", "gridPos": { "h": 1, "w": 24, "x": 0, "y": 6 } }, { "type": "timeseries", "title": "CPU по режимам", "description": "iowait отдельно от user/system: высокий iowait означает, что процессор ждёт диск, и добавлять ядер бесполезно.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 7 }, "targets": [ { "refId": "A", "expr": "sum by (host, mode) (rate(node_cpu_seconds_total{mode!=\"idle\", host=~\"$host\"}[5m])) / on (host) group_left count by (host) (node_cpu_seconds_total{mode=\"idle\", host=~\"$host\"})", "legendFormat": "{{host}} · {{mode}}" } ], "fieldConfig": { "defaults": { "unit": "percentunit", "min": 0, "custom": { "fillOpacity": 20, "stacking": { "mode": "normal" }, "showPoints": "never" } }, "overrides": [] } }, { "type": "timeseries", "title": "Память", "description": "Занято = всего минус доступно. Своп показан отдельно: его рост означает, что рабочий набор перестал помещаться.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 7 }, "targets": [ { "refId": "A", "expr": "node_memory_MemTotal_bytes{host=~\"$host\"} - node_memory_MemAvailable_bytes{host=~\"$host\"}", "legendFormat": "{{host}} · занято" }, { "refId": "B", "expr": "node_memory_SwapTotal_bytes{host=~\"$host\"} - node_memory_SwapFree_bytes{host=~\"$host\"}", "legendFormat": "{{host}} · своп" } ], "fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "fillOpacity": 15, "showPoints": "never" } }, "overrides": [] } }, { "type": "timeseries", "title": "Занятость дисков", "description": "По точкам монтирования. Порог алерта — 85 %, критический — 93 %.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 15 }, "targets": [ { "refId": "A", "expr": "1 - node_filesystem_avail_bytes{fstype!~\"tmpfs|overlay\", host=~\"$host\"} / node_filesystem_size_bytes{fstype!~\"tmpfs|overlay\", host=~\"$host\"}", "legendFormat": "{{host}} · {{mountpoint}}" } ], "fieldConfig": { "defaults": { "unit": "percentunit", "min": 0, "max": 1, "custom": { "fillOpacity": 10, "showPoints": "never", "thresholdsStyle": { "mode": "dashed" } }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 0.85 }, { "color": "red", "value": 0.93 } ] } }, "overrides": [] } }, { "type": "timeseries", "title": "Дисковый ввод-вывод", "description": "Байты чтения и записи по устройствам. Всплеск записи по ночам — это бэкапы (00:30 и 01:30 UTC), так и должно быть.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 15 }, "targets": [ { "refId": "A", "expr": "sum by (host) (rate(node_disk_read_bytes_total{host=~\"$host\"}[5m]))", "legendFormat": "{{host}} · чтение" }, { "refId": "B", "expr": "sum by (host) (rate(node_disk_written_bytes_total{host=~\"$host\"}[5m]))", "legendFormat": "{{host}} · запись" } ], "fieldConfig": { "defaults": { "unit": "Bps", "custom": { "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] } }, { "type": "row", "title": "Контейнеры", "gridPos": { "h": 1, "w": 24, "x": 0, "y": 23 } }, { "type": "timeseries", "title": "Память по контейнерам (топ-15)", "description": "working set, а не usage: usage включает переиспользуемый кэш и завышает картину. Именно по этой метрике сравнивается фактическое потребление с mem_limit.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 10, "w": 14, "x": 0, "y": 24 }, "targets": [ { "refId": "A", "expr": "topk(15, container_memory_working_set_bytes{name!=\"\", host=~\"$host\"})", "legendFormat": "{{host}} · {{name}}" } ], "fieldConfig": { "defaults": { "unit": "bytes", "custom": { "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] } }, { "type": "table", "title": "Приближение к mem_limit", "description": "Доля от заданного лимита. Пустая строка означает, что лимит не выставлен вовсе — тогда потребление сверху не ограничено ничем, кроме памяти хоста.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 10, "w": 10, "x": 14, "y": 24 }, "targets": [ { "refId": "A", "instant": true, "format": "table", "expr": "sort_desc(container_memory_working_set_bytes{name!=\"\", host=~\"$host\"} / (container_spec_memory_limit_bytes{name!=\"\", host=~\"$host\"} > 0))", "legendFormat": "{{name}}" } ], "transformations": [ { "id": "organize", "options": { "excludeByName": { "Time": true, "job": true, "instance": true, "id": true, "image": true } } } ], "fieldConfig": { "defaults": { "unit": "percentunit", "custom": { "align": "auto", "cellOptions": { "type": "gauge" } }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 0.8 }, { "color": "red", "value": 0.9 } ] } }, "overrides": [] } }, { "type": "timeseries", "title": "Перезапуски контейнеров", "description": "Число стартов за полчаса. Больше трёх — цикл перезапусков: снаружи такой контейнер выглядит поднятым, а деплой при этом зелёный.", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 34 }, "targets": [ { "refId": "A", "expr": "changes(container_start_time_seconds{name!=\"\", host=~\"$host\"}[30m]) > 0", "legendFormat": "{{host}} · {{name}}" } ], "fieldConfig": { "defaults": { "unit": "short", "min": 0, "custom": { "drawStyle": "bars", "fillOpacity": 60, "showPoints": "never" } }, "overrides": [] } } ] }