İçeriğe atla
Yiğit Tenekeci
CV

Homelab

Yeşil yanan ama ölü sistem: izlemede yanlış şeyi ölçmek

Bir servisin ayakta olduğunu sanmakla gerçekten ayakta olması arasındaki farkı bir gece yarısı kesintisi öğretti. 12 Eylül’de, 00:01’de cloudflared tüneli düştü. Log’da quic dial hataları, network is unreachable, sonra otomatik retry ve 00:03:31’de dört bağlantının yeniden kayıt olması. İki dakika.

Ertesi sabah her şey yeşildi. Kırmızı bir satır yoktu, hiçbir uyarı gelmemişti, 04:00 bakımı “6/6 container Up” diye rapor vermişti. Hepsi doğruydu. Sadece benim sorduğum soruya değil, başka bir soruya cevap veriyordu.

İzleme kurarken en pahalı hata aracı yanlış seçmek değil. Yanlış şeyi ölçüp yeşil rengi doğru sanmak.

200 cevabı kimden geliyor

n8n’i ayakta mı diye kontrol etmek için yaptığım şey basitti: alan adına istek atmak, gelen 200’ü “çalışıyor” diye okumak.

Bir gün cevabın gövdesine baktım. Beklediğim JSON değil, Cloudflare Access’in HTML giriş ekranıydı.

n8n.yigittenekeci.com adresinin önünde Cloudflare Tunnel var, girişinde de Cloudflare Access. Yetkisiz bir istek n8n’e hiç ulaşmıyor; Cloudflare onu kendi kapısında karşılıyor. Tünel tamamen ölü olsa da o ekran açılıyor, çünkü ekran Cloudflare’ın sunucusundan geliyor. Yani ölçtüğüm şey n8n değildi. n8n ölse de yeşil, tünel ölse de yeşil, hatta evdeki sunucunun fişi çekilse de yeşil.

Kontrolü yaparken sadece durum koduna bakmayı bırakıp gelen gövdeyi okumak, aylardır yanlış soruya cevap aldığımı gösterdi.

Kontrolü uygulamanın içine taşımak

Çözüm, dışarıdan erişilebilen ama yalnızca uygulama gerçekten çalışıyorsa cevap veren bir adres üretmekti. n8n tarafında iki düğümlü küçük bir akış yazdım: GET /webhook/health{"status":"ok"}.

Bu yolun işe yaramasının sebebi, /webhook/* yollarının Access’ten muaf tutulmuş olması. Cevap doğrudan n8n’in kendi içinden çıkıyor, arada kimse yok. n8n düşerse cevap üretecek bir şey kalmıyor.

Aynı mantığı diğerlerine de yaydım: Plex’te /identity, kendi yazdığım API’lerde /health. Bu uçların ortak özelliği, cevabı üretmek için uygulamanın gerçekten iş yapıyor olması gerekmesi. Statik bir sayfa ya da bir ara katman 200 dönebiliyorsa, o adres sağlık kontrolü değil, süs.

Docker’da aynı hastalık

docker ps çıktısındaki “Up 3 days” bana konteynerin süreci yaşıyor diyor. Servis cevap veriyor demiyor.

İkisini ayırt etmenin yolu HEALTHCHECK. Veritabanı konteynerimde tanımlı, o yüzden listede (healthy) görünüyor. Plex’te, qBittorrent’te ve n8n’de yok, o yüzden sadece Up yazıyor. İki farklı kesinlik seviyesi, aynı yeşil renkte.

Mayıs’ta bunun için küçük bir izleyici yazmıştım: Docker soketini okuyup konteyner durumlarını SQLite’a kaydeden, 120 saniyede bir çalışan bir daemon ve 9876 portunda bir HTTP API. Durumları cep telefonumdan, SSH atmadan görebilmek istiyordum.

PRD’yi yazarken takip edilecek durumu “running / stopped / crashed” diye üçe ayırmışım. Elime geçen ise iki şey: Up ve Exited. “Up 3 gün” ile “Up 40 saniye” state tarafında aynı kutuya düşüyor — ikisi de çalışıyor sayılıyor. Yani aracın cevapladığı soru “konteyner yaşıyor mu”ydu; benim sormam gereken soru “servis çalışıyor mu”ydu.

Aynı PRD’de bildirimler “v2’ye ertelendi” diye yazıyor. v2 gelmedi, servisi de kapattım. Yani o izleyici hayatı boyunca tek bir cümle söylemedi. Sessiz bir izleyici, olmayan izleyiciden daha kötü: var olduğunu sanıyorsun.

Zabbix yeşil, servis ölü

Sunucuda Zabbix de çalışıyor. İki host izleniyor, açık problem sayısı sıfır, agent’lar cevap veriyor.

Ama Zabbix’in baktığı şey host’un kendisi: CPU, disk, bellek, agent ayakta mı. “Host ayakta” ile “üstündeki servis işini yapıyor” ayrı şeyler. Zabbix tüm göstergeleri yeşilken bir webhook akışı sessizce ölebilir ve bunu hiçbir panelde göremezsin. Host ayakta olduğu sürece o yeşil yanmaya devam eder.

Gerçek kesinti nasıl görünüyor

14 Eylül gecesi 22:15 ile 23:04 arasında sunucu temiz kapanmadı. Journal kaydı ortada kesilmiş, last çıktısında shutdown satırı yok, açılışta “clock jumped backwards” uyarısı var. Neredeyse bir saat sistem yoktu; muhtemel sebep elektrik kesintisi.

Ertesi sabah her şey yerindeydi. Dosya sistemi temiz, servisler ayakta, konteynerler çalışıyor. Sistem kendi kendine toparlanmıştı, yani uzaktan bakınca hiçbir şey olmamış gibi görünüyordu. Ama o bir saat boyunca ne olduğunu ne ben biliyordum ne izleme. Öğrenmem ertesi gün journal’a bakmamla oldu.

İki olayın ortak noktası şu: kesinti gerçekti, gösterge yeşildi. Yeşil renk “bir şey olmadı” demiyor. “Bir şey benim baktığım yerde olmadı” diyor.

Uçtan uca demek ne demek

Bugün bakım betiğinin son adımı aynı soruyu iki ayrı yerden soruyor:

http://localhost:5678/webhook/health
https://n8n.yigittenekeci.com/webhook/health

Birincisi tünelin ve Access’in devrede olmadığı iç yol, ikincisi dışarıdan gerçek kullanıcının gördüğü yol. İkisinin de 200 dönmesi gerekiyor. Sadece dışarısı düşükse sorun tünelde ya da DNS’te; sadece içerisi düşükse sorun konteynerde. Cevabın hangi kattan geldiğini bilmek, sorunu aramaya başlayacağım yeri de söylüyor.

Plex’te /identity ve sabitlenmiş image tag kontrolü de aynı mantıkla duruyor. Sadece “konteyner ayakta” değil, “doğru sürüm ayakta ve cevap veriyor”.

Neyi farklı yapardım

Önce ne ölçtüğüme karar verir, sonra adresi seçerdim. “200 döndü” tek başına bir bilgi değil; kimin döndürdüğü asıl bilgi. Kontrol yazarken gövdeyi okumak, durum koduna bakmaktan daha çok şey söylüyor.

Durumları birbirine karıştırmazdım. Konteyner yaşıyor, sağlıklı, cevap veriyor — üçü ayrı şey ve üçü ayrı gösterilmeli. HEALTHCHECK’i olmayan bir konteynerin Up çıktısına sağlık muamelesi yapmazdım; o sadece bir varlık beyanı.

Günde bir kez çalışan kontrol fotoğraf çeker, nöbet tutmaz. İki dakikalık bir tünel kesintisini hiç görmez, çünkü ona hiç denk gelmez. İzleme gerçek zamanlı olacaksa, olay anında konuşmalı.

Ve v2’yi ertelemek yerine izleyiciye en baştan bir ses verirdim: bir şey ters gittiğinde Telegram’a tek satır mesaj. Hata yakalamayı sonraya bırakılan özellik, çoğu zaman hiç yazılmayan özellik oluyor.

Az ama anlamlı kontrol, çok sayıda yeşil etiketten iyidir. Yeşil göstergelere bakarken artık tek bir soru soruyorum: bu rengi üreten şey, benim merak ettiğim şey mi? Cevap hayırsa o gösterge bana hiçbir şey söylemiyor demektir.