# 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 "" "" "" # prod ./unseal.sh prod "" "" "" ``` Скрипт делает: 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 '' kubectl exec -n config vault-0 -- vault operator unseal '' kubectl exec -n config vault-0 -- vault operator unseal '' # 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 -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.