Агуулгыг алгасах

Ажиллагаа

Байршуулалт, ажиглалт, нөөцлөлт. deploy/, .github/workflows/deploy.yml ба ажиллаж байгаа суулгацаас уншиж бичигдсэн.

Баримтын төв · Архитектур · Гарын авлага


Дөрвөн нэр, нэг хост

Нэр Юу
nexus.gerege.mn Платформ өөрөө — frontend ба /api/v1/*
admin.nexus.gerege.mn Операторын консол — /api/platform/v1/*
monitor.nexus.gerege.mn Grafana
backups.nexus.gerege.mn Шифрлэгдсэн нөөцийн сан (MinIO) + тайлбар хуудас
docs.nexus.gerege.mn Энэ баримт

Хоёр урсгал өөр origin дээр байгаа нь гоо зүйн биш: cookie нь hostname-аар хязгаарлагддаг тул тусдаа нэр нь тусдаа ambient authority гэсэн үг.

Байршуулалт

CI ногоон болсны дараа deploy.yml:

ghcr.io-д backend ба frontend image бүтээж түлхэх
   ↓  (tag = commit sha, мөн latest)
хост руу ssh: compose файл хуулах → pull → migrate → restart

Хоёр зүйл зориуд:

  • Хувилбар нь image дотор ldflags-аар шатаагдана. Тэгэхгүй бол суулгац бүр өөрийн хувилбарыг мэдэхгүй болно — каталог "platform": ">=1.1.0" шаардахад хариулах зүйлгүй.
  • Хуучныг шинэ нь бэлэн болтол буулгахгүй. GHCR дөнгөж түлхсэн хувийн image-д denied гэж хариулах нь ховор биш бөгөөд нэг удаа тэр нь тухайн ажиллагааны өөрийнх нь түлхсэн image-ийн rollout-ыг унагаасан.

Ажиглалт

deploy/docker-compose.monitoring.yml — тусдаа стек, тусдаа сүлжээ, платформын сүлжээнд зөвхөн scrape хийхээр холбогдоно.

Хадгалах хугацаа
Prometheus 3.1 Хэмжүүр 60 хоног / 20 GB
Loki 3.4 Лог 31 хоног
Tempo 2.7 Trace 72 цаг
Alloy 1.7 Цуглуулагч
Grafana 11.5 Дэлгэц
Alertmanager 0.28 Сэрэмжлүүлэг

Экспортерууд: node_exporter, cAdvisor, postgres_exporter, redis_exporter.

Trace 72 цаг байгаа шалтгаан: trace нь хүсэлт болсноос хойш минут, эсвэл цагийн дотор уншигддаг. Долоо хоногийн настай trace-ыг хэн ч нээдэггүй.

Хэмжүүр

Хэмжүүр бүр OpenTelemetry-ийн SDK-аар дамжиж, Prometheus exporter-ээр /metrics дээр гарна. HTTP-ийнх нь semantic convention-ыг дагана:

http_server_request_duration_seconds{http_request_method,http_route,http_response_status_code}

Хүсэлтийн тоо нь тусдаа counter биш — тэр гистограммын _count цуврал.

http.request.method нь хаалттай олонлог. Танихгүй үйл үг _OTHER болж нугалагдана: PROPFIND гэж дуудсан сканнер time series үүсгэх ёсгүй.

Гадаад систем бүр нэг histogram-аар хэмжигдэнэ — external_request_duration_seconds{system,operation,status} — системийн нэр нь мөн адил хаалттай олонлог, танихгүй нь other.

Exemplar

Trace асаалттай үед гистограммын сэмпл бүр trace_id авч явна. Латенси графикийн удаан цэг дээр дарахад Grafana тэр яг тэр хүсэлтийн trace-ыг нээнэ — «аль хүсэлт удаан байсан бэ» гэдгийг таамаглах хэрэггүй.

/metrics нь OpenMetrics хэлбэрээр үйлчилдэг байх ёстой, эс бөгөөс exemplar дамжихгүй.

Лог

Alloy Docker-ийн лог цуглуулж Loki руу өгнө. Backend нь slog-оор JSON бичдэг тул | json ажиллана.

Хоёр урхи, хоёулаа энэ суулгац дээр бодитоор гарсан:

  • LogQL-ийн шүүлт том жижиг үсэг ялгана. |= "audit" нь юу ч олохгүй — бичигдсэн зүйл нь "msg":"AUDIT_EVENT".
  • $__rate_interval нь зөвхөн Prometheus-ийнх. Loki дээр $__auto.

Мөн: Grafana нь панелийг панелийн датасурс дээр ажиллуулдаг, target-ийнх дээр биш. Хоёр нь зөрвөл LogQL нь Prometheus руу очиж parse алдаа өгнө.

Дэлгэцүүд

deploy/monitoring/grafana/dashboards/ — provisioning-оор ирдэг, гараар үүсгэдэггүй:

api-overview · infrastructure · logs · security · resilience · external-systems · monitoring-self

Сүүлийнх нь хамгийн чухал: ажиглалт өөрөө ажиллаж байгаа эсэх. Унтарсан Prometheus нь бүх зүйл хэвийн байгаа мэт харагддаг.

Сэрэмжлүүлэг

31 дүрэм, зургаан файлд. Хамрах хүрээ:

  • API — унтарсан, латенси, алдааны төсвийн шаталт (хурдан / удаан)
  • Дэд бүтэц — диск, санах ой, Postgres, Redis, контейнерын дахин эхлэл, TLS
  • Консол — нэвтрэлтийн бүтэлгүйтэл, түгжээ, break-glass ашиглалт, бүртгэгдээгүй бичилт
  • Гадаад систем — удаан, доройтсон, бүтэлгүй
  • Нөөцлөлт — бүтэлгүй, хуучирсан, хэзээ ч харагдаагүй, хостоос гараагүй
  • Ажиглалт өөрөө — Alertmanager мэдэгдэхгүй байна, дүрэм тооцоолж чадахгүй байна, Loki лог татгалзаж байна, target унтарсан

NexusTLSExpiryUnknown нь тусгай: тэр нь «гэрчилгээ дуусах гэж байна» гэсэн үг биш, «хэн ч хэмжихгүй байна» гэсэн үг. Хугацааг бичдэг cron ажил нь гараар суулгагддаг бөгөөд нэг хост дээр огт суулгагдаагүй байсан.

Нөөцлөлт

deploy/scripts/backup.sh, cron дээр өдөр бүр.

pg_dump → хуучныг цэвэрлэх → platform_backups-д мөр бичих
        → node_exporter-ийн textfile руу хэмжүүр бичих
        → age-ээр шифрлэж off-site руу илгээх

Гурав дахь алхам нь консол уншдаг мөр. Дөрөв дэх нь Prometheus уншдаг — шөнө дунд хэн нэгэнд сэрэмжлүүлэг илгээж чадах цорын ганц хувилбар. Хэмжигдэхгүй нөөцлөлт нь нөөцлөлт байхгүйтэй бараг адил: cron-ий чимээгүй бүтэлгүйтэл нь сэргээх өдрөө л илэрдэг.

Хостод зөвхөн age-ийн нийтийн түлхүүр байна. Эвдэрсэн платформ өөрийн илгээсэн зүйлээ уншиж чадахгүй; хувийн түлхүүр нь операторт байна. Түүнийг хост дээр үлдээвэл шифрлэлт нь утгагүй; түүнийг алдвал нөөцлөлт нь утгагүй.

Off-site сан нь MinIO, объектын хувилбарлалт асаалттай, байршуулалтын түлхүүр нь зөвхөн нэмэх эрхтэй. Тэр нь эвдэрсэн хост нь өөрийн өмнөх нөөцлөлтүүдийг устгаж чадахгүй гэсэн үг.

Хэмжүүр:

nexus_backup_last_run_timestamp_seconds
nexus_backup_last_success_timestamp_seconds
nexus_backup_last_size_bytes
nexus_backup_last_ok
nexus_backup_offsite_ok

Бүтэлгүйтсэн ажиллагаа нь өмнөх амжилтын мөчийг хадгална — эс бөгөөс нэг бүтэлгүйтэл нь «хэзээ ч амжилттай болоогүй»-тэй ялгагдахаа болино. Тохируулаагүй суулгац дээр offsite_ok нь 0 хэвээр байна, тэр нь зөв: хуулбар өөр газар байхгүй гэдэг нь хэмжигдэх ёстой баримт.

Сэргээлт

Нөөцлөлт нь сэргээгдэх хүртэл нөөцлөлт биш. Шалгах арга:

age -d -i key.txt backup.sql.gz.age | gunzip > restore.sql
createdb restore_check && psql restore_check < restore.sql
psql restore_check -c "select count(*) from information_schema.tables
                        where table_schema in ('workspace','registry','operator')"

Хаягдах өгөгдлийн сан руу — ажиллаж байгаа руу биш.

Гараар хийгддэг зүйлс

Байршуулалт автомат, гэхдээ эдгээр нь биш. Шинэ хост дээр мартагддаг зүйлс:

  • backup.sh-ийн cron бичлэг
  • TLS дуусах хугацааг бичдэг cron ажил
  • Docker 29 дээр cAdvisor-ын containerd тохиргоо (--containerd-namespace=moby ба pid: host) — үүнгүйгээр нэг л цуврал экспортлогдоно, мөн энэ нь дахин эхлүүлэхийг шаарддаг, дахин үүсгэхийг биш

Дэлгэрэнгүй алхмуудыг Гарын авлага.