docs(ops): operator runbook — kafka, outbox DLQ, db migrations + index
Карточки процедур для on-call. Self-contained: можно открыть в момент инцидента без необходимости понимать всю архитектуру. - README.md — index by symptom + быстрые гайды по 401, 500, admin-ui 502. - kafka-restart.md — pause/unpause, replicas=0 fix, force-delete, restart consumer'ов после Kafka up. - outbox-dlq.md — диагностика DLQ через UI/API/SQL, типичные причины (orphan topic, ACL, broken payload), replay через UPDATE dlq_at=NULL. - db-migrations.md — Liquibase changelog, добавление, откат, recovery failed migration через DELETE databasechangelog. Vault unseal был отдельным коммитом ранее.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# Ordinis НСИ ЦУОД — Operator Runbook
|
||||
|
||||
Карточки процедур для on-call инженера. Каждая карточка self-contained: можно
|
||||
открыть в момент инцидента и пройти по шагам без необходимости понимать всю
|
||||
архитектуру.
|
||||
|
||||
## Indexed by symptom
|
||||
|
||||
| Симптом | Карточка |
|
||||
|---------------------------------------------------------------|----------|
|
||||
| Spring Boot pod'ы залипли в `Init:0/1` после reboot | [vault-unseal.md](vault-unseal.md) |
|
||||
| Kafka pod не Running, либо `vault-agent` не достукивается | [kafka-restart.md](kafka-restart.md) |
|
||||
| Метрика `ordinis_outbox_dlq_size > 0` | [outbox-dlq.md](outbox-dlq.md) |
|
||||
| Pod в `CrashLoopBackOff` с liquibase ошибкой в логах | [db-migrations.md](db-migrations.md) |
|
||||
| API возвращает 401 на любые запросы | См. §1 ниже |
|
||||
| API возвращает 500 на конкретный endpoint | См. §2 ниже |
|
||||
| Admin UI не загружается (502/503) | См. §3 ниже |
|
||||
|
||||
## 1. 401 Unauthorized
|
||||
|
||||
Сейчас на staging `ORDINIS_AUTH_REQUIRED=true`. Anonymous = 401. Проверить:
|
||||
|
||||
```bash
|
||||
# 1. Header передан?
|
||||
curl -v -H "Authorization: Bearer $TOKEN" ... | grep -i authorization
|
||||
|
||||
# 2. JWT валиден?
|
||||
echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | jq
|
||||
# проверить exp, iss, realm_access.roles
|
||||
|
||||
# 3. Issuer правильный?
|
||||
# должен быть https://auth.nstart.space/realms/nstart
|
||||
```
|
||||
|
||||
Если JWT прошёл проверку, но 401 — backend логи:
|
||||
```bash
|
||||
kubectl logs -n ordinis-staging deploy/ordinis-app -c app --tail=50 \
|
||||
| grep -iE "jwt|invalid_token|expired"
|
||||
```
|
||||
|
||||
Типичные причины:
|
||||
- `Invalid signature` — Keycloak ротировал ключи, но бэкенд кэширует старый. Restart pod.
|
||||
- `Token expired` — refresh token не сработал, юзер должен перелогиниться.
|
||||
- `Issuer mismatch` — JWT issued другим Keycloak realm'ом.
|
||||
|
||||
## 2. 500 Internal Server Error на endpoint
|
||||
|
||||
```bash
|
||||
# Найти trace_id из ответа
|
||||
curl -i ... | grep -i traceid
|
||||
# либо UI показывает traceId в alert
|
||||
|
||||
# Найти полный stack trace
|
||||
kubectl logs -n ordinis-staging deploy/ordinis-app -c app --tail=200 \
|
||||
| grep "<traceId>"
|
||||
```
|
||||
|
||||
Типичные причины (в наших коммитах):
|
||||
- `could not determine data type of parameter $N` — Hibernate JPQL с `IS NULL`
|
||||
на nullable timestamp. Решение — sentinel value (см. fix audit search).
|
||||
- `DataIntegrityViolationException dictionary_records_no_overlap` — bitemporal
|
||||
exclusion constraint, период пересекается. Friendly 409 уже маппится — если
|
||||
500 значит код-путь неуспел поймать.
|
||||
- `JsonMappingException` — payload поломан (фронт передал stale schema).
|
||||
|
||||
## 3. Admin UI не загружается / 502 / 503
|
||||
|
||||
```bash
|
||||
kubectl get pods -n ordinis-staging | grep admin-ui
|
||||
```
|
||||
|
||||
| Status | Причина |
|
||||
|-----------------------|---------|
|
||||
| `ImagePullBackOff` | Тег image не существует в registry. Проверь `kubectl describe`. Восстановить:<br>`kubectl set image deployment/ordinis-admin-ui -n ordinis-staging ui=repo.nstart.cloud/terravault/ordinis-admin-ui:main` |
|
||||
| `CrashLoopBackOff` | nginx config invalid либо resolver недоступен. См. logs. |
|
||||
| `Running 1/1`, но 502 | Upstream (writer/read-api) сам в дауне. Проверь те pod'ы. |
|
||||
|
||||
## 4. Что-то ещё — где смотреть
|
||||
|
||||
- **Pod state:** `kubectl get pods -n ordinis-staging`
|
||||
- **Recent events:** `kubectl get events -n ordinis-staging --sort-by='.lastTimestamp' | tail -20`
|
||||
- **Resource usage:** `kubectl top pod -n ordinis-staging`
|
||||
- **Logs:** `kubectl logs -n ordinis-staging deploy/<name> -c app --tail=100`
|
||||
- **Liveness/readiness probes:** `kubectl describe pod -n ordinis-staging <pod>`
|
||||
- **Ingress:** `kubectl get ingress -n ordinis-staging`
|
||||
- **Helm release:** `helm history ordinis -n ordinis-staging`
|
||||
|
||||
## 5. Эскалация
|
||||
|
||||
>30 мин downtime, не понятно куда копать → tech lead (zimin.an@nstart.space).
|
||||
|
||||
## 6. Связанные ресурсы
|
||||
|
||||
- API integration guide: [../tech/api-integration.md](../tech/api-integration.md)
|
||||
- Альтум integration: [../integration/altum-imaging-order.md](../integration/altum-imaging-order.md)
|
||||
- Project state: [../status/2026-05-05-state.md](../status/2026-05-05-state.md)
|
||||
- Helm chart: `ordinis-infra/charts/ordinis/`
|
||||
- Vault setup: `ordinis-infra/k8s/vault/setup.sh`
|
||||
Reference in New Issue
Block a user