docs(ops): vault unseal runbook + auto-unseal migration plan
Triage card для on-call: где взять unseal-keys (1Password placeholder, уточнить с DevOps lead), как запустить script либо ручную процедуру, что проверить после, troubleshooting типовых проблем. Также: §7 — план миграции на auto-unseal (Transit / Yandex KMS) когда определимся с master Vault или KMS-backend.
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# Runbook: Vault unseal (staging / prod)
|
||||
|
||||
**Когда использовать:** Vault на кластере залип в `Sealed=true` после reboot
|
||||
ноды или manual seal. Признаки:
|
||||
- Spring Boot pod'ы (`ordinis-app`, `ordinis-read-api`, `ordinis-projection-writer`)
|
||||
стоят в `Init:0/1`.
|
||||
- В логах `vault-agent-init` контейнера: `Vault is sealed`, error 503 на
|
||||
`auth/kubernetes/login`.
|
||||
- `kubectl exec -n config vault-0 -- vault status` → `Sealed: true`.
|
||||
|
||||
**Auto-unseal сейчас НЕ настроен** (v1 closure backlog: Transit secret engine
|
||||
с master Vault либо Yandex Cloud KMS). До миграции — ручная процедура ниже.
|
||||
|
||||
---
|
||||
|
||||
## 1. Где взять unseal-ключи
|
||||
|
||||
Ключи Shamir, threshold **3 из 5**. Хранение:
|
||||
|
||||
- **Corporate 1Password** — vault `Ordinis НСИ ЦУОД`:
|
||||
- `vault-staging-unseal-keys` — для cluster.265 (192.168.100.161)
|
||||
- `vault-prod-unseal-keys` — для cluster.142 (192.168.100.142)
|
||||
- **Резерв** (cold storage) — у DevOps lead в KeePass.
|
||||
|
||||
Доступ к 1Password vault — у списка инженеров с on-call. При расширении —
|
||||
добавлять через 1Password admin. Никогда не пересылать ключи в Slack /
|
||||
Telegram / email.
|
||||
|
||||
> ⚠️ **При утере 5 из 5 ключей:** Vault инициализируется заново → ВСЕ
|
||||
> secrets потеряны (postgres passwords, Kafka SASL, Keycloak signing keys
|
||||
> в K8s secrets — отдельно). Plan: получить root token + replay `setup.sh` +
|
||||
> заново положить secrets из 1Password (Postgres backup + Vault: писать
|
||||
> только в зеркало). Делать только с письменным разрешением tech lead.
|
||||
|
||||
## 2. Быстрый unseal (script)
|
||||
|
||||
```bash
|
||||
cd ~/code/ordinis-infra/k8s/vault
|
||||
|
||||
# staging
|
||||
./unseal.sh staging "<KEY_1>" "<KEY_2>" "<KEY_3>"
|
||||
|
||||
# prod
|
||||
./unseal.sh prod "<KEY_1>" "<KEY_2>" "<KEY_3>"
|
||||
```
|
||||
|
||||
Скрипт делает:
|
||||
|
||||
1. Pull kubeconfig с ноды (если ещё не скачан).
|
||||
2. Проверяет `vault status` — если уже unsealed, выходит.
|
||||
3. Применяет 3 ключа последовательно через `vault operator unseal`.
|
||||
4. Проверяет `Sealed: false`.
|
||||
5. Force-deletes Spring Boot pod'ы — vault-agent-init иначе ждёт backoff
|
||||
до 3+ минут на следующую попытку auth.
|
||||
|
||||
После — `kubectl get pods -n ordinis-{env}` показывает `2/2 Running`
|
||||
через ~2 минуты.
|
||||
|
||||
## 3. Ручной unseal (если script недоступен)
|
||||
|
||||
```bash
|
||||
# 1. Получить kubeconfig
|
||||
ssh root@192.168.100.161 "cat /etc/kubernetes/admin.conf" > /tmp/kc-161
|
||||
sed -i '' 's|server: https://[^:]*:|server: https://192.168.100.161:|' /tmp/kc-161
|
||||
export KUBECONFIG=/tmp/kc-161
|
||||
|
||||
# 2. Проверить статус
|
||||
kubectl exec -n config vault-0 -- vault status
|
||||
|
||||
# 3. Применить 3 ключа (по одному)
|
||||
kubectl exec -n config vault-0 -- vault operator unseal '<KEY_1>'
|
||||
kubectl exec -n config vault-0 -- vault operator unseal '<KEY_2>'
|
||||
kubectl exec -n config vault-0 -- vault operator unseal '<KEY_3>'
|
||||
|
||||
# 4. Убедиться Sealed: false
|
||||
kubectl exec -n config vault-0 -- vault status
|
||||
|
||||
# 5. Перезапустить Spring Boot pod'ы
|
||||
kubectl delete pod -n ordinis-staging \
|
||||
-l 'app.kubernetes.io/name in (ordinis-app,ordinis-read-api,ordinis-projection-writer)' \
|
||||
--grace-period=0 --force
|
||||
|
||||
# 6. Проверить
|
||||
kubectl get pods -n ordinis-staging
|
||||
```
|
||||
|
||||
## 4. Подтверждение что всё работает
|
||||
|
||||
```bash
|
||||
# read-api
|
||||
curl -sk --resolve ordinis.k8s.265.nstart.cloud:443:192.168.100.161 \
|
||||
https://ordinis.k8s.265.nstart.cloud/api/v1/spacecraft/records?lang=ru-RU \
|
||||
| jq 'length'
|
||||
# → должно вернуть число > 0
|
||||
|
||||
# admin
|
||||
curl -sk -o /dev/null -w "%{http_code}\n" \
|
||||
--resolve ordinis.k8s.265.nstart.cloud:443:192.168.100.161 \
|
||||
"https://ordinis.k8s.265.nstart.cloud/api/v1/admin/audit?page=0&size=5"
|
||||
# → 200
|
||||
```
|
||||
|
||||
## 5. Эскалация / проблемы
|
||||
|
||||
| Симптом | Что делать |
|
||||
|------------------------------------------------------|--|
|
||||
| `vault status` → `connection refused` | Pod `vault-0` не Running. `kubectl get pods -n config` + `kubectl describe`. |
|
||||
| `unseal` принимает ключ но Sealed остаётся true | Проверить count `Unseal Progress` — может нужен 4-й ключ если threshold увеличили. |
|
||||
| Все 3 ключа отвергает (`invalid key`) | Whitespace / обрезанные символы. Скопировать заново из 1Password (полное поле). |
|
||||
| Pod'ы Spring Boot не поднимаются после unseal | `kubectl logs <pod> -c vault-agent-init` — могут быть policy/role миграции после изменений. |
|
||||
| Consul backend (Vault использует Consul) недоступен | `kubectl get pods -n config consul-server-0` + `kubectl logs`. |
|
||||
|
||||
При 30+ минут downtime → эскалация tech lead → решение о переносе
|
||||
prod-нагрузки на запасной кластер либо публичная коммуникация в SLA-канал.
|
||||
|
||||
## 6. Связанные документы
|
||||
|
||||
- Установка Vault с нуля: `ordinis-infra/k8s/vault/setup.sh`
|
||||
- Архитектура auth: `ordinis-auth/.../{ScopeContext,SecurityConfig}.java`
|
||||
- Список секретов в Vault: `secret/ordinis/cuod/` (postgres, kafka, redis)
|
||||
|
||||
## 7. Переход к auto-unseal (TODO для v1 closure)
|
||||
|
||||
Когда будет master Vault либо Yandex Cloud KMS:
|
||||
|
||||
1. Добавить `seal "transit"` либо `seal "yandexcloudkms"` stanza в vault config
|
||||
ConfigMap (`config/vault-config`).
|
||||
2. Запустить migration:
|
||||
```
|
||||
kubectl exec -n config vault-0 -- vault operator unseal -migrate KEY_1
|
||||
kubectl exec -n config vault-0 -- vault operator unseal -migrate KEY_2
|
||||
kubectl exec -n config vault-0 -- vault operator unseal -migrate KEY_3
|
||||
```
|
||||
3. После миграции существующие Shamir-keys больше не работают — выдаются
|
||||
Recovery Keys (5 шт, тот же threshold 3) для emergency rekey/operator-init
|
||||
операций.
|
||||
4. Обновить этот runbook: основной случай — auto-unseal, ручной unseal
|
||||
только при downtime master Vault / KMS.
|
||||
Reference in New Issue
Block a user