deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Reboot, /var/tmp'yi temizledi ve Kafka Connect zstd sıkıştırmasını sessizce bozdu

dev.to'da yayınlanan bir postmortem, kernel yaması için yapılan reboot'un tmpfs destekli /var/tmp'yi nasıl temizlediğini ve Kafka Connect worker'ını sabitlenmiş JVM temp dizini olmadan, kayıtları zstd ile sıkıştıramaz durumda bıraktığını anlatıyor.

Reboot, /var/tmp'yi temizledi ve Kafka Connect zstd sıkıştırmasını sessizce bozdu

Sağlıklı görünen ama gönderim yapamayan bir worker

dev.to'da yayınlanan bir postmortem, rutin bir kernel yaması reboot'unun Kafka Connect worker'ını REST çağrılarına yanıt verirken ve connector'ını RUNNING olarak bildirirken nasıl bıraktığını, oysa arka plandaki task'in başarısız olduğunu anlatıyor. Host'u kernel 6.1.188-233.386 sürümüne taşıyan yama, 2026-10-08 tarihinde yaklaşık 16:10 UTC'de yapılan bir reboot ile devreye girdi; o akşem 22:18 IST itibarıyla ekip, yığın izi birkaç ekran boyunca uzanan FAILED durumundaki bir task'i triage ediyordu.

Host, AL2023 tarzı bir image üzerinde dağıtık bir Connect worker'ı çalıştırıyordu ve producer override'ı zstd sıkıştırmayı zorlayan bir source connector'a sahipti. Systemd unit'i, JVM temp dizinini bilinçli olarak JAVA_TOOL_OPTIONS=-Djava.io.tmpdir=/var/tmp/kafka ile sabitliyordu — temp dosyalarına bilinen bir yol vermenin mantıklı bir yolu, ancak reboot sonrası bu yolu yeniden oluşturacak hiçbir mekanizma yoktu. Paket hiçbir tmpfiles.d parçası içermiyordu ve unit'te dizini oluşturup chown yapacak bir ExecStartPre yoktu. Bu image'de /var/tmp tmpfs olduğu için reboot onu sildi ve fleet'teki bir kardeş worker da aynı kusuru taşıyordu.

zstd hatayı neden gecikmeli hale getirdi

Postmortem'e göre bozulma yalnızca task kayıt üretmeye çalıştığında ortaya çıktı, başlangıçta değil. Kafka'nın zstd desteği zstd-jni üzerinden çalışır ve ilk kullanımda platforma özgü bir native kütüphaneyi java.io.tmpdir içine açar. Dizin gittiği için File.createTempFile bir IOException fırlattı, zstd sınıflarının static initializer'ı başarısız oldu ve sonraki her sıkıştırma denemesi, sendRecords civarında bir ConnectException'a sarılmış bir NoClassDefFoundError ile öldü.

Bu dizilim yanıltıcı görüntüyü açıklıyor: worker temiz bir şekilde boot oldu, 8083 portundaki REST ayakta kaldı ve yalnızca veri yolu bozulmuştu. Yazarın ilk içgüdüsü bir classpath sorunuydu, çünkü NoClassDefFoundError genellikle eksik bir jar'a işaret eder; ancak izdeki "cannot unpack" ve File.createTempFile çerçeveleri, native kodun diske yazma başarısızlığına işaret ediyordu. Önce dizini oluşturmadan servisi yeniden başlatmak yalnızca çökmeyi yeniden üretti ve yalnızca task'i yeniden başlatmak, initializer'ı çoktan takılmış bir JVM'i kurtaramazdı. Yazar artık, status JSON'da önbelleğe alınmış muhtemelen eski bir iz yerine, REST status endpoint'inden gelen task state alanına ve taze worker loglarına güveniyor.

8778 portundaki izleme gürültüsü

Triage sırasında Telegraf, localhost:8778'deki Jolokia için her on beş saniyede bir connection-refused hatası logladı. Bunun ilgisiz olduğu anlaşıldı: Connect unit'i JMX metriklerini 7073 portundaki JMX Prometheus üzerinden açığa çıkarıyordu ve 8778 yalnızca izleme yapılandırmasında vardı. Yazar, metrik boşluğunu veri yolu kesintisinden ayrı bir ticket olarak ele aldı ve ilgili bir tuzağa dikkat çekti — EC2 reboot zaman damgaları ve Telegraf log satırları UTC olarak gelirken ekip IST ile düşünüyordu, bu da dönüştürülmeyen her zaman çizelgesini çarpıtır.

Çözüm

Acil onarım, dizini kafka sahipliği ve 1770 modu ile oluşturmak, servisi yeniden başlatmak, ardından başarısız task'i REST üzerinden yeniden başlatmaktı. Task RUNNING durumuna döndü ve o pipeline parçasındaki aşağı akış lag'i — dizin var olana kadar source connector üretemediği için asıl etki buydu — boşaldı.

Kalıcılık için postmortem, systemd'in dizini her boot'ta yeniden oluşturması için d /var/tmp/kafka 1770 kafka kafka - gibi bir tmpfiles.d girdisi öneriyor; isteğe bağlı olarak unit içinde ExecStartPre mkdir ve chown satırlarıyla desteklenebilir, ikisi de manuel bir reboot sonrası adımı olarak bırakılmak yerine configuration management üzerinden yönetilmelidir. Producer sıkıştırma override'ını lz4, snappy veya none'a geçirmek native unpack'i tamamen aşardı, bunun bedeli sıkıştırma oranı veya CPU olurdu; ekip zstd'yi korudu ve dizini düzeltti. tmpfiles.d değişikliğinin ve Telegraf temizliğinin fleet geneli dağıtımı, incident kapatıldığında hala açıktı.

Neden önemli

java.io.tmpdir'i tmpfs destekli bir yola sabitleyen — ya da ilk kullanımda kendini tembelce açan bir native kütüphaneye bel bağlayan — herhangi bir JVM servisi bu hata modunu taşır ve rutin yama reboot'ları tam da bu modun ortaya çıktığı andır. Yalnızca REST'e veya süreç durumuna vuran health check'ler kayıtlar akmayı durdururken geçmeye devam eder ve ortaya çıkan yığın izi, araştırmacıları eksik bir dizin yerine classpath'lere ve broker'lara yönlendirir. Ucuz sigorta tek satırlık bir tmpfiles.d parçası artı bir ExecStartPre'dir ve ucuz teşhis, başka yerde zaman harcamadan önce tmpdir'in var olduğunu doğrulamaktır. Unit dosyaları, ortam ayarları ve dosya sistemi düzeni, uygulamanın kendisi kadar configuration management titizliğini hak eder.

  • #kafka
  • #kafka-connect
  • #systemd
  • #devops
  • #incident-postmortem

İlgili yazılar