Cloud Native Uygulamalarda İzlenebilirlik — 2. Bölüm

Serdar Kalaycı
Intertech
Published in
7 min readJul 19, 2020

Yazımın ilk bölümünde izlenebilirlik başlığı altındaki kavramların neler olduğuna değinmiştik. Bu bölümde de bu kavramlardan Gözlemleme, Loglama ve Metrik Toplama konularının nasıl uygulanabileceğinden bahsedeceğiz. Metriklerin Analizi, Veri görselleştirme, Takip Etme ve Uyarma konularına da serinin bir sonraki bölümünde bahsederek seriyi kapatacağız.

Ön not: Uygulamalarımızı izlenebilir kılmak için bir çok farklı araç açık kaynak olarak bulunabilmektedir. Ben de işin pratiğine bakacağımız bu kısımda genellikle endüstride yaygın kabul görmüş açık kaynak projeleri, bunlar arasında da mümkün olduğunca Cloud Native Computing Foundation (CNCF) (https://cncf.io) tarafından desteklenen projeleri ele alacağım.

İzlenebilirlik Bileşenleri

Gözlemleme (Monitoring)

Gözlemleme, son kullanıcı gözüyle yapılması gerektiğinden dikkat edilmesi gereken nokta, gözlemleme yapan servisinizin, gözlemlemek istediğiniz servise son kullanıcının eriştiği yoldan erişiyor olmasıdır. Örneğin aynı ağ içinde yer almaları halinde DNS servisinde oluşacak bir hatayı veya veri merkezimizin dış ağ bağlantısında oluşacak bir sorunu gözlemlememiz mümkün olmayacaktır. Bu nedenle bu uygulama için ideal çözüm veri merkezimizin dışında Zabbix (https://www.zabbix.com) gibi bir gözlemleme uygulaması kurmak veya Uptime Robot (https://uptimerobot.com) veya Pingdom (https://www.pingdom.com) gibi Monitoring as a Service (MaaS) uygulamalarından birini kullanmak olacaktır.

Loglama (Logging)

Dağıtık uygulamalarda loglama işlemi, klasik yaklaşımla çözümlemeye kalkıştığımızda birden fazla probleme yol açacaktır. Dağıtık uygulamaların hem yatayda, hem dikeyde bölünmüş olarak çalışacağı göz önüne alınarak, hem aynı servisin birden çok kopyasının ürettikleri logların, hem de birbiriyle etkileşen dikeyde ayrıştırılmış servislerin birbirini takip eden loglarının bir arada incelenebilmesi için, tüm logların merkezi bir sistemde toplanıyor olması gerekmektedir. Aynı zamanda bu ortamın tüm logların düz metin olarak yazıldığı metin dosyalarının biriktiği bir dizin yerine yapısal log verisinin saklandığı sorgulanabilir bir veritabanı tercih edilmelidir. Metinsel verileri işlemesi ve arama konusundaki kolaylığı ile Elastic (https://www.elastic.co/elasticsearch) veritabanı bu konuda evrensel bir kabul görmüş durumda. Hatta tamamı Elastic firmasına ait ürünlerden oluşan ve ELK Stack olarak adlandırılan yapı (https://www.elastic.co/elastic-stack) logların kaynaktan alınıp Elastic veritabanına taşınması için Logstash ve verilerin görselleştirilmesi işini üstlenen Kibana ürünleri ile uçtan uca bir merkezi loglama çözümü de sunuyor. Logların taşınması için CNCF mezunu bir proje olan Fluentd (https://www.fluentd.org) ve görselleştirme için Grafana (https://grafana.com) ürünleri de oldukça yaygın olarak kullanılmaktadır.

Uygulamamız cloud-native olsun veya olmasın loglama konusunda dikkat edilmesi gereken ilk kural, loglamanın çeşitli seviyelerde yapılması ve bu seviyelerin genel olarak kabul görmüş ve üzerinde uzlaşılmış olmasıdır. Yani örneğin TRACE, INFO, ERROR, FATAL gibi bir seviyelendirme üzerinde anlaşılmış ise, geliştiriciler arasında hangi durumda ERROR hangi durumda FATAL seviyelerinin kullanılacağı konusunda anlayış birliği oluşmuş olmalıdır. Uygulamanın konfigürasyonu ile bu seviyelerden hangilerinin reel olarak loglama sistemine yazılacağı çalışma zamanında ayarlanabilmelidir çünkü log yazmak, genel olarak yazılacak verinin diğer yöntemlerden daha fazla olması nedeniyle izleme yöntemleri arasında hem ağ iletişimi hem de saklama alanı olarak en maliyetlisidir.

Monolitik uygulamalarda iyi bir pratik olan, ancak dağıtık uygulamalarda olmazsa olmaz hale gelen bir loglama pratiği de tüm sistemlerin loglanması sırasında aynı formatın kullanılması ve bu formatın sonrasında log sistemlerince regular expression gibi kırılgan yapılar kullanılarak parse edilmesini beklemek yerine en baştan itibaren JSON gibi yapısal bir veri modeli olarak oluşturulması gereklidir. Bu veri modelinin de farklı servisleri geliştiren takımlar arasında kabul edilmiş ve standardize edilmiş olması, farklı servisler tarafından yazılan log kayıtlarının bir arada incelenebilmesi açısından kritiktir.

Metrik Toplama (Metrics Collection)

Metriklerin ölçülebilir sayısal değerler olduğundan ve o anda sistemimizin ne durumda olduğunu bize anlatabildiğinden ve bu verilerin zaman serisi şeklinde tutulması halinde de sistemimizin gelecekte ne duruma geleceği hakkında fikir verebildiğinden yazının ilk kısmında bahsetmiştik.

CNCF kapsamında mezun statüsüne ulaşan ikinci proje olan Prometheus (https://prometheus.io) ürünü bu konuda tüm endüstri tarafından kabul görmüş durumdadır. Prometheus, belirli standartlara uygun metriklerin yayınlandığı bir RESTful servisi belirli aralıklarla tüketmek üzere konfigüre edilebilen ve bu metrikleri zaman serisi olarak saklayabilen bir üründür. Prometheus projesi, aynı zamanda birçok programlama dili için önceden hazırlanmış metrikler ve metrikleri yayınlamak için bir RESTful servisi açma imkanı sunan kütüphaneleri de içerir. Prometheus’un metrik yayınlama formatı (https://prometheus.io/docs/instrumenting/exposition_formats/) Cloud Native Computing Foundation (CNCF) tarafından Open Metrics (https://openmetrics.io) projesi altında endüstri standardı olarak belirlenmesi çalışması devam etmektedir.

Metrik verileri (ziyaret sayısı gibi tam sayı değerler de olsa) her zaman kayan noktalı ondalık (floating point decimal) sayı olarak tutulur ve temel olarak iki kategoriye ayrılır.

Sayaç (Counter) tipi, sürekli artan değerleri tutmak için kullanılan veriyi tutmak için kullanılır. Bu veri tipini arabalardaki kilometre sayacına benzetebiliriz. Örneğin servisimize gelen talep (request) sayısı, uygulamada alınan hata sayısı gibi sürekli artan değerler sayaç tipindeki veriler olarak tutabiliriz. Ayrıca bir ürünü inceleyenlerin sayısı ve satın alanların sayısı gibi iş odaklı metrikler de sayaç tipinde saklanıp iş kararları alma konusunda destek olarak kullanılabilir.

Ölçü (Gauge) tipindeki veri belirli iki referans aralığında ileri-geri hareket edebilen değerler için kullanılır. Bu veri tipini araçlardaki hız göstergesine benzetebiliriz. Anlık CPU ve Memory kullanımları, hata/talep oranı gibi değerleri ölçü tipinde tutabiliriz. Ayrıca satın alma / sepete ürün ekleme oranı gibi iş odaklı metrikler de ölçü tipinde saklanabilir.

Tüm izleme yöntemlerinde olduğu gibi metrik konusunda da takip edebileceğimiz sonsuz seçenek karşımıza çıkacaktır. Tüm metrikleri takip etmeye çalışmak, gerçekten önemli olan metrikleri gözden kaçırmamıza neden olabileceğinden sınırlı bir set ile başlamak ve yararlı olacağına inandığımız metrikleri zaman içinde eklemek daha doğru bir yaklaşım olacaktır.

Uygulama Metrikleri

Uygulamalar için en kolay uygulanabilecek ve en kolay anlaşılan yaklaşım Google tarafından ortaya atılmış olan RED desenidir.

RED Deseni

Web tabanlı hizmetler için önerilen bu desen, Request, Errors, Duration metriklerinin ilk harflerinden üretilmiştir. Buna göre her bir servisin talep sayısı, bu talepler arasında hata alınanların sayısı, ve bu taleplere yanıt vermemiz için geçen süreyi takip etmek yeterlidir. Bu yaklaşım özellikle Google Site Güvenilirlik Mühendisliği (Site Reliability Engineering, SRE) ekipleri tarafından benimsenmiş ve tüm servislerin aynı metriklerle takip ediliyor olmasını, servisleri takip eden ve ilk müdahaleyi yapan ekipler açısından işi çok kolaylaştırdığını iddia ederek savunmuşlardır.

İş Metrikleri

İş birimlerinin takip etmek ve iş anlamı çıkarabileceği bir çok metriğin (ana sayfa ziyaretlerinin satışa dönüşme oranı gibi) yanı sıra sistemi geliştiren ve sistemin sağlığı için çalışan ekip için de anlam ifade edebilecek yardım sayfalarının görüntülenme miktarı veya eğer varsa servis durumu sayfanızın (örneğin https://status.azure.com/en-us/status) ziyaret sayısı, sisteminizde bir şeylerin ters gittiği anlamına gelebilir.

Kubernetes Metrikleri

Kubernetes platform hakkında metrikleri toplayabileceğimiz araçlar sunar. En temel seviyede Google tarafından geliştirilmiş bir araç olan cAdvisor (Container Advisor https://github.com/google/cadvisor) container’lar için kaynak kullanım ve performans metriklerini toplar. Kubernetes bu aracın ürettiği metrikleri kullanarak yeni bir pod’un hangi node üzerinde çalıştırılacağına veya yatayda genişleme yapılıp yapılmayacağına karar verir. Ayrıca kube-state-metrics (https://github.com/kubernetes/kube-state-metrics) adındaki araç ile, Kubernetes API tarafından oluşturulan tüm Kubernetes üzerindeki tüm objeler (node, pod, deployment vb) hakkındaki metrikleri Prometheus tarafından tüketilmeye hazır bir biçimde /metrics uç noktası ile 8080 portundan sunar. Tahmin edilebileceği gibi bu arayüzden yüzlerce metrik yayınlanmakta ve proje kapsamında metrik sayısı gün geçtikçe artmaktadır. Güncel metrik bilgilerine projeye ait dokümantasyon üzerinden (https://github.com/kubernetes/kube-state-metrics/tree/master/docs) ulaşılabilir. Yine başlangıçta en kısa vadede maksimum yarar sağlayabileceğimizi düşündüğümüz bir set ile başlamak ve zaman içinde takip alanımızı genişletmek yararlı olacaktır.

Cluster Sağlığı Metrikleri

Kubernetes cluster’ımızın sağlığını takip edebilmek için aşağıdaki metrik setini takip etmek yararlı olacaktır.

  • Node sayısı ve sağlığı
  • Node başına ve toplam kaynak miktarı ve kullanımı

Pod/Container Metrikleri

Kubernetes üzerinde çalışan pod ve containerlarımız için aşağıdaki metrikleri takip edebiliriz;

  • Node başına ve toplam pod sayısı
  • Her bir container için kaynak kullanımı ve bu kullanımın request ve limit bilgisine oranı (1)
  • Her bir pod için Liveness/Readiness durumları (2)
  • Container/Pod restart sayıları
  • Her bir container için giriş/çıkış ağ trafiği

(1) Resource Requests/Limits: Tüm standart container çalışma zamanları (Docker, CRI-O, Containerd) bir container için çalışma zamanında o container için ayrılacak minimum ve maksimum CPU ve memory kaynağını tanımlamamıza olanak verir. Kubernetes yeni bir pod yaratılacağı zaman mevcut bütün podların request ve limit bilgilerine bakarak hangi node üzerinde yaratması gerektiğine karar verir veya yeni bir pod için yeterli kaynağı yoksa yaratılmasını erteleyebilir.

(2) Liveness/Readiness Probes: Kubernetes üzerinde bir pod tanımlanırken pod’un çalışır hale geldiğini ve sağlıklı çalışıp çalışmadığını Kubernetes’in kontrol etmesini sağlayan yapılardır. Basit bir şekilde Kubernetes’e podunuzun açtığı bir uç noktaya (genel olarak uygulamanızın asıl uç noktaları ile karıştırılmasını da engellemek açısından /healtz uç noktası kullanılmaktadır.) http istekleri göndermesini sağlayabiliriz.

Yukarıdaki örnekte pod çalıştırıldıktan sonra ilk olarak 5 saniye, sonra da her 3 saniyede bir 8888 portundan /healtz uç noktasına http Get işlemi yapılması istenmiştir. Bu talebe 2xx veya 3xx HTTP kodlarından birinin dönmesi halinde Kubernetes pod’un hayatta olduğunu kabul eder, aksi halde podun restart edilmesi işlemini başlatır.

Readiness probe, eğer uygulamanızın çalıştıktan sonra hazırlanmak için bir süreye ihtiyacı varsa veya dış kaynaklara sıkı bağlı çalışmak zorundaysa kullanılabilecek bir seçenektir. Yani pod hayatta olsa da hizmet verebilir olup olmadığının kontrol edilmesidir. Yukarıdaki örnekte pod çalıştırıldıktan sonra ilk olarak 15 saniye, sonra da her 30 saniyede bir 8888 portundan /healtz uç noktasına http Get işlemi yapılması istenmiştir. Bu talebe 2xx veya 3xx HTTP kodları haricinde bir HTTP response code dönmesi halinde Kubernetes pod’un sağlıklı çalışmadığını düşünerek bağlı olduğu servisten çıkartır ve trafik almasına izin vermez.

Kubernetes üzerinde http dışında da probe seçenekleri mevcuttur. Aşağıdaki örneklerde tcp ve basit komut çalıştırma örnekleri görülebilir.

Liveness ve readiness probe özelliği hem pod seviyesinde gözlemleme imkanı sunarken hem de kendi kendine iyileşme (self healing) imkanı sağladığından Kubernetes ortamında çalışacak tüm uygulamalar için olmazsa olmazdır denilebilir.

Deployment Metrikleri

Tüm deployment tanımlarımız için aşağıdaki metrikleri incelememiz oluşan problemleri hızlıca görmemize ve oluşabilecek problemleri önceden kestirebilmemize yardımcı olacaktır;

  • Deployment sayısı
  • Her deployment için tanımlanmış replica sayısı
  • Her deployment için sağlanamayan replica sayısı

Çalışma Zamanı (Runtime) Metrikleri

Programlama dilleri için hazır metrik kütüphaneleri bu dillerin çalışma zamanları ile ilgili de birçok metrik yayınlayabilmektedir. Kullanılan dile uygun olarak bu metriklerin takip edilmesi de uygulama sağlığının takibi açısından kritiktir.

  • Aktif process/thread/goroutine sayısı
  • Heap ve stack kullanımı
  • Nonheap memory kullanımı (kullanılan dil destekliyorsa)
  • Garbage collector çalışma ve duraklama süreleri (kullanılan dil destekliyorsa)
  • Açık tutulan dosya sayısı
  • Açık tutulan ağ portu sayısı

Serinin bu bölümünde en kolay ve doğru pratiği bu hizmeti dışarıdan almak olan Gözlemleme, Loglama ve Metrik Toplama ve Metriklerin Analizi konularına değinmiş olduk. Gözlemleme ve Loglama genellikle yazılım ekiplerinin aşina olduğu konular. Ancak bu yaklaşımlar genellikle reaktif olarak hareket etmemize olanak sağlıyorlar. Metrik konusu oldukça uzun, bir o kadar kritik ve malesef genellikle göz ardı edilen bir konu. Metrik verisinin toplaması ve saklaması log verisinden daha kolay olmasının yanısıra verinin doğru analizi ile de proaktif davranmamıza imkan sağlayacak bir yaklaşım.

Bu bölümü daha fazla uzatmamak için metrik verisinin nasıl analiz edileceğini bir sonraki bölüme bıraktım. Daha sonra verilerin görselleştirilmesi, Takip Etme ve Uyarma konularından bahsedip seriyi noktalayacağız.

Serinin üçüncü bölümüne buradan erişebilirsiniz.

--

--