Söz Verme Teorisi (Promise Theory) ve Kubernetes

“Söz verme teorisi tam da bu işte. Kubernetes sizin ‘istediğiniz durumu’ (desired state) kabul eder, ve eğer gereksinimlerinizi karşılayamazsa, size sebebini söyler. Bu örnekte, yeni bir makine eklemeniz veya var olan birinin sağlıklı hale gelmesini beklemeniz gerekiyor; ardından Kubernetes uygulamanın makine üzerinde çalıştırılması için gerekli planlamayı yapacaktır(schedule).” Kelsey Hightower’ın ilginç bir Kubernetes hatasına dair tweet’e cevabı
“Kendi kendine düzelme (self healing), istenen nihai durum (desired end state), otomatik hata düzeltimi gibi CFEngine içinde var olan özellikler, Kubernetes vb. araçlar tarafından benimsendi ve bugün bulutta gördüğümüz otomatik elastik ölçekleme fonksiyonları artık olağan görülmeye başlandı.” Mark Burgess
Bir teorik fizikçiydi Mark Burgess.
1992 yılında doktora sonrası araştırma için Norveç’in Oslo Üniversitesine gitti. O sıralarda üniversitenin bilgi işlem altyapısında ağırlıklı olarak Unix tabanlı Sun Microsystems benzeri terminaller kullanılmaktaydı. Fizik araştırmaları kapsamında bu bilgisayarları kurcalaması, değişiklikler yapması, bilgisayarlar arası ağ kurması filan gerekti. Bilgisayarlarla haşır neşir oldukça, onlara olan ilgisi arttı ve derinlemesine incelemeye başladı. Bir akademisyen olmanın getirdiği biçimlenmenin etkisiyle öncelikle elindeki şeyi anlamaya ve doğasını keşfetmeye çabaladı. Bu çabasını besleyen şey “bir şeylerin çalışmasını sağlamanın bilim değil teknoloji olduğu, bilim olması için arkada yatan teoriyi anlamamız ve onu daha büyük bir resimle ilişkilendirerek düşünmemiz gerektiği” yönündeki düşüncesiydi.
Bilgisayarlara dair zihnini kurcalayan ilk problem ise konfigürasyon yönetimi oldu.
Konfigürasyon Yönetimi ve CFEngine’nin Doğuşu
O sıralarda yaygın olarak Unix türevi işletim sistemine sahip makineler kullanılmaktaydı. Günümüzdeki Linux makinelerin aksine Unix makineler birbirinden çok farklıydı. Bu durum da farklı tipteki Unix makineleri kurmayı ve yapılandırmayı çok fazla uğraştırıcı kılıyordu. Mesela bir konfigürasyon için bir script yazıp bunu her yerde çalıştırmak çok da mümkün değildi.
Burgess’in zihnini kurcalayan bu probleme getirdiği çözümse belliydi: yeni üst bir katman oluşturarak alttaki farklılıkları yok etmek yani farklı tipteki makineleri soyutlayarak modellemek. Bilgisayarı ifade eden “makine” diye zihinsel bir model tasavvur edersiniz ve farklı işletim sistemindeki implementasyonları bu modelin ardına gizlersiniz. Hayali “makine”nizin tipiyse Solaris, AIX veya HP-UX gibi herhangi bir şey olabilir. O zamanlar kimsenin gündeminde makinelerin konfigürasyon yönetimi diye bir problem yoktu. Aslında yönetilecek binlerce makine de yoktu. Genel düşünce “bilgisayarı kurarsın ve kullanırsın” şeklindeydi.
Bu modelleme ve soyutlama ihtiyacı, türünün ilk örneği olan CFEngine (Configuration Engine) aracını doğurdu 1993 yılında.

Halihazırda var olan araçlara fazla odaklanan bazı eleştiriler, bu işin birkaç script ve make aracıyla yapılabileceği şeklindeydi.
Bu argüman doğru olsa da gözden kaçırılan, CFEngine’nin sunduğu üst seviye yeni bir deklaratif konfigürasyon dili ve soyutlama sayesinde yüzlerce satırlık scriptler yazma ihtiyacını ortadan kaldırması, tekrar tekrar çalıştırıldığında hep aynı sonucu verecek biçimde (idempotent) tasarlanması, if-else koşulu tabanlı uzun kontroller yerine etiket tabanlı bir sistem sunmasıydı. Özetle sistem bakım işlerinin yönetimini ve otomasyonunu oldukça kolaylaştırmasıydı.
İlk nesil CFEngine’nin işleyişi şöyleydi:
- Merkezi bir konfigürasyon sunucusunda yer alan bir dosya içerisinde farklı tipteki dağıtık makinelerden oluşan sistemin konfigürasyonu tanımlanıyordu.
- Yönetilecek her bir makineye CFEngine uygulaması yükleniyordu.
- Manuel olarak veya cronjob benzeri bir araçla periyodik olarak CFEngine uygulaması tetikleniyor, o da merkezi sistemden konfigürasyonu çekip ve makineye uyguluyordu.
CFEngine’nin açık kaynak GNU projesi olarak yayımlanması geniş kitlelere ulaşmasını sağladı. Proje CERN tarafından benimsendi ve kullanıldı. Burgess projeyle ilgili ilk sunumunu bir CERN kongresinde yaptı. Bunu diğer yerler takip etti.
CFEngine türünün ilk örneği ve konfigürasyon yönetimi konusunda diğerlerine ilham kaynağı olan bir araç. Altyapının kodla oluşturulması (infrastructure as code) yaklaşımında CFEngine’nin açtığı yoldan ilerleyen popüler diğer örneklerin bazılarıysa Puppet, Chef, Ansible.

Bilgisayarların Bağışıklık Sistemi ve Kendi Kendine İyileşme
Makineler ve konfigürasyonları üzerine araştırmaya ve düşünmeye devam eden Burgess’in ulaştığı bir sonraki zihinsel aşama “hatayı kabullenmek” oldu. Hatasız sistemler peşinde koşmanın anlamsız olduğu, makinelerin elbet bir gün bozulacağını kabullenmenin ve bu hata durumunun otomatik olarak nasıl düzeltileceğine odaklanmanın daha doğru olacağını düşündü.
Bu düşüncesini besleyen fikirlerden biri de entropi kavramı oldu. Entropi bir sistemdeki düzensizliğin ölçüsüdür. Fizikteki termodinamik yasasına göre kapalı bir sistemdeki düzensizlik azaltılamaz, ya sabit kalır ya da artar. Dolayısıyla bir makine nihayetinde çevresel etkilerden dolayı veya başka herhangi bir sebeple bozulacaktır.
Entropi kavramının yazılım geliştirme dünyasına da yansıması oldu. Buna göre, yapılan her bir ek geliştirme veya değişiklik sistem karmaşıklığında ve düzensizliğinde artışa sebep olmaktadır. Bunun ilacıysa:
- Herkesin kendi evinin önünü süpürmesi (kırık camlar teorisi)
- Yeniden düzenleme ve modellemelerle (refactoring) karmaşıklığın ve düzensizliğin azaltılması
- Teknik borç (technical debt) birikiminin önüne geçilmesidir.
Burgess yarattığı makine soyutlamasını kullanarak “istenen nihai durum”u (desired end state) deklare etmeyi, makineler bozulduğu veya hata aldığı aldığı durumda arkada çalışacak bir mekanizmayla tekrardan istenen duruma yakınsamaya çalışacak (convergence) bir metodoloji geliştirdi. Bu yaklaşımda her bir makine için bir istenen nihai durum deklare ediliyor ve bu durumdan uzaklaşmalar (divergence) periyodik kontrollerle tespit edilip tekrardan istenen duruma yaklaşmak üzere mekanizmalar devreye sokuluyordu.
Burgess bu yaklaşımını anlatmak üzere Amerika’ya gitti, fakat hiç kimse neden bahsettiğini anlamadı. Buna canı sıkıldı ve dönüş yolunda uçaktayken canlılardaki bağışıklık sistemi mekanizmasını “istenen nihai durum” kavramını anlatmak için kullanıp kullanamayacağını düşündü. Eve döndükten sonra bu fikir üzerinde çalıştı ve ertesi yıl 1998'de Lisa konferansında sunumunu yaptı.

Bilgisayar bağışıklık sistemi canlılardaki bağışıklık sistemini referans alıyor. Canlılardaki bağışıklık sistemi, dış dünyadan zararlı virüslerin bünyeye gireceği gerçeğini kabulleniyor ve bunları tespit edip etkisiz hale getirmek için proaktif ve reaktif yöntemler barındırıyor. Bağışıklık sisteminin varlığı doktorlara olan ihtiyacı ortadan kaldırmıyor. Aksine hayatı onlar için daha çekilir kılıyor. Çünkü en küçük rahatsızlıkta doktora gitmeye, bir hapı ağzımıza atmak için doktor çağırmaya ihtiyaç duymuyoruz.
Bilgisayar bağışıklık sistemi de insanlara daha az iş yüklemekle ilgilidir. Manuel müdahaleler yerine makinelerin kendi kendine iyileşmeleri (self-healing) ve kendi kendilerini düzeltmeleri (self-correcting) için gerekli mekanizmaları oluşturmakla ilgilidir.
Bu mekanizmaların kurulabilmesi içinse yazılım sağlığı kontrollerinin (health-check) geliştirilmesi gerekiyor. Hastalıklı durumla sağlıklı durumun veya iyiyle kötünün ayırt edilebilmesi için gerekli kriterlerin belirlenmesi gerekiyor. Eğer bu kriterleri bir yazılım tarafından tespit edilebilecek şekilde tanımlayabilirsek, hastalığın önlenmesi veya iyileştirilmesi için gerekli bağışıklık sistemini de inşa edilebiliriz.
Bir uygulamada hata oluştuğu zaman, ne olduğu ve ne zaman olduğu hakkında en iyi bilgiye yine uygulamanın kendisi sahip olur genellikle. Dış dünyadaki gözlemciler sadece tahmin edebilir. Bu sebeple uygulamanın durumu hakkındaki geri bildirimi uygulamanın kendisi vermelidir. Sistem geneli bir bağışıklık mekanizması kurabilmek için de uygulamaların dışarıya bu sinyalleri iletmesi gerekir.
Bir bağışıklık sistemi içinde bulunduğu çevreyi tanımalı, değişimlerden sürekli haberdar olmalı ve gereken durumlarda devreye girmelidir. Örneğin makinenin CPU ve bellek kullanımlarını takip etmeli ve gerekirse aşırı bellek kullanan bir uygulamayı kapatabilmelidir. Bunu sağlamak için temel olarak, arızayı tespit etme (monitoring) ve müdahale ederek istenen duruma yakınsama (convergence) mekanizmalarına sahip olmalıdır.
Sosyal ve biyolojik sistemlerin hatalara bağışık olmasının sebeplerinden biri de yedekli doğasıdır. Örneğin elimiz çizildiğinde ve birkaç hücre öldüğünde yerine geçecek bir sürü yedek hücre bulunuyor. Vücudumuzda sürekli hücreler ölüyor fakat bunların yerini diğerleri aldığı için bundan etkilenmiyoruz. Veya otobüsü kaçırdığımızda 10dk sonra bir başkası geliyor ve ona biniyoruz. Bilgisayar sistemleri de oluşan hatalardan etkilenmemek için benzer yedeklilik mekanizmalarını kullanıyor.
Bugünün buluta göre tasarlanmış sistemleri (cloud-native), Kubernetes ve OpenShift gibi modern altyapılar, sistem bağışılıklılığı ve kendi kendine iyileşme konusunda benzer yaklaşımları kullanıyorlar. Bu modern sistemlerde sunulan otomatik ölçekleme ve yedeklilik mekanizmaları da artık sıradan kanıksanmış şeyler.
Söz Verme Teorisi (Promise Theory)
Bir arkadaşınıza hediye göndermek istediğinizde bir postaneye veya kargo şirketine gidersiniz. Sizden hediyeyi bir zarfa veya kargo poşetine koymanız sonra da ağzını yapıştırarak kapatmanız istenir. Paketin üzerine gönderen ve alıcı bilgilerini girersiniz. Peşinden paketi görevliye teslim edersiniz, güven ve huzur içinde evinize dönersiniz, gerisine karışmazsınız. Paket kargo arabasıyla mı uçakla mı götürüldü, kim tarafından götürüldü sizin için hiç önemli değildir. Paketin teslimatı konusunda da kafanızda “acaba teslim edilir mi?” gibisinden hiç bir soru işareti yoktur, aracı kuruma güvenirsiniz. Kargo şirketi aldığı paketleri süresi içinde teslim edeceği konusunda söz vermiştir ve geçmiş örneklerde de sözünde durmuştur. Arada sırada yolda araçlar bozulur, yerine başka bir araç gelir ve teslimatı yapar. Bütün bu sürecin geri planı ve detayları sizin için hiç de önemli değildir. Önemsediğiniz tek şey, söz verilen süre içinde paketin teslim edilmesidir.
Sosyal hayat yukarıdaki örnekteki gibi güven ilişkisi üzerine kurulu söz verme mekanizmalarıyla çalışır.
Söz verme teorisi 2004 yılında Mark Burgess tarafından ortaya atıldı. Teori temel olarak büyük ölçekli dağıtık sistemlerin kontrolü ve yönetimi problemini daha iyi bir şekilde ele almayı hedefliyor. Merkezi bir beyinle mikro yönetim yapma yaklaşımının büyük sistemlerde yetersiz kaldığını görüyor. Bunun yerine sosyal hayattakine benzer şekilde dağıtık sistemi, otonom küçük bileşenler ve bu bileşenlerin verdiği sözler ve yaptıkları iş birliği çerçevesinde kurgulamanın daha iyi bir yol olduğunu söylüyor.
Söz verme teorisinde “verilen sözler”, arzu edilen sonucu yani “istenilen nihai durumu” temsil ediyor. Söz verme teorisi niyete yani sonuca odaklanır ve niyet karşı tarafa deklare edildiğinde verilmiş bir söze dönüşür.
Bir yemek tarifine baktığınızda en üstte yemeğin resmini yani sonucu görürsünüz. Yemek tarifi direk olarak önünüze atılmaz. Önce sonucu deklare edip ve ilginizi çekmeye çalışırlar. Sonrasında tarifin detayları ve adımları verilir.
Söz verme teorisinin temel prensipleri şöyle:
- İtme yerine çekme
- Komutların yerine verilen sözler
- Merkezi yönetim yerine otonomi ve sorumluluk
- Nihai amacı veya niyeti deklare etmeyen komut silsilesi ve adımlar yerine niyete, amaca veya sonuca odaklanmak
- Niyeti yani istenen nihai durumu, varsayımları ve sistem davranışlarını deklare ederek dokümantasyon oluşturmak, böylelikle hatadan dönmeyi kolaylaştırmak, hem de olası çatışmaları çözmek
- Yukarıdan aşağı doğru gitmek yerine aşağıdan yukarıya gitmek, yani önce parçaları ve sorumluluklarını belirlemek ve ardından parçalardan bütünü oluşturmak
Söz vermek garanti vermek değildir kesinlikle. İkisi farklıdır birbirinden. Birinin karşı konulamaz bir gücü ve sonsuz hızı olmadığı sürece garanti diye bir şey yoktur.
Söz verme teorisi farklı alanları etkilemiş olsa da, Burgess bu teorinin felsefi bir yaklaşımdan ibaret olmadığını pratikte kullanılmak üzere düşünülmüş bir mühendislik konsepti olduğunu söylüyor. Söz verme teorisi başkalarına karşı iyi olmak veya ahlaki olmakla ilgili değildir. Dağıtık sistemlerdeki belirsizliği yok etmeyi de sağlamaz, sadece illüzyon perdesini yok ederek ne tür bir karmaşanın içinde olduğumuzu net bir şekilde görmemizi sağlar.
Bir yöneticinin müşteriye projenin teslimi konusunda ekibiyle konuşmadan teslim tarihi verdiğini düşünün. Bu bir aldatmacadan, bir yalandan başka nedir? Ekipteki kişiler proje üzerinde ön çalışma yapıp bir teslim tarihi sözü vermediği durumda bu projenin yöneticinin belirttiği zamanda gerçekleme ihtimali nedir? Empoze etmek etmek bize kesinlik getirmez. İşi yapacak ekipteki kişilerin verdiği sözlere dayanmak yapabileceğimiz en iyi şeydir. Otonomi bizi kesinliğe daha fazla yaklaştırır. Fakat bu yine de bir garanti değildir.
Söz verme teorisi, verilen sözlere dayanarak ilerlemek yerine empoze etmenin istenilen sonuca ulaşmada kesinliği azalttığını söyler temel olarak.
Komut Vermek Yerine Söz Vermek
Komutlardan söz vermeye geçişteki değişime örnek olarak halka açık bir yerdeki tuvalet temizliğini ele alabiliriz.
Komut vererek:
- Yerleri X’le yıka.
- Klozetleri fırçala.
- Sabunluklara sıvı sabun doldur.
- Bu işi her saat başı yap
Söz vererek:
- Saatlik kontrollerde yerlerin temiz ve kuru olacağına söz veriyorum.
- Saatlik kontrollerde klozetlerin temiz olacağına söz veriyorum.
- Saatlik kontrollerde sabunluklarda sıvı sabunun olacağına söz veriyorum.
Söz Vermek Komut Vermekten Niçin Daha İyidir?
Televizyon karşısında uzaktan kumandayla geçirdiğimiz onlarca yıl bizi makinelerle çalışma konusunda başka bir yol olabileceğini düşünmekten alıkoydu der Burgess. Halbuki düğmeye basmak, komut veren (imperative) scriptler, uzaktan verilen komutlar çok sayıda makineden oluşan bir sistemde iyi işlemez. Komut bazlı çalışmak ölçeklenebilir değildir.
Komut bazlı çalışırken karşıdaki makinenin durumunu bilmeyiz. Bilgimiz eksiktir. Karşıdaki makinede gereksinim duyduğumuz şeyler mevcut olmayabilir. Karşıdaki makine bu komutlara uyamayabilir veya üzerindeki politikalar gereği uymak istemeyebilir.
Komut bazlı çalışmanın problemlerden biri niyetle implementasyonun ayrıştırılmasıdır. Halbuki söz verme bazlı çalışıldığında makine niyeti bilir, o an karşılık veremese de koşullar düzeldiğinde sözünü tutmak için gerekli adımları atabilir. Komutlar ise kırılgandır, en ufak farklı bir durumda tüm süreç durur ve devam etmez. Farklı çelişen komutlar çözümlenemez fakat söz verme yaklaşımında niyetlerin dokümantasyonu yapıldığından çelişmeler çözülebilir.

Söz vermeyle komut bazlı yaklaşımı karşılaştırırsak:
- Komutlar nihai sonucu veya niyeti bilmeden bir takım adımları takip etmenizi ister.
- Komutlar nihai niyetin dokümantasyonunu yapmaz.
- Komutlar bağlama, bulunulan duruma, zamana bağlıdır. Bulunulan durumdan bağımsız olarak herhangi bir anda çalıştırılamaz.
- Komutlar dışsaldır, ötekine yani tanım gereği kontrolümüzde olmayan bir şeye yöneliktir. Otonom bileşenler ve verilen sözlerse kendi içine, kendi kontrolünde olana yöneliktir.
- Söz verme bir devamlılığı ve sabit bir durumu temsil eder, komutlar böyle değildir.
- Komutlar bir durumdan uzaklaşmayı, söz vermeyse bir duruma yaklaşmayı ifade eder.

Ortaya Çıkış Hikayesi
2000'lerin başında Amerika’da sistem bilimine katkılarından dolayı bir başarı ödülü aldı Burgess. Fakat bu alana çok da hakim olmadığını düşündüğünden biraz kendini suçlu hissetti. Geri dönüp daha derinlemesine araştırma yapmak ve daha iyi anlamak istedi.
Yine fizikçi olan bir arkadaşıyla birlikte çeşitli konularda graf teorisi üzerinde çalışırken bir aydınlanma yaşadı. Ağların nasıl tanımlanabileceğini ve işbirliğinin sonuçlarını anlamada ağın farklı parçalarının nasıl farklı roller üstlenebileceğini anladı. Buradaki anahtar nokta etkinin ağ üzerinden yayılmasıydı. Bunu yönetim sistemlerine uyarlamak istiyordu fakat mekaniğini tam kavrayamamıştı.
Önce işbirliği konusuyla ilgili ne varsa okudu araştırdı. Konuyla ilgili bir sürü çalışmanın yapılmış olacağını düşünmüştü başlangıçta fakat yanıldı. Araştırmaları sonucunda eksik olan şeyin niyet veya amaç olduğunu keşfetti. İhtiyaç duyduğu şeyi bulmuştu. Graf teorisi ve niyetlerin grafiği temelinde söz verme teorisini ortaya koydu. Söz verme teorisinin ismini belirlerken de yönetim alanındaki diğer kavramlara ve onların beraberinde taşıdıkları bagajlara hapsolmaktan kaçınmak istedi.
Söz verme teorisini geliştirdikten belli bir süre sonra da bunu pratiğe dökmek istedi ve üçüncü nesil CFEngine’i söz verme teorisini kullanarak tekrar yazdı.
Kubernetes’teki Yansımalar
Söz verme teorisi ve gerisindeki bazı prensipler Kubernetes’in tasarımında kullanılmıştır. Kubernetes temelde bizden nihai durumu ve varsayımlarını deklare eden bir doküman alır ve bunu sağlamaya söz verir.
Örneğin bir pod için 100GB disk talep ettiysek ve elde bu kapasite yoksa Kubernetes bir olay kaydı oluşturarak bunu bize haber verir. Disk kapasitesini artırdığımız andan itibaren sözünü tutar, “istenen nihai duruma” yakınsamasını yapar ve bizim müdahale etmemize gerek kalmadan podu ayağa kaldırır.
Veya bir pod için dokümana yazdığımız minimum CPU ve bellek kaynağı sağlanamıyorsa, Kubernetes durumu açıklayan bir olay kaydıyla bize haber verir. Sunucu kümesine yeterli kaynağa sahip bir sunucu eklendiğinde veya başka bir sunucuda yeterli kaynak mevcut hale geldiğindeyse bize sormadan sözünü tutar, “istenen nihai duruma” yakınsamasını yapar ve podu ayağa kaldırır.
Kubernetes podları izler ve sağlık durumunu (health) ve hazır olma durumunu (readiness) çeşitli yöntemlerle tespit etme mekanizması sunar. Uygulama sağlığının düzelmesinden umudunu keserse onu siler yerine yeni bir uygulama kopyasını ayağa kaldırır. Uygulama kopyası (pod) hazır değilse iletilen trafiği keser, hazır olunca tekrar trafiği yönlendirir. Böylelikle yine sözünü tutar ve “istenen nihai duruma” yakınsamasını yapar.
Bir Kubernetes hata mesajı:

Google’da Kubernetes projesinin sesi olan Kelsey Hightower’ın buna yanıtı:

Bitirirken
Bir şeyleri öğrenmek üzere yola çıkıp araştırmalar yaparken serüvenin sizi nereye sürükleyeceğini her zaman öngöremezsiniz. Bir yere ulaşma amacıyla yola çıkmışken kendinizi bambaşka bir yerde bulabilirsiniz. Yolda keşfettiğiniz bir şey size çok ilginç gelir ve cazibesiyle sizi kendine çeker. Bu da bir bakıma böyle bir şeydi.
Kaynakça
- Söz verme teorisi hikayesi: https://www.youtube.com/watch?v=sA76lddxkMA
- İlk CFEngine makalesi: https://www.researchgate.net/publication/243774232_Cfengine_A_site_configuration_engine
- Bilgisayar bağışıklılığı makalesi: https://people.scs.carleton.ca/~soma/biosec/readings/burgess-immunology.pdf
- Söz verme teorisi Google TechTalks konuşması: https://www.youtube.com/watch?v=4CCXs4Om5pY&list=PL6wAWDeKgxZdtCLlj2GeTmwLlMsRI26c4&index=5
- Söz verme teorisiyle ilgili YouTube kanalı: https://www.youtube.com/channel/UCxoHs7KK2GCYcEZK6ttigaA/videos
- Konfigürasyon araçları tarihçesi: http://verticalsysadmin.com/blog/relative-origins-of-cfengine-chef-and-puppet/
- Bir makale: https://www.linuxjournal.com/content/promise-theory%E2%80%94what-it
- Thinking in Promise kitabı: https://www.amazon.com/Thinking-Promises-Designing-Systems-Cooperation/dp/1491917873
- Kubernetes Belgeseli 1. bölüm: https://www.youtube.com/watch?v=sVP8xb9BrhM
- Kubernetes Belgeseli 2. bölüm: https://www.youtube.com/watch?v=318elIq37PE