Bir Azure Projesi
Artistanbul’da çalışmaya başladıktan bir süre sonra bir müşterimiz için uygulama verisini Almanya içinde tutma ve Almanya’da iki ayrı şehirdeki veri merkezleri arasında geçiş yapabilme zorunluluğu ortaya çıktı. Araştırmalarımız sonucunda bu şartları sağlayan tek bulut sağlayıcısının Microsoft Azure olduğunu gördük ve Azure ile ilişkimiz başladı.
Azure Almanya, küresel Azure’dan tamamen izole bir platform olduğundan, genel kullanıma açık çoğu servis ya çok geç geliyor ya da hiç gelmiyordu. PostgreSQL veritabanı servisinin gelmesi dahi yılları buldu. Bu platform üzerinde sadece Redis, Application Gateway ve Blob Storage servislerini kullanabildik. Hem platformun kısıtlarından hem de eski bir platformun göçünü gerçekleştirmiş olmamızdan dolayı Azure kullanımımız bir “on-premise” veri merkezi kullanımından farksızdı. “Cloud native” bir proje için biraz daha beklememiz gerekecekti.
Azure Almanya göçünden neredeyse bir sene sonra, bir süredir yazılım dışı işlerde projeler yürüttüğümüz bir müşterimiz yeni bir fikirle çıkageldi. Eğitim odaklı bir AR-GE projesi kapsamında bizden yazılım hizmeti almak istiyorlardı. Bu proje benim için bulutun ve Azure’un anahtarı oldu.
Genel hatlarıyla projenin teknik altyapısı
Proje kapsamında önümüzde iki temel teknik mücadele vardı:
- Kapalı kutu bir cihazla etkileşime geçecek bir yazılım ekosistemi oluşturmak
- Kullanıcının tarayıcı aracılığıyla üç boyutlu modellerle etkileşime geçebilmesini sağlayacak bir platform oluşturmak
Bu iki mücadele için ben ve ekip arkadaşlarım 10 ayrı uygulama yazdık:
* Tamamen React ve ThreeJS ile yazılmış frontend uygulaması (Kullanıcının sistemle esas etkileşeme geçtiği kısım olması dolayısıyla, en kritiği)
* API belkemiği olarak iki tane büyükçe Django uygulaması
* CMS hizmeti için bir React frontend ve bir Django backend uygulaması
* Beş tane küçük boyutlu Flask uygulaması
Bütün uygulamalar ilk andan itibaren konteynerler içerisinde hayatlarını sürdürdü ve neredeyse projenin başından itibaren GitLab CI bütün imaj oluşturma yükümüzü üstlendi. Yine projenin başından itibaren tüm test ve “staging” ortamlarımız Azure üzerinde koştu ve birkaç istisna dışında bulut servislerini kullanmaktan çekinmedik. Hatta denebilir ki, yazdığımız kodun çoğu kullandığımız bulut servislerinin etrafında şekillendi. Tabii bu kararımızla kendimizi Azure’a sıkı sıkıya bağlamış olduk ancak bu sayede bulut servislerinden tamamen yararlanabildik. Aksi takdirde bulut agnostik olmak için yaratacağımız operasyonel maliyet, ilerde bir gün (yüksek olasılıkla da hiç olmayacak) göç için harcayacağımız emekten çok daha fazla olacaktı.
Azure ortamında kullandığımız servislerin ilki, App Service
Bütün uygulamalarımız bir App Service planında konteynerler içerisinde koşuyor. Geliştirme aşamasında kullanmadığımız iki Azure servisinden biri buydu. Projenin başında maliyete dair bir kaygı bulunduğundan bu servisi geç aşamada kullanmaya karar verdik. Zaten her halükarda konteyner teknolojisine sırtımızı dayadığımızdan uygulamaların çalışacağı ortam ne olursa olsun davranışları aynı olacaktı. Proje yayına çıktığı andan itibaren de uygulamalar App Service’e geçti ve herhangi bir şekilde bizi üzmediler (sağolsunlar). App Service operasyonel eforu miminum seviyede tutarak ölçeklenebilir ve stabil bir platform sunduğundan gayet hoşuma gitti. İçinde hazır olarak gelen “Continous Delivery” ve “Deployment Slot” özelliklerini de çok beğendim. Henüz “Deployment Slot” kullanmasak da “Continous Delivery” özellikle test ortamlarımız için çok işimize yarıyor.
Elbette her şey güllük gülistanlık değil. App Service’e dair beni üzen iki nokta oldu:
- 1. API servislerimiz Django uygulamaları olduğundan özellikle veritabanı şema değişikliklerinde `manage.py` komutlarını çalıştırmaya ihtiyaç duyuyoruz. App Service ne yazık ki bir konteynere `exec` komutu ile müdahale etmeye izin vermiyor ve sizi konteyner içinde uygulamanızla birlikte bir de SSH sunucusu çalıştırmaya zorluyor. Bu bana hem konteyner mantığına aykırı (1 konteyner = 1 işlem) hem de istisnai bir operasyonel işlem için aşırıya kaçan bir yöntem gibi geliyor.
- Konteyner imajlarımız GitLab CI ile oluşturuluyor ve tetik mekanizmalarına göre hangi ortamı hedeflediği belirlenip ona göre yapılandırılıyordu. Master’a giren her kod test ortamları için bir imaj oluştururken, kodun belirli formatlarda etiketlenmesi “staging” veya yayın ortamının hedefleneceğini belirtiyordu. Projenin yayına çıkmasından önceki hafta proje sahipleri ile birlikte son bir hata çözüm seansı için bir araya geldik. Bir yandan uygulama test edilirken bir yandan da bulunan hataları çözüyorduk ve hızlı geri bildirim alabilmek için sık sık yayın ortamını güncelliyorduk. CI yapılandırma dosyamızı değiştirmektense süreci Gitlab CI arayüzünden elle tetikleyip yayın ortamını hedefleyecek imajlar oluşturuyor ve App Service’in bize sunduğu URL’e istek yaparak yeni imajı kullanmaya başlamasını sağlıyorduk. Dolayısıyla bende, eğer bu URL’e istek yapılmazsa imaj etiketi güncellense dahi çalışan uygulamanın güncellenmeyeceği algısı oluştu. Günün sonunda küçük bir toplantı yapma ve üçüncü parti gruplara uygulamanın bir demosunu yapma isteğiyle karşılaştık. “Sorun değil” diye düşündüm, “zaten uygulama gayet sağlıklı şu anda.” Meğer 10 dakika önce son bir “merge request” master’a girmiş ve test ortamını hedefleyen yeni bir imaj oluşturulmuş. App Service de kimse rica etmediği halde yeni imajı çekip uygulamayı güncellemeyi kendine vazifebilmiş. Nihayetinde demoyu kendi bilgisayarımdan yapmak zorunda kaldım ve neden yayın ortamında değişmez (immutable) imaj etiketleri kullanmamız gerektiğini öğrenmiş oldum.
Batch Service
Proje içerisinde 30-40 saniye süre ile yüksek CPU gereksinimi olan ve kullanıcı talebi üzerine başlayan bir dizi işlemi karşılama gereksinimimiz bulunuyor. Bu işlemlerin de Bash ile çalışması gerekiyor. Bu isteri Batch Service ile karşılamaya karar verdik. Batch bize bir işin altındaki her görevi tamamlamak için gereken her şeyi programatik olarak tanımlayabileceğimiz ve görevlerin sonuçlarını Blob Storage’a aktarabileceğimiz bir API ve bu işleri çalıştırabilmek için bir makine havuzu sunuyor. Maliyeti minimumda tutmak için makinelerin üçte ikisini düşük öncelikli olarak oluşturduk. Düşük öncelikli makineler her bulut sağlayıcının farklı isimlerle de olsa sunduğu ve o an ihtiyaç fazlası olan düşük fiyatlı sanal makineleri anlatmak için kullanılıyor. Bu makineleri kullanırken her an kapatılabileceğini ve belirli bir süre yerine yenisinin sağlanamayabileceğini göz önünde bulundurmak gerekiyor. Biz bunun için makine yapılandırmasını Packer kullanarak oluşturduğumuz imaj ile sağladık. Böylece makine kapanıp açılsa da açıldığı anda çalışabilir olduğunu garanti edebiliyoruz.
Events Hub
Yukarıda bahsettiğim kapalı kutu cihaz, dakikada birkaç kere servislerimize durum bilgisi paylaşıyor. Bu verilerin neredeyse anlık olarak işlenmesi, kullanıcılara iletilmesi, gerekiyorsa bildirim gönderilmesi ve belirli aralıklarla analiz edilip raporlanması gerekiyor. Bunun için IoT Hub ile Event Hubs arasında seçim yapmamız gerekti ve bu servis üzerinden cihazla etkileşim kurmamız gerekmediğinden Event Hubs servisini seçtik.
Blob Storage
Proje genelinde üç boyutlu modellerin tarayıcıya eklenmesi, bunlar üzerinde yapılan değişikliklerin kaydedilmesi ve bu modellerin Batch Service üzerinde bir dizi işleme tabi tutulması için bu dosyaların hepsini Blob Storage üzerinde tuttuk ve kullanılacak yere göre SAS ile imzalanmış URL’leri yoğun bir şekilde kullandık.
Redis & PostgreSQL
Bu servislerin tanıtılmaya ihtiyacı yok. Cache ihtiyaçlarımız için Redis, bütün uygulamalarımızın veritabanı olarak da PostgreSQL servisini kullandık.
Traffic Manager & Application Gateway
Uygulamalarımızın son kullanıcıya açılması için Traffic Manager ve Application Gateway kullandık. Application Gateway bize kural bazlı yönlendirme, yük dağıtma, SSL sonlandırma ve WAF koruması sağladığından tepe tepe kullandığımız bir servis oldu.
Terraform
Bir Azure servisi değil belki ama Terraform olmasaydı yukarıdaki servisleri kullanmak bir eziyet olacağından burada listelemeyi uygun buluyorum. Projenin başından itibaren “Infrastructure as a Code” yaklaşımını benimsedik ve bütün bulut yapılandırmasını Terraform ile yönettik. Bu özellikle Application Gateway gibi sık değişiklik gerektiren ve karmaşık bağımlılıklara sahip olan servisleri yönetmemiz için bize çok kolaylık sağladı.
Projenin gerçek lansmanı henüz gerçekleşmediğinden hep örtülü şekilde bahsetmek durumunda kaldım ama son bir aydır Türkiye genelinde 150’den fazla noktada kullanılmaya başlandı ve Artistanbul ekibi olarak gurur duyduğumuz bir proje oldu.