- Refactor production setup documentation to reflect a 3-node Vault Raft cluster starting from launch. - Update all paths to use StorageBox mounts for shared state (SWAG config, TLS certs, Monitoring data). - Switch Nginx configuration convention from proxy-confs to site-confs to align with SWAG's auto-include behavior. - Standardize TLS private key extensions to .pem. - Update node failover and recovery facts to include monitoring services. - Align deployment pipeline instructions with the latest environment variable-driven approach.
154 lines
5.8 KiB
Markdown
154 lines
5.8 KiB
Markdown
# Docker Swarm — Node Recovery
|
||
|
||
Test ortamında tek manager (`iklim-app-01`) ve tek worker (`iklim-db-01`) bulunur. Hangi node'un yeniden kurulduğuna göre recovery süreci farklılaşır.
|
||
|
||
## Senaryo 1: `iklim-app-01` (Manager) Yeniden Kurulur
|
||
|
||
### Sorun
|
||
|
||
Yeni `iklim-app-01` üzerinde `docker swarm init` farklı cluster ID ile yeni bir küme başlatır. `iklim-db-01` hâlâ eski kümeye bağlıdır. Ansible `swarm` role'u `iklim-db-01`'de Swarm'ı `active` görür, join denemez. İki node iki ayrı kümede kalır.
|
||
|
||
### Çözüm
|
||
|
||
```bash
|
||
# 1. iklim-db-01 üzerinde — eski kümeden çık
|
||
docker swarm leave --force
|
||
|
||
# 2. Ansible ile her iki node'u yeniden kur
|
||
cd ansible/test
|
||
ansible-playbook -i inventory/generated/test.yml test-bootstrap.yml --ask-vault-pass
|
||
|
||
# 3. DB stack'i yeniden deploy et
|
||
ansible-playbook -i inventory/generated/test.yml test-db-post-stack.yml --ask-vault-pass
|
||
```
|
||
|
||
DB verileri `iklim-db-01`'deki named volume'larda korunur, kayıp yaşanmaz.
|
||
|
||
---
|
||
|
||
## Senaryo 2: `iklim-db-01` (Worker) Yeniden Kurulur
|
||
|
||
### Durum
|
||
|
||
Yeni `iklim-db-01` Swarm'dan habersiz başlar (`inactive`). Manager (`iklim-app-01`) eski dead node kaydını tutar.
|
||
|
||
### Çözüm
|
||
|
||
```bash
|
||
# 1. Ansible bootstrap — yeni node otomatik join olur
|
||
cd ansible/test
|
||
ansible-playbook -i inventory/generated/test.yml test-bootstrap.yml --ask-vault-pass
|
||
|
||
# 2. iklim-app-01 üzerinde — eski dead node kaydını temizle
|
||
docker node ls # eski node ID'yi bul
|
||
docker node rm <eski-node-id>
|
||
|
||
# 3. DB stack'i yeniden deploy et (backup'tan restore sonrası)
|
||
ansible-playbook -i inventory/generated/test.yml test-db-post-stack.yml --ask-vault-pass
|
||
```
|
||
|
||
Ansible `swarm` role'u `inactive` durumu gördüğü için token alıp join eder, `role=db` label'ını uygular. DB servisleri placement constraint sayesinde yeni node'a schedule edilir.
|
||
|
||
---
|
||
|
||
## Senaryo 3: Her İki Node Yeniden Kurulur
|
||
|
||
Her şey sıfırdan kurulur, Swarm uyumsuzluğu yaşanmaz.
|
||
|
||
```bash
|
||
cd ansible/test
|
||
ansible-playbook -i inventory/generated/test.yml test-bootstrap.yml --ask-vault-pass
|
||
ansible-playbook -i inventory/generated/test.yml test-db-post-stack.yml --ask-vault-pass
|
||
```
|
||
|
||
---
|
||
|
||
## Özet
|
||
|
||
| Senaryo | Manuel Adım | Ansible Yeterli mi? |
|
||
|---|---|---|
|
||
| Manager (`iklim-app-01`) ölür | `docker swarm leave --force` (worker'da) | Sonrasında evet |
|
||
| Worker (`iklim-db-01`) ölür | `docker node rm <id>` (manager'da) | Büyük ölçüde evet |
|
||
| Her ikisi ölür | Yok | Evet |
|
||
|
||
## Neden Prod'da Bu Sorun Yok
|
||
|
||
Prod ortamında birden fazla manager node (en az 3) çalıştırılır. Tek manager düşse diğerleri liderliği devralır, küme sağlıklı kalmaya devam eder.
|
||
|
||
---
|
||
|
||
# Prod — Monitoring & SWAG Failover
|
||
|
||
SWAG, cert-reloader, Prometheus ve Grafana cluster-native (replicated) değildir; her zaman tek instance çalışırlar ve varsayılan olarak `iklim-app-01`'e (Floating IP node) sabitlenmişlerdir. `iklim-app-01` çöktüğünde bu servisler durur; DNS/HTTPS erişimi ve izleme (monitoring) kesilir. Swarm quorum 2 manager ile devam eder; mikroservisler ve Vault başka node'lara taşınır.
|
||
|
||
Tüm bu servislerin verileri ve konfigürasyonları StorageBox'ta tutulur:
|
||
- **SWAG:** `/mnt/storagebox/swag/config`
|
||
- **SSL:** `/mnt/storagebox/ssl`
|
||
- **Prometheus:** `/mnt/storagebox/prometheus/data`
|
||
- **Grafana:** `/mnt/storagebox/grafana/data`
|
||
|
||
## Prod Senaryo: `iklim-app-01` Çöktü
|
||
|
||
### 1. Servisleri Başka Node'a Taşı
|
||
|
||
SWAG ve cert-reloader birlikte taşınmalıdır. Prometheus ve Grafana da bağımsız olarak veya aynı anda taşınabilir.
|
||
|
||
```bash
|
||
# iklim-app-02 veya iklim-app-03 üzerinde (aktif manager):
|
||
|
||
# SWAG & Cert-Reloader taşıma
|
||
docker service update --constraint-add "node.hostname == iklim-app-02" --constraint-rm "node.hostname == iklim-app-01" iklimco_swag
|
||
docker service update --constraint-add "node.hostname == iklim-app-02" --constraint-rm "node.hostname == iklim-app-01" iklimco_cert-reloader
|
||
|
||
# Prometheus & Grafana taşıma
|
||
docker service update --constraint-add "node.hostname == iklim-app-02" --constraint-rm "node.hostname == iklim-app-01" iklimco_prometheus
|
||
docker service update --constraint-add "node.hostname == iklim-app-02" --constraint-rm "node.hostname == iklim-app-01" iklimco_grafana
|
||
```
|
||
|
||
### 2. Floating IP'yi Yeni Node'a Taşı
|
||
|
||
**CLI ile:**
|
||
|
||
```bash
|
||
hcloud floating-ip assign <floating-ip-id> <iklim-app-02-server-id>
|
||
```
|
||
|
||
**Hetzner Cloud Console (web) ile:**
|
||
|
||
1. [console.hetzner.cloud](https://console.hetzner.cloud) adresine giriş yap.
|
||
2. Sol menüden ilgili projeyi seç (`iklim_prod`).
|
||
3. Sol menüden **Floating IPs** sekmesine gir.
|
||
4. `iklim-prod-app-fip` satırının sağındaki **⋮** (üç nokta) menüsünü aç → **Reassign**.
|
||
5. Açılan listeden **`iklim-app-02`**'yi seç → **Reassign** butonuna tıkla.
|
||
|
||
### 3. Doğrula
|
||
|
||
```bash
|
||
docker service ls | grep -E 'swag|cert-reloader|prometheus|grafana'
|
||
curl -si https://api.iklim.co/health
|
||
```
|
||
|
||
### `iklim-app-01` Geri Döndüğünde
|
||
|
||
Node Swarm'a yeniden katıldıktan sonra tüm servisleri tekrar `iklim-app-01`'e taşıyıp Floating IP'yi geri aktarabilirsiniz.
|
||
|
||
```bash
|
||
# Servisleri geri taşı
|
||
for svc in iklimco_swag iklimco_cert-reloader iklimco_prometheus iklimco_grafana; do
|
||
docker service update --constraint-add "node.hostname == iklim-app-01" --constraint-rm "node.hostname == iklim-app-02" $svc
|
||
done
|
||
|
||
# Floating IP'yi iklim-app-01'e geri ata
|
||
hcloud floating-ip assign <floating-ip-id> <iklim-app-01-server-id>
|
||
```
|
||
|
||
## Özet
|
||
|
||
| Bileşen | Failover davranışı |
|
||
|---------|-------------------|
|
||
| Swarm quorum | Otomatik — 2 manager yeterli |
|
||
| Vault, mikroservisler | Otomatik — `node.labels.type == service` constraint ile başka node'a schedule edilir |
|
||
| SWAG, cert-reloader | Manuel — `docker service update --constraint-*` + Floating IP taşıma |
|
||
| Prometheus, Grafana | Manuel — `docker service update --constraint-*` |
|
||
| Veriler & Konfig | StorageBox'ta; failover node hemen erişir, veri kaybı yaşanmaz |
|