Nasıl “Kubernetes Operator” Geliştirebilirim?

Selçuk Usta
Nov 28 · 3 min read

Bu yazı tam olarak “Writing Your First Kubernetes Operator” tadında bir yazı olmayacak, “What is Kubernetes Operator” konulu olacağını söylemek de yanlış olacaktır. Ne olduğunu söylemiyorsun, nasıl yazılacağını da anlatmıyorsun. O halde neden devam edeyim? dediğinizi duyar gibiyim. Onu da aşağıdaki girizgah ile özetleyeceğim ki çok vaktinizi almayayım.

Fotoğraf, Dan Lohmar tarafından çekilmiş ve Unsplash üzerinde yayınlanmıştır.

Hikayenin Başlangıç Noktası

Haftasonu, sevgili Gökhan Şengün’ün “Kubernetes Native Uygulama Geliştirme” konulu bir etkinliği vardı. Etkinliğin bir noktasında, iş süreçlerine özel bazı ihtiyaçlar konusunda Kubernetes’in native objelerinin tam olarak cevap veremediğinden dem vuruldu. Bunun üzerine ise ortaya “Kubernetes Operator” başlığı çıktı.

İş süreçlerine özel bazı ihtiyaçlar tam olarak neyi ifade eder?

In-memory bir storage uygulaması geliştirdiğimizi düşünelim. Uygulamanızın temel mimarisinde bir master ve {N} replika yer alıyor. Master uygulama yazma emirlerini işleyip replikalara dağıtırken, okuma işlerini ise direkt olarak uygun replikaya yönlendiriyor. Bir de failover senaryonuz var ve bunun için de bir consensus algoritması kullandınız/geliştirdiniz. Ayrıca konfigürasyona bağlı olarak da in-memory verileri kalıcı olarak yazabiliyorsunuz.

Bu durumda iş sürecinizde PersistentVolumeClaim, Deployment, Service, ConfigMap, StatefulSets gibi bir çok Kubernetes objesini sıralı ya da eşzamanlı olarak bir iş akışı doğrultusunda oluşturmalı; kaynağın imhası durumunda ise yine iş akışı takip edilerek geride iz bırakmadan objeler ortadan kaldırılmalıdır.

Bu gibi durumlar için 1.16.0 versiyonu itibariyle Custom Resources Definitions (CRDs) adı verilen API, Kubernetes dünyasındaki yerini aldı. Operator ise tam bu noktada, tanımlı özel objelerin durumlarını takip eden, gerekli operasyonları yöneten controller objesi olarak karşımıza çıkıyor.

Peki, böylesi kapsamlı iş süreçlerimiz yoksa?

Hikayenin başlangıç noktasına geri dönüyorum ve öğretiyi kendi hikayemle bir noktada kesiştirebiliyorum. Takribi 1 ay kadar önce şöyle bir serzenişte bulunmuştum:

Bu da aslına bakarsanız bir iş süreci. Domain özelinde olmasa dahi tercih edilen teknoloji özelinde yaşanan bir sorun.

Bu iş sürecinin hedeflenen şekilde çözümlenebilmesi için ConfigMap üzerinde bir değişiklik olduğu takdirde, ConfigMap’in mount edildiği Deployment objesi tespit edilmeli ve RollingUpdate yordamı ile — değişiklik esnasında bir kesinti yaşanmamalı — güncellenmelidir.

Etkinlikte bahsedilen API ile bu sorunun üstesinden gelinebileceğini düşündüm ve kolları sıvadım.

⚠️Yazının bu noktasından sonraki kod blokları ve en altta verilen repository’i deneysel bir çalışma olarak kabul edebilirsiniz. Gördüğünüz hatalar ve öneriler için PR iletmeniz veya özelden iletişime geçmeniz benim için oldukça önemli.

Ben bu iş için Operator Framework’ü tercih ettim — internetteki bir çok kaynak da buraya refere ediyor — . Operator geliştirmek için gerekli tüm ön gereksinimleri adresinden öğrenebilirsiniz. Yazıyı çok detaya boğmamak adına burayı atlıyorum.

İş sürecimi kontrol eden CustomResourceDefinition tanımım şu şekilde olmalı diye düşündüm:

Operator tarafından oluşturulacak ConfigMap tanımına ait gereksinimler ve bu konfigürasyonu kullanan bağımlı Deployment obje isimleri.

Buna karşılık gelen isimli nesnemi oluşturuyorum ki ( ) Controller içerisinden yukarıdaki tanımlanan değerlere ulaşabileyim:

dosyası iş sürecinin yönetildiği nokta. Bu dosya içerisinde ConfigMap objesi üzerindeki değişiklikleri takip edeceğimi ifade ettiğim bir blok mevcut:

Bu sayede fonksiyonu, oluşturduğum özel objede bir değişiklik olduğunda tetikleneceği gibi, bu obje ile oluşturulmuş ve tarafından sahiplenilmiş ConfigMap objesi için de tetikte olacak.

fonksiyonu, bir controller’ın en kritik nesnesi olarak tabir edilebilir. Dokümantasyonda da belirtildiği gibi; NetCoreConfigManagement objesinin state’ini okuyup takip eden ve değişiklik olduğu takdirde bu değişikliğin uygulanmasını sağlayan fonksiyondur.

Bu fonksiyon içerisinde, aşağıdaki iş sürecinin tetiklenmesini sağlıyoruz:

Kısaca özetlemek gerekirse, state değişmeden önceki konfigürasyonu ve yeni state’teki konfigürasyonu karşılaştırıyor; bir değişiklik varsa öncelikle NetCoreConfigManagement objesi tarafından oluşturulmuş ConfigMap objesini yeni hali ile güncelliyor, sonrasında ise bağlı tüm Deployment objelerini yeniden başlatıyoruz.

Sonuç

⚠️Medium’un embed spesifikasyonundan ötürü video oldukça kalitesiz görünüyor. Orijinal linke buradan ulaşabilirsiniz.

Tam da iş sürecimizin emrettiği şekilde bir davranış sergileniyor. ile başlayan pod’un loglarına baktığımızda da kod içerisinde belirttiğimiz logları ve controller’in kendi loglarını gözlemleyebiliyoruz.

Yukarıda ufak ufak alıntılar yaptığım örnek uygulamaya şuradan ulaşabilirsiniz 👇

Yazıyı tamamlamadan hemen önce “Awesome Operators” isimli repository’i de incelemenizi öneririm. İrili ufaklı onlarca CRDs örneği mevcut.

Bir sonraki yazıya dek, iş süreçlerinizde ile arasında hiç fark olmaması dileğiyle.

Selçuk Usta

Written by

Software Development Manager (at) Rasyotek. Former trainer & consultant. Family member of C# and Python. Newbie on Unix. Articles are mostly about coding.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade