- 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.
5.8 KiB
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
# 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
# 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.
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.
# 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:
hcloud floating-ip assign <floating-ip-id> <iklim-app-02-server-id>
Hetzner Cloud Console (web) ile:
- console.hetzner.cloud adresine giriş yap.
- Sol menüden ilgili projeyi seç (
iklim_prod). - Sol menüden Floating IPs sekmesine gir.
iklim-prod-app-fipsatırının sağındaki ⋮ (üç nokta) menüsünü aç → Reassign.- Açılan listeden
iklim-app-02'yi seç → Reassign butonuna tıkla.
3. Doğrula
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.
# 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 |