Fatih GÜL
6 min readDec 14, 2019

Kubernetes In Action kitabında okuduğum bölümleri paylaşıyorum. Kitap değerlendirmesi için bir önceki yazı: https://medium.com/@fatihgul/kubernetes-in-action-ac77eb406d89

1- Introducing Kubernetes — Giriş (Haydi Dümen başına)

Yıllar önce olduğu gibi hâlâ günümüzde de tek server üzerinde ya da bir kaç servere yayılmış büyük monolithic uygulamalar varlığını devam ettirmektedir. Bu metodolojiyi benimsemiş legacy sistemler hala çok yaygın olarak kullanılmakla birlikte ağır işleyen bir release yönetimi vardır. Her release sonrası developerlar tüm her şeyi paketleyip operasyon takımına ilettikten sonra operasyon takımı bu paketi deploy edip monitör etmekle(izlemekle) ve uygulamanın fail olması durumunda bu paketi tekrar çalışır duruma getirmekle sorumludurlar.

Bugün bu büyük monolithic uygulamaların yerini kendisini meydana getiren birbirinden bağımsız çalışabilen microservice olarak adlandırdığımız atomik yapıda daha küçük bileşenler alıyor. Bu bileşenler birbirinden çok iyi yalıtıldığı ve ayrıştırıldığı için (decouple), her birinin kendine özgü ve diğerlerinden bağımsız işleyen development, deployment ve scaling süreçleri vardır. Bu da doğal olarak monolithic uygulamayla karşılaştırdığımızda değişime çok daha hızlı adapte olabilen, çevik bir sisteme doğru yürüdüğümüzü gösterir.

Büyük monolithic uygulamamızı küçük çok sayıda bileşene ayırdığımız ve veri-merkezlerimizin de gittikçe büyüdüğünü göz önüne aldığımızda bu sefer çok sayıda küçük bileşenin bir bütün gibi davranmasını beklememiz aslında tırmanılması gereken dik bir yokuşa geldiğimizi fark etmemiz demektir. Çünkü çok sayıda componenti konfigure etmek, yönetmek, çalıştırmak, sorunsuz bir şekilde birbiriyle haberleştirmek, davranışlarını izlemek çok zor bir süreçtir. Hangi componentin nerede çalışması gerektiği, kaynak tüketimini minimalize etme problemleri, manuel yürütülen süreçler, fail ve scale etme gibi durumlarda işin içine girince bütün bu süreci sorunsuz, hızlı, güvenilir ve sağlam bir şekilde yürütmek için otomasyon kaçınılmaz olur. İşte Kubernetes de tam burada devreye girer.

Kubernetes sayesinde developer ne zaman isterse uygulamasını kolaylıkla dışardan yardım almadan deploy edebilir. Artık release yönetimindeki ağır işleyen süreç de yerini daha çevik bir sürece bırakıyor. Sadece developer için değil aynı zamanda operasyonel takım içinde işleri kolaylaştırıyor. Her bir bileşeni(microservice) izleme, fail durumlarında deploy etme, ihtiyaç halinde scale etme, bileşenleri birbirleriyle haberleştirme, configure etme gibi sorumlulukları kubernetes devralıp, altyapısal diğer geliştirim ve yönetim işleri için operasyon takımına alan genişletiyor. Artık netice olarak birim zamanda hem developer hemde operasyonel ekip daha az sorunla karşılaşıp daha fazla ve sağlam çıktı üretmeye başlıyor. Ben bu olayı zamanın genişlemesi diye tabir ediyorum.

Kubernetes çalıştığı data-center’ı soyutlayıp tek bir kaynakmış gibi sunmasının yanında arka planda üzerinde çalıştığı sunucular hakkında da bilgi sahibi olmanızı beklemiyor. Bir çok bileşeninizi temel bilgiler içeren konfigurasyonel dosyaları şeklinde talimatlarla Kubernetese ilettiğinizde Kubernetes bu bileşenleri istediğiniz konfigurasyonda ayağa kaldırıp aynı zamanda birbirleriyle de haberleşmesini sağlıyor. Fail durumlarını handle etmekle birlikte scale işlemleri içinde yük Kubernetes’in omuzlarında artık!

1.1 Understanding the need for a system like Kubernetes Kubernetes’e duyulan ihtiyaç

Kubernetes dünyasının kapısını çalıp içeri misafir olmadan önce son yıllardaki development ve deployment süreçlerinde meydana gelen değişikliklere bir göz atalım. Aslında development olarak büyük monolithic uygulamalardan microservice mimariye geçiş, bu geçiş neticesinde etkilenen deployment süreçleri ve bu süreçlerin gerçekleştiği alt yapılardaki evrimselleşmeleri ne kadar iyi kavrarsak Kubernetes ve Docker gibi container teknolojilerine o kadar iyi hakim oluruz.

1.1.1 Moving from monolithic apps to microservices — microservice mimariye geçiş

Monolithic uygulamanın içerdiği componentler birbirine sıkı sıkıya bağlıdır(tight coupled) ve bu componentlerin development, deployment ve yönetimi(management) sanki tek bir entity gibi olur ve esasında bu bir tek OS(işletim sistemi) processidir. Monolithic uygulamamızın herhangi bir componentinde yapılan değişiklik diğer componentleri etkilemeyen bir değişiklik olsa bile uygulamanın bütününü etkilediğinden tekrar deploy edilmesine neden olur. Monolithic uygulamamıza eklenecek olan yeni modül ve modüllere eklenen yeni özelliklerle uygulamamızın kod hacmi, kapsamı ve karmaşıklığı da giderek artar.

Monolithic uygulamamızı taşıyacak güçlü omuzlara, serverlara yani sunuculara ihtiyacımız olacak. Sunucularımıza gelen yük arttığında sunucularımızı iki şekilde scale edebiliriz. Ya sunucuların bulunduğu cpu, memory ve diğer componentlerdeki kaynak(resource) miktarlarının büyüklüğünü arttıracağız(scale-up) ya da uygulamamızdan birkaç tane instance daha oluşturacağız(scale-out). Scale-up yaparken uygulamamızda herhangi bir değişiklik yapmak gerekmiyor ama nispeten pahalı bir çözüm olduğu açık. Diğer yandan Scaling-out ise daha ucuz olmasına rağmen buna karşılık implementasyonu daha zor ve bazen mümkün olmuyor. Neticede monolithic uygulamanın herhangi bir componenti ölçeklendirilemiyorsa uygulamanın kendisinin ölçeklenemez olduğu gerçeğiyle karşılaşıyorsunuz ve monolithic uygulamayı daha küçük componentlere(microservice) ayrıştırmaya başlıyorsunuz.

SPLITTING APPS INTO MICROSERVICES — Mikroservicelere bölünme zamanı

Yukarıda değindiğimiz ve değinmediğimiz daha başka problemlerden dolayı complex monolithic uygulamamızı daha küçük, birbirinden bağımsız deploy edilebilen mikroservicelere ayırıyoruz. Her mikroservice diğerlerinden bağımsız, yalıtılmış bir processe sahipken diğerleriyle de bir api arayüz aracılığıyla iletişim halindedir.

Microservicelerin birbiriyle olan iletişimi synchronous veya asynchronous biçimde olabilir. Genelde synchronous iletişim HTTP protokolü üzerinden RESTful(REpresentational State Transfer) API aracılığı ile sağlanırken, asynchronous iletişim ise AMQP(Advanced Message Queueing Protocol) gibi asynchronous protokoller yardımıyla sağlanır. Bu iletişim protokolleri sayesinde her microservice o işin doğasına uygun kendine özgü dil ve framework ile yazılabilir.

Her microservice tek başına static ip’si olan bir sunucu üzerinde ve standalone process olarak çalışır. Bu da her microservice için birbirinden bağımsız deployment ve development sürecini mümkün kılar.

SCALING MICROSERVICES — microservicelerin ölçeklenmesi

Monolithic sistemlerde bir component ilgisiz diğer componetlerle de sıkı sıkıya bağlı olduğundan aslında monolithic uygulamanın bütün olarak scale edilmesi söz konusu olmakla birlikte scaling işlemi göz korkutucu hale gelebiliyor. Monolithic sistemlerin tersine microservice içeren mimarilerde service bazlı scale işlemi yapılabilmektedir. Yani ihtiyaç halinde ilgili microservice diğer microservicelerden bağımsız olarak farklı sunucular üzerinde scale edilebilmektedir. Bu sırada diğer microservicelerin sayısı değişmeden kalmaktadır.

DEPLOYING MICROSERVICES — microservicelerin deploy edilmesi

Her şey artısı ve eksisi ile geldiği gibi microservice mimarisinin de getirdiği ek yükler, çözülmesi gereken yeni problem kümeleri vardır. Birkaç tane deploy edilebilen atomik componenti yönetmek kolaydır. Ama bu sayı giderek büyüdüğünde deployment stratejisi ile ilgili alacağımız kararlar ve uygulayacağımız yöntemlerdeki zorlukta beraberinde büyümektedir.

Microservicelerin sayısından ziyade bir takım gibi hareket edip bütünlük sağlaması önemlidir. Microservicelerin birbirlerini bulmaları ve sürekli iletişim halinde olmaları gerekir. Bunlarda gerekli konfigurasyonların yapılmasına bağlıdır. Microservice sayısı arttıkça da doğal olarak hata eğilimi artmaktadır ve özellikle sunucuların fail ettiği durumları düşündüğümüzde bu durumu handle edecek olan operasyonel ekibin işi gittikçe zorlaşacaktır.

Sadece deploy etme değil aynı zamanda bu microserviceler arasındaki iletişimi debug ve trace etme gibi ayrı bir zorluk da karşımıza çıkıyor. Dağ ne kadar yüce olsa da yol üstünden aşar sözünü referans alarak bu problemin üstesinden gelen tracing ve debugging çözümleri de bulunmaktadır.

UNDERSTANDING THE DIVERGENCE OF ENVIRONMENT REQUIREMENTS

Microservice mimarisinin getirdiği yenilik sadece microservicelerin birbirinden bağımsız deploy edilebilmesi değil aynı zamanda birbirinden bağımsız ve izole bir şekilde geliştirme(development) olanağı sağlamasıdır. Birbirinden bağımsız geliştirme olanağına sahip olması demek her microservice ekibinin ve sahibinin farklı olması ve bu farklı ekiplerin kullandığı kütüphanelerin farklı olması hatta aynı kütüphanelerin farklı versiyonlarının kullanılması gibi durumlar ortaya çıkması demektir ve bu engellenemez bir gerçekliktir.

Böyle bir durum deployment olayları ile ilgilenen operasyonel ekip için kabusun başlaması demektir(Bu durumu container olmadan düşünüyoruz). Çünkü özellikle aynı host üzerinde deployment yapılacak olan microservicelerin kullandığı aynı kütüphanelerin farklı versiyonları conflictlere neden olacaktır. Bunun yanında microservice sayısının artması ile bu tarz problemlerle başa çıkmak inanılmaz güçleşecektir.

1.1.2 Providing a consistent environment to applications — Uygulamalar için tutarlı ortamlar sağlanması

En büyük problem geliştirilen ve deploy edilen microservice sayısından ziyade microservicelerin development’ı yapılan ortam ile deployment’ı yapılan pruduction ortamı arasındaki farklılıklardır. Sadece development ve production ortamlarındaki farklılık değil aynı zamanda production ortamları da birbirinden farklı olabiliyor. Hatta aynı production sunucusunda zamanla ortam değişkenleri de değişebiliyor. Yani sırtımızı dayadığımız yegane gerçeklik değişim!

Bu farklılıklar donanımdan(hardware) işletim sistemlerine oradan da kullanılan kütüphanelere kadar uzayan bir silsile halinde devam ediyor. Production ortamının yönetimi operasyonel ekipte iken development ortamı geliştiricilerin laptoplarıdır. Dolayısıyla her iki grup için olaya bakış açısı ve önem sırası farklılaşmaktadır. Operasyonel ekip için önemli olan güvenlik yamaları, sistemin güncel tutulması gibi önemli meseleleri development ekibi pek önemsemez.

Production sistemlerde development laptoplarında olmayan farklı development ekiplerinin geliştirdiği uygulamalar da mevcuttur. Production bütün bu uygulamalar için tutarlı bir ortam sağlamalıdır.

Production ortamındaki görünebilecek problemleri azaltmak için development ortamı ile production ortamını senkronize etmek gerekiyor. Bunun yoluda production ile development ortamı arasındaki işletim sistemi, kullanılan kütüphaneler, ortam değişkenleri, networking ayarlamalar dahil her şeyi eşitlemekten geçiyor. Hatta mümkünse aynı sunucu üzerine herhangi bir değişiklik yapmadan farklı uygulamalar deploy edebilme kabiliyetinin sağlanması da gerekmektedir!

Bu bölüm henüz tamamlanmadı. Hazır oldukça yayınlamaya devam edeceğim. Kalan konular aşağıda işaretlenmiştir. Bir sonraki yazı ise Introducing container teknologies.