Integrates `vault-check-health.sh` into `vault-bootstrap.sh` to perform a network-based health check. If all Vault nodes are found initialized and unsealed, the bootstrap process is skipped, preventing unnecessary restarts or re-initialization. Renames `failover_scenarios.md` to `vault_failover_scenarios.md` for improved clarity and consistency.
168 lines
10 KiB
Markdown
168 lines
10 KiB
Markdown
# Vault HA Failover Senaryoları
|
||
|
||
Bu belge, 3 düğümlü Vault HA Raft kümesinin Docker Swarm üzerindeki çeşitli host makine hatası ve kurtarma koşulları altında nasıl davrandığını ve her durumda manuel müdahale gerekip gerekmediğini kapsamaktadır.
|
||
|
||
---
|
||
|
||
## Mimari Özeti
|
||
|
||
| Özellik | Değer |
|
||
|---|---|
|
||
| Vault düğümleri | 3 replika (`vault-1`, `vault-2`, `vault-3`) |
|
||
| Raft çoğunluğu (quorum) | 3 düğümden 2'si gereklidir |
|
||
| Düğüm kimliği | `hostname: "vault-{{.Task.Slot}}.iklim.co"` — yeniden başlatmalarda sabittir |
|
||
| Unseal mekanizması | Shamir anahtarı, Docker Swarm secret'ı `vault_unseal_key` olarak saklanır |
|
||
| Entrypoint unseal döngüsü | Başlangıçtan sonra 3 dakikaya kadar her 2 saniyede bir `vault operator unseal` komutunu dener |
|
||
| Yerleşim (Placement) | `max_replicas_per_node: 1`, `node.labels.type == service` |
|
||
|
||
`hostname` ayarı kritik parçadır: Swarm, rastgele bir konteyner kimliği yerine **sabit bir slot numarası** (1, 2, 3) atadığı için, Raft `node_id` her yeniden başlatmada aynı kalır. Raft, geri dönen bir düğümü `node_id` üzerinden hemen tanır ve onu yepyeni bir eş (peer) olarak değerlendirmek yerine replikasyona kaldığı yerden devam eder.
|
||
|
||
---
|
||
|
||
## Raft Çoğunluk (Quorum) Kuralları
|
||
|
||
| Hayattaki düğümler | Çoğunluk | Küme durumu |
|
||
|---|---|---|
|
||
| 3 / 3 | Evet | Tamamen operasyonel |
|
||
| 2 / 3 | Evet | Operasyonel — okuma ve yazma işlemleri devam eder |
|
||
| 1 / 3 | **Hayır** | Donmuş — çoğunluk sağlanana kadar okuma ve yazma işlemleri engellenir |
|
||
| 0 / 3 | **Hayır** | Kapalı |
|
||
|
||
Küme, herhangi bir hizmet kesintisi olmadan **aynı anda bir düğüm hatasını** tolere edebilir.
|
||
|
||
---
|
||
|
||
## Senaryo 1 — Takipçi (Follower) Host Makine Çöküyor, Volume Sağlam
|
||
|
||
**Tetikleyici**: `vault-N` (bir takipçi) çalıştıran host makine çöker veya kapatılır. Vault volume'u host makinenin diskinde hayatta kalır.
|
||
|
||
**Otomatik davranış**:
|
||
1. Docker Swarm görevi (task) başarısız olarak işaretler. `max_replicas_per_node: 1` ayarı uygun başka bir host makine bırakmadığı için, Swarm replikayı başka bir yerde yeniden zamanlamaz. Hizmet 2/3 görevle çalışmaya devam eder.
|
||
2. Kalan 2 düğüm (1 lider + 1 takipçi) çoğunluğu korur. Küme, isteklere normal şekilde hizmet vermeye devam eder.
|
||
3. Host makine geri gelip Swarm'a tekrar katıldığında, Swarm görevi hemen üzerinde zamanlar.
|
||
4. Konteyner başlar, Raft verilerini sağlam bulur, lider ile `retry_join` üzerinden bağlantı kurar ve saklanan log indeksinden devam eder.
|
||
5. Entrypoint unseal döngüsü `/run/secrets/vault_unseal_key` dosyasını okur ve düğümü otomatik olarak unseal eder.
|
||
6. Düğüm saniyeler içinde `standby` (takipçi) durumuna geçer.
|
||
|
||
**Manuel müdahale**: Gerekli değildir.
|
||
|
||
---
|
||
|
||
## Senaryo 2 — Takipçi Host Makine Çöküyor, Volume Kayıp (Host Makine Yeniden Kuruldu)
|
||
|
||
**Tetikleyici**: `vault-N` çalıştıran host makine tamamen değiştirilir veya Docker volume'ları silinir (`rm -rf /var/lib/docker/volumes/iklimco_vault-data-vl/_data/*`).
|
||
|
||
> Bu senaryo testlerde doğrulandı: o sırada Raft lideri olan vault-3'ün volume'u silindi. Tam kurtarma yaklaşık 5 saniye sürdü.
|
||
|
||
**Otomatik davranış**:
|
||
1. Swarm, görevi (şimdi temiz olan) host makine üzerinde zamanlar.
|
||
2. Konteyner boş bir veri dizini ile başlar (`security barrier not initialized`).
|
||
3. `retry_join`, `vault.iklim.co:8200` (paylaşılan overlay takma adı) ile iletişime geçer. Başlangıçta sealed bir düğüme denk gelirse otomatik olarak tekrar dener.
|
||
4. Başarılı bir katılımda lider, tam Raft günlüğünü yeni düğüme aktarır (`previous-index=<leader> → last-index=1`).
|
||
5. `Initialized: true` olduğunda, entrypoint unseal döngüsü düğümü başarıyla unseal eder.
|
||
6. Düğüm, Raft seçim sonucuna bağlı olarak `standby` (takipçi) veya `active` (lider) durumuna geçer.
|
||
|
||
**Manuel müdahale**: Gerekli değildir.
|
||
|
||
**Yeniden kurulan host makinede ön koşul**:
|
||
- Konteyner başlamadan önce wildcard sertifika dosyaları `/opt/iklimco/ssl/` dizininde mevcut olmalıdır. Bunlar konteynere salt okunur (read-only) olarak bağlanır. Eğer host makine sıfırdan kurulduysa, Swarm'ı tekrar ayağa kaldırmadan önce sertifikaları geri yükleyin.
|
||
|
||
---
|
||
|
||
## Senaryo 3 — Lider (Leader) Host Makine Çöküyor, Volume Sağlam
|
||
|
||
**Tetikleyici**: Mevcut Raft liderini çalıştıran host makine çöker veya kapatılır. Volume hayatta kalır.
|
||
|
||
**Otomatik davranış**:
|
||
1. Hayatta kalan iki takipçi, Raft kalp atışı zaman aşımı (~5–10 sn) üzerinden lider kaybını tespit eder. Bunlardan biri Raft seçimini kazanır ve yeni lider olur.
|
||
2. Küme, yeni lider ile isteklere hizmet vermeye devam eder. Herhangi bir konfigürasyon değişikliği gerekmez — `vault.iklim.co` overlay takma adı, çalışan tüm konteynerlere round-robin (sırayla) dağıtım yapar.
|
||
3. Orijinal lider host makine geri geldiğinde, konteyneri yeniden başlar, Raft verilerini bulur, bir takipçi olarak tekrar katılır ve otomatik olarak unseal edilir.
|
||
|
||
**Manuel müdahale**: Gerekli değildir.
|
||
|
||
---
|
||
|
||
## Senaryo 4 — Lider Host Makine Çöküyor, Volume Kayıp (Host Makine Yeniden Kuruldu)
|
||
|
||
Senaryo 2 ile aynıdır ancak lider düğüm üzerinde tetiklenir. Davranış aynıdır: kalan 2 düğüm hemen yeni bir lider seçer ve yeniden kurulan host makine, tam log replikasyonu ile yeni bir takipçi olarak katılır.
|
||
|
||
**Manuel müdahale**: Gerekli değildir (Senaryo 2 ile aynı wildcard sertifika ön koşulu geçerlidir).
|
||
|
||
---
|
||
|
||
## Senaryo 5 — İki Düğüm Aynı Anda Çöküyor
|
||
|
||
**Tetikleyici**: Üç host makineden ikisi aynı anda arızalanır (örneğin iki kabini etkileyen bir güç kesintisi).
|
||
|
||
**Otomatik davranış**:
|
||
1. Çoğunluk kaybolur (3 düğümden sadece 1'i hayatta).
|
||
2. Hayatta kalan düğüm bir lider seçemez ve salt okunur / donmuş duruma geçer. Tüm Vault API çağrıları hata döndürür.
|
||
3. Çöken iki host makineden **herhangi biri** geri gelip Vault konteyneri başladığında, çoğunluk geri yüklenir (3 düğümden 2'si).
|
||
4. Raft tekrar bir lider seçer. Küme normal operasyona döner.
|
||
5. Üçüncü host makine geri döndüğünde, takipçi olarak tekrar katılır.
|
||
|
||
**Manuel müdahale**: Gerekli değildir — arızalanan iki düğümden en az birinin en sonunda volume'u sağlam olarak geri dönmesi (veya `retry_join` üzerinden taze bir düğüm olarak tekrar katılması) şartıyla.
|
||
|
||
> Eğer her iki arızalı düğümün de volume'u silinmişse ve hiçbiri tekrar katılamıyorsa, hayatta kalan tek düğüm Raft günlüğünün tek kopyasını elinde tutar. Bu uç durumda küme kendi kendini iyileştirecektir: iki taze düğüm katıldığında hayatta kalan liderden tam bir Raft anlık görüntüsü (snapshot) alacaktır.
|
||
|
||
---
|
||
|
||
## Senaryo 6 — Üç Düğümün Hepsi Çöküyor
|
||
|
||
**Tetikleyici**: Tam veri merkezi kesintisi, üç Swarm worker düğümünün tamamı aynı anda kapanır.
|
||
|
||
**Otomatik davranış**:
|
||
1. Host makineler geri geldiğinde, Swarm üç Vault görevini de zamanlar.
|
||
2. Setiap konteyner başlar ve Raft verilerini sağlam bulur (volume'lar yeniden başlatmalarda korunur).
|
||
3. Raft, üç düğüm arasında bir lider seçer (en yüksek Raft `CommitIndex` değerine sahip olan düğüm kazanır).
|
||
4. Üç düğümün tamamı entrypoint döngüsü üzerinden otomatik olarak unseal edilir.
|
||
5. Küme, herhangi bir insan müdahalesi olmadan tamamen operasyonel hale gelir.
|
||
|
||
**Manuel müdahale**: Gerekli değildir (volume'ların host makine yeniden başlatmalarından sağ çıktığı varsayılmaktadır; bu, işletim sistemi yeniden başlatmaları / güç döngüleri için normaldir).
|
||
|
||
---
|
||
|
||
## Senaryo 7 — Host Makine Swarm'dan Tamamen Çıkarıldı ve Tekrar Eklendi
|
||
|
||
**Tetikleyici**: Bir worker düğümü manuel olarak drain edilir ve Swarm'dan çıkarılır (`docker node rm`), ardından yeni veya yeniden imajlanmış bir host makine `docker swarm join` ile tekrar katılır.
|
||
|
||
**Otomatik davranış**:
|
||
- Yeni Swarm düğümü, gerekli düğüm etiketine (label) sahip olmadığı için otomatik olarak bir Vault görevi almaz.
|
||
|
||
**Manuel müdahale gereklidir**:
|
||
```bash
|
||
# Yeni düğüm kimliğini (node ID) bulun
|
||
docker node ls
|
||
|
||
# Swarm'ın vault'u üzerinde zamanlayabilmesi için yerleşim etiketini (placement label) tekrar uygulayın
|
||
docker node update --label-add type=service <node-id>
|
||
```
|
||
|
||
Etiket uygulandıktan sonra Swarm, bir sonraki mutabakat döngüsü içinde (genellikle 10 sn içinde) Vault replikasını düğüm üzerinde zamanlar. Bu noktadan itibaren Senaryo 1–4 geçerlidir (otomatik unseal).
|
||
|
||
---
|
||
|
||
## Özet Tablosu
|
||
|
||
| Senaryo | Çoğunluk kayboldu mu? | Otomatik kurtarma | Manuel adımlar |
|
||
|---|---|---|---|
|
||
| 1 — Takipçi çöktü, volume sağlam | Hayır | Evet | Yok |
|
||
| 2 — Takipçi çöktü, volume silindi | Hayır | Evet | Host makine yeniden kurulduysa `/opt/iklimco/ssl` sertifikalarını geri yükleyin |
|
||
| 3 — Lider çöktü, volume sağlam | Hayır (yeni seçim) | Evet | Yok |
|
||
| 4 — Lider çöktü, volume silindi | Hayır (yeni seçim) | Evet | Host makine yeniden kurulduysa `/opt/iklimco/ssl` sertifikalarını geri yükleyin |
|
||
| 5 — İki düğüm aynı anda çöktü | **Evet** (biri dönene kadar) | Evet | Yok — bir düğümün dönmesini bekleyin |
|
||
| 6 — Üç düğümün hepsi çöktü | **Evet** (ikisi dönene kadar) | Evet | Yok |
|
||
| 7 — Host makine Swarm'dan çıkarıldı ve tekrar eklendi | Hayır | Kısmi | `docker node update --label-add type=service <id>` |
|
||
|
||
---
|
||
|
||
## Otomatik Kurtarmayı Sağlayan Temel Tasarım Özellikleri
|
||
|
||
1. **Sabit `node_id`**: `hostname: "vault-{{.Task.Slot}}.iklim.co"` ayarı, Vault'un Raft `node_id` değerinin konteyner yeniden başlatmalarında asla değişmemesini sağlar. Bu olmasaydı, her yeniden başlatma yeni bir eş kimliği oluştururdu ve küme asla tekrar kurulamazdı.
|
||
|
||
2. **Entrypoint unseal döngüsü**: Konteyner, 3 dakikaya kadar her 2 saniyede bir `vault operator unseal` komutunu dener. Bu, taze bir düğümün Raft'a katılana kadar unseal edilemediği "tavuk mu yumurta mı" durumunu kapsar — döngü, Raft katılımı başarılı olana kadar denemeye devam eder.
|
||
|
||
3. **`vault_unseal_key` Docker secret'ı**: Unseal anahtarı, konteyner içinde her zaman `/run/secrets/vault_unseal_key` konumunda mevcuttur. Herhangi bir yeniden başlatmadan sonra hiç kimsenin anahtarı yazması gerekmez.
|
||
|
||
4. **Paylaşılan takma ad ile `retry_join`**: Tüm düğümler `vault.iklim.co:8200` (hizmet VIP'si / overlay takma adı) adresini işaret eder. Swarm bunu çalışan herhangi bir sağlıklı konteynere yük dengeler (load-balance), böylece yeni bir düğüm, hangi eşin mevcut lider olduğunu bilmesine gerek kalmadan kümeyi her zaman bulabilir.
|