Ne oldu?
31 Ocak 2017 akşamı GitLab.com’un PostgreSQL veritabanında yük aniden arttı. GitLab’e göre bunun bir kısmı spam’den, bir kısmı da yanlışlıkla kötüye kullanım diye işaretlenmiş bir hesabı silmeye çalışan arka plan işinden geliyordu. Yük yüzünden ikinci sunucuya (secondary) yapılan replikasyon geride kaldı ve sonunda koptu. Ana sunucu, ikincinin yetişmek için ihtiyaç duyduğu WAL kayıtlarını çoktan silmişti.
Gece 23:30 civarında (UTC) bir mühendis, ikinci sunucuyu sıfırdan kurmak için veri klasörünü silmeye karar verdi. Ama silme komutu yanlış sunucuda, yani ana sunucuda (primary) çalıştı. Birkaç saniye içinde fark edip durdurdu. O arada yaklaşık 300 GB veri silinmişti.
Beş yedek, sıfır çalışan
Asıl sürpriz bundan sonra geldi. GitLab’in elinde kâğıt üzerinde beş farklı koruma vardı, pratikte hiçbiri işe yaramadı:
- pg_dump yedekleri: Yedek işi, PostgreSQL 9.6 veritabanını 9.2 sürümünün aracıyla almaya çalışıyordu. İş her seferinde başarısız oldu, yedek klasörü boştu.
- Hata e-postaları: Bu hataları bildiren e-postalar gönderiliyordu ama cron e-postaları için DMARC ayarı yapılmadığından reddediliyordu. Kimsenin haberi olmadı.
- Bulut disk görüntüleri: Azure disk snapshot’ları dosya sunucularında açıktı, veritabanı sunucularında değil. Ekip öbür yedeklerin yeteceğini varsaymıştı.
- Replikasyon: Zaten o akşam kopmuştu. Üstelik replikasyon yanlış silmeyi de anında kopyalar, yedek yerine geçmez.
- LVM görüntüleri: Otomatik olarak yalnızca 24 saatte bir alınıyordu. Yani en yakın otomatik kopya bir gün kadar eski olabilirdi.
Kurtarıcı, planın parçası bile değildi. Bir mühendis o gün saat 17:20’de, bir yük testi için taze veri istediğinden elle bir LVM disk görüntüsü almış ve test ortamına kopyalamıştı. GitLab bu 6 saatlik kopyadan geri döndü.
Bedeli neydi?
GitLab’in kendi raporuna göre yaklaşık 6 saatlik veritabanı değişikliği kayboldu. Tahmini olarak yaklaşık 5.000 proje, 5.000 yorum ve 700 kadar yeni kullanıcı hesabı etkilendi. Git depoları ve wiki’ler silinmedi, sadece erişilemez oldu. Test ortamının diskleri yavaş olduğu için veriyi geri kopyalamak saatler sürdü. GitLab.com toplamda 18 saat kadar kapalı kaldı.
Bütün bu süre boyunca GitLab notlarını herkese açık bir dokümanda tuttu ve kurtarmayı YouTube’da canlı yayınladı. Raporlarına göre yayını aynı anda en çok yaklaşık 5.000 kişi izledi.
Senin için dersler
- Denenmemiş yedek, yedek değildir. Yedeğin işe yarayıp yaramadığını ancak geri yükleyerek öğrenirsin. GitLab da sonrasında yedekten kurtarmayı otomatik test etmeyi işler listesine koydu. Aynı dersin bulut tarafını AWS veri kaybı yazımızda anlattık.
- Yedek işini izle, sessizliğe güvenme. “Hata gelmedi” ile “başarılı oldu” aynı şey değil. Yedek dosyasının boyutunu ve tarihini kontrol eden bir izleme kur. GitLab bunun için bir yedek izleme paneli yaptı.
- Felaket anında yazılı plan olsun. Gece yarısı, yorgun bir mühendisin elle komut yazması riskli. Adım adım runbook’lar ve hangi sunucuda olduğunu belli eden terminal ayarları bu hatayı zorlaştırır.
- PostgreSQL’de sürekli arşivleme düşün. WAL arşivleme ve zamanda bir ana geri dönüş (point-in-time recovery), veriyi sadece günlük kopyalardan değil, istediğin bir dakikaya kadar geri getirmeni sağlar.
- Suçlayan değil, öğreten rapor yaz. GitLab olayı açıkça paylaştı. Raporda tek bir hatayı değil, onu mümkün kılan bütün zinciri ve 15 iyileştirme maddesini anlattı. İç dokümanda mühendisin adı geçtiği için, ileride isimleri gizleyeceğini de söyledi. Büyük bir kesintiden sonra yayımlanan başka bir öğretici raporu GitHub kesintisi yazısında incelemiştik.
Düşün
- Senin veritabanının yedeği en son ne zaman gerçekten geri yüklendi?
- Gece yedek işi bozulsa bunu kim, nasıl fark eder?
Videoyu izle
Kaynaklar (4, İngilizce)
- Better Stack: GitLab Lost 300GB… Then Livestreamed the Fix (short) (yeni sekmede açılır)
- GitLab: Postmortem of database outage of January 31 (yeni sekmede açılır)
- GitLab: GitLab.com database incident (February 1, 2017) (yeni sekmede açılır)
- PostgreSQL Docs: Continuous archiving and point-in-time recovery (PITR) (yeni sekmede açılır)
Kendi cümlelerimizle yazılmış bir özettir, çeviri değildir. Tüm kaynaklar yukarıda.