Devops yaptık da n’oldu?

Orhun Begendi
hesapkurdu-development
8 min readMay 7, 2018

Son dönemlerde herkesin dilinden düşüremediği bir konu var, Devops! Herkes kıyısından köşesinden bir şekilde bu tip adımlar ya atıyor ya da atmaya çalışıyor. Biz de kendi seviyemizde bir şeyler yaptık sonunda dönüp baktık n’oldu diye. Dönüp baktığımızda gördüğümüz şeyleri paylaşmak istedim.

En önemli bilinmesi gereken şeylerden biri bana göre Continuous Delivery/Integration devops değil, bunu ben de zamanla daha iyi kavradım diyebilirim. CI/CD yapıları devops’un sadece parçaları. Evet, çok önemliler ama sadece onları kurunca biz çok iyi devops yaptık diyemeyiz. Zaten bir süre sonra siz de bunun tek olay olmadığını anlayacaksınız, acı olacak emin olun; ama anlayacaksınız 🙂

Size herkesin anlattığı gibi çok hızlı, temiz deployment’lar vs. diye anlatmak istemiyorum. Gerçekte olan şey bu değil! İlk olarak devops nedir bunu anlamak lazım. Devops bir kültürdür ve tamamen şirketin buna kayması ve ayak uydurması gerekiyor. Bu olduktan sonra hepsi arkasından geliyor yoksa bir adım bile ilerleyemiyorsunuz. Elle deployment çıkmaktan kendi kendine canlıya çıkan commit’ler seviyesine gelinmesi o kadar zor değil ama şirkete göre zorluk gösterebilir. Zorluğun çıkmasının tek sebebi şirketin buna ayak uydurmamasıdır bundan emin olabilirsiniz. Biz birkaç ayda herşeyi otomatiğe aldık. Diyeceksiniz ki:

İyi de bunu nasıl yaptınız?

Burada işimizi en çok kolaylaştıran, belki de en önemli konu yönetimin devops’un değerini biliyor ve en az bizim kadar benimsiyor olmasıydı. Eğer sizin firmanındaki yönetim kadrosu devops’un önemini yeterli şekilde anlamıyorsa önce bu sorunu çözmeniz gerekli. Bu yazıda hem developer’ların hem de yöneticilerin anlayabileceği, verimliliği temelden geliştiren konulara örnekler vermeye özen göstereceğim.

Ayrıca çoğu blogda gördüğüm bir durum var. Herkes sanki çok basitmiş gibi birşeyleri anlatıp biz yaptık çok güzel oldu diyor. Bu ölçüde bir geçiş kesinlikle çok basit veya kolay olmuyor. Hatalar oluyor, geri alınan adımlar oluyor. Yönetim ve teknik ekip olarak hataları sürekli olarak çözmeye ve verimliliği arttırmaya odaklanmış olmak gerekiyor.

Ben size sorunlarımızdan, hatalarımızdan, onları nasıl çözdüğümüzden, ve süreç dahilinde kullandığımız yapılardan bahsetmek istiyorum.

Devops eforlarından önce

İlk olarak size eski yapımızdan bahsedeyim. Aktif olarak kanban şeklinde çalışan, .Net teknolojileri kullanan ve provider olarak Amazon’u seçmiş bir firma vardı. Evet, sadece bu kadar. Deploymentlar en tecrübeli developer tarafından hergün evet hergün deployment yapılan bir yapı vardı. En iyi developer tüm gün deployment ile uğraşıyordu. Peki kod kalitesi? kaliteyi ölçecek bir yapı bile mevcut değildi! Test yoktu, daily standup yoktu, deployment’lar AWS üzerindeki EBS’lere Visual Studio’daki bir extension ile çıkılıyor ve dualar ediliyordu. Logging için elmah, monitoring içinde bir miktar New Relic kullanılıyordu. Eğer publish sonrası belli bir süre hata gelmezse iyi bir publish sayılıyordu ve yola devam ediliyordu.

Bu kadar koşuşturmaca arasında tabiki testler aksıyor, bozulan şeyler artıyor ve en önemlisi asıl iş gücü deployment ve canlıda ki problemlere çözemeye gidiyordu. Sisteme yeni feature eklemek günlük bir iş değildi. Tüm developerların günlük işi live bug’lardı denebilir.

Bunu görünce toplantılar yaptık, herkesin dünden razı olduğu ama nasıl yaparız dediği bir konuya balıklama atladık, DEVOPS! Görünen o ki kolay olmayacaktı. Ne yapacaktık, nerden başlayacaktık, ilk neyi yapmalıydık? Bu sorular çığ gibi büyürken benimsediğimiz tek bir kural oldu, hayat kurtaran altın kural, çözüm hiç bir zaman CI veya CD olmayacaktı, biz de Continuous Improvement yolunu seçtik. Olay çok basit, o an canımızı en çok sıkan sorun ne ise ona çözüm bulduk ve devops kültürü kendiliğinden yayıldı. Çünkü sorunlar çözüm buluyordu!

Kendimize tanı koymamız gerekiyordu ve analizden geçmemiz gerekiyordu. Kodumuzu Sonarqube ile analiz ettik. Sonuçlar korkunç derecede kötüydü. Bunları düzeltmeli miydik yoksa farklı şekillerde mi çözmeliydik? Bunu düşünürken başka sorunlarımız baş gösterdi.

Öncelikle ufak bir bilgi vermem gerekli. Hesapkurdu.com’da 2 temel yapı taşı var, ön yüzü taşıyan Mvc yapısı ve buradaki dataları ve backend’deki tüm ağırlığı taşıyan WebApi. Bunların ikiside aynı database’e bakıyordu. Buradaki DAL katmanında model uyumsuzluk sorunları baş gösteriyordu. 2 proje de ayrı solution’lar olduğu için bizde buradaki DAL katmanını ortaklaştırarak ilk pipeline’ımızı kurduk. DAL katmanını tüm model’leri, dto’ları vb. yapıları bir model projesinde toplayıp bunu Nuget pakedine dönüştürdük. Kendi nuget repository’mizin kodunu yazdık ve paketlerimiz buraya attık. Tüm solution ve projelerden bunları kullandık ve tadaaa ilk sorunlar baş göstermeye başladı bile. Aynı modeli kullanan ama farklı FK’lar ile birbirine bağlanmış amatörce yazılmış yüzlerce satırlık kodlar başımızı çok ağrıttı. Buradan dersimizi aldık, 3–4 gün süren bir kaostan sonra ne yapmamız gerektiğini kesinlikle anladık. İlk başta dur sonra bakarız dediğimiz analizler! Bunları temizleyelim desek ömrümüz yetmez gibi duruyordu.

Şöyleki ilk zamanlardan sadece tek bir projemizin analiz datasını paylaşayım.

Bugs : 868

Vulnerabilities : 137

Code Smell : 42000

Debt : 1400 gün

Gerçekten üzücü bir tablo. Bunun gibi 3 tane daha ana solution vardı. Onların durumu bundan daha kötü olanları da vardı. Bu böyle çözülmeyecekti çok daha sağlam çözümler gerekliydi. Tek tek bunlar çözülür mü? Delilik!

Pull-Requests ve check-in yetkileri

Biz de git yapımızı ve güzel bir şekilde oturttuğumuz feature-branch yapımızı daha da güçlendirecek bir karar aldık. Bu da Master ve Development branch’lerine yazma yetkilerini sınırlandırmak. Evet çok eğlenceli oldu denebilir. Hatalı mergeler, rollback’ler ve daha nicesi kayboldu gitti. İyi de diğer branch’leri nasıl merge yapıyoruz? Tabi ki Pull Request yapısı ile. 2 kişinin onayı olmadan pull requestler onaylanmıyor ve mergelenmiyor eğer yapılırsa arkadaşlar gerekli ikazı alıyordu :) Bu şekilde kalitenin düşmemesini yavaş da olsa artmasını sağladık.

Pull request yapısı ile bazı kurallar koyduk. Mesela en önemlisi pull request’te daha önceden belirlediğimiz kod standard’larına uyup uymadığı inceleniyor ve review eden developlar tek sorumlusu oluyor. Bu yüzden herkes çok dikkat etmeye başladı. Hiç aklımıza gelmeyen güzel bir şey de oldu, herkesin yabancı olduğu code base’i herkes daha iyi tanır hale geldi. Çözülen bug sayımız o kadar hızlı arttı ki biz bile şaşırdık doğrusu.

Aslında burada da ciddi hatalar yaptık. Bunları da başımıza geldikçe çözdük ki en önemlisi buydu. Abi bir pull request’im var bakabilir misin gibi durumlar çok oluşuyordu ya da daha önce bahsettiğim dal katmanı ve ortak kullanılan yapılar için oluşan nugetleri projelerin ana branch’lerinde güncellemek gerekiyordu. Çok fazla conflict ve vakit kayıpları oluşuyordu. Hepsini tamamen çözemesek bile %90'ını çözdük denebilir. Canlı için dal katmanı ya da common içerisinde yeni bir paket çıkarsa tüm projelerde update eden bir pipeline daha ihtiyacımız oldu.

İş gücümüzü geri kazanmaya başlamıştık ama hala o noktada değildik. Yeni arayışlara girdik ve hergün yapılan deployment’ları haftanın belirli 2 gününe çekmiştik. Canlıdaki sorun yaşama oranını %90 oranında azaltmıştık her publish olmasa bile arada sorun çıkıyor ve bu sorunalr gerçekten ya çok büyük ya da anında farkedilmeyen yani silent exception’lar oluyordu. Ayrıca kod yapımız çok karmaşık ve bunu düzeltmek için aksiyon alamıyorduk. Çünkü bir şeyi bozarsam tehdidi çok yüksek ve sitenin aktif olması en önemli önceliğimiz.

Test, test, test

Bunu aşmanın tek yolunun test olduğunu sonunda takım olarak anlamıştık. Ufak tefek başlayan testler hız kazandı. Bazı yapıları tamamen silip testi yazılmış haliyle yazmaya başladık. Sadece %30 coverage oranında bile yakaladığımzı hataların inanılmaz yüksek olduğunu gördük. Bunun üzerine o kadar çok yoğunlaştık ki işimiz gücümüz test edilebilir bir yapı kurmak oldu diyebilirim. Smoke testler, integration testleri vs vs vs…

Testler yazdıkça yazdık ve mimari olarak sıkıntılarımız daha çok gördük. Yanlış DI seçimleri, hatalı helper’lar, hataya açık kodlar ve daha nicesi… Test yazdıkça kodu düzelttik, düzelttikçe test yazdık. Kod kalitemiz arttıkça arttı kalite sabit kalmıyor gittikçe “A” quality’ye yaklaşıyorduk. Hatta “A” quality olduğumuz zaman küçük bir kutlama bile yaptık :)

Pipeline’lar

Artık bunca şey yaptıktan sonra şu publish, upload vb. amelelikleri kaldırmamızın vakti gelmişti. Burada AWS kullanmamızın çok faydasını gördük. EBS yapısı publish çıkabilmemizi o kadar rahatlattı ki kullanan bilir 🙂 AWS’de ayağa kaldırdığımız pre-prod ortamlarına otomatik deployment yapan pipeline’lar kurmaya başladık. Toplamda 8 farklı sunucuya bir kısmı AWS’de bir kısmı farklı provider’larda çalışan ortamlarımıza deployment pipeline’ları kurduk. Bunları gün içerisinde yapmak sitede sıkıntı oluşturabileceğinden gece saatlerine kurduk.

Release yöneticileri

Bunların yanı sıra publish’lerden sorumlu bir arkadaş atadık. Bu kişi her hafta başkası oluyor. Tek yaptığı iş pipeline’lar çalıştı mı? Her şey ok ise publish ile ilgili mail’leri atıp işine geri dönüyor. Bu sayede herkes pipeline’lar hakkında bilgi sahibi oldu. Burada gözden kaçırdığımız en önemli nokta ise pipeline’lar ve arkadaki sistemin eğitimini vermeden veya anlatmadan bu işe kalkışmayın! Biz yaptık olmadı ve başta olması gereken eğitimi sonradan yaptık. O zamana kadar o kadar fazla bu sorulara cevap verdim ki gün içerisinde ne yaptığımı unutmaya başladım doğrusu.

Sürekli duyduğumuz abi pre-prod hazır mı, testler ok mu, şimdi test edebilir miyiz? Söylemleri sıfırlandı. O kadar fazla adam gücünü geri aldık ki sanki şirket çalışanlarını %30 arttırmış gibiydik. Her sabah herkes masasına oturduğunda artık biliyorduk ki dün merge yapılan tüm kodlar pre-prod ve test ortamlarında aktif durumda ve testi bekliyordu.

Tabi AWS blue/green deployment desteği olmaması bizim sıkıntımız oldu. Deployda sistemin kısa süreli gitmesi sorunlarıyla karşı karşıya kaldık. Hemde her zamankinden çok! Bunu çözmek için uğraşıyoruz çalışmamız bitince bir blog ile paylaşıyor olacağım.

Tabi bunları yaparken de hatalar oldu. En önemli noktayı atlamıştık. Publish pre-prod’daydı ama kimin haberi vardı? Bir sorundan dolayı çıkmazsa kim bilecekti? ve kurtarıcımız Slack kanalları geldi. Bunla da yetinmedik her publish sonrası oluşan unique id ile herkese mail’ler geçiyordu. Herkes biliyordu ki artık pre-prod’dayız.

Canlıya almak mı? Çocuk oyuncağı, AWS konsoldan tek bir butona basarak artık canlıdaydık. Açıkcası bu kısmı otomatize etmek henüz yemedi diyebilirim 🙂 Mutlaka bir insan gözü görmeliydi. Ama biz küçük bir firmayız çok iş gücü demekti ve verimi arttırmamız gerekiyordu. Burada aklımıza selenium testleri ve specflow bize umut oldu. Şuan bunun hakkında çok bir şey diyemiyorum. Henüz analiz aşamasındayız. Bunu yapınca çok uzun detaylı bir blog yazacağım meraklısı takipte kalsın.

Bu işin herkesin çok dikkat ettiği ama işin %40lık kısmı olan otomasyon kısmıydı. Devops bu değil!

Biz bunları yaparken başka neler yaptık?

JIRA + Bitbucket + Kanban

Kanban sistemimizi geliştirdik. Haftalık toplantılardan günlük (daily standup) toplantı yapısına geçtik. Aktif olarak herkes herkesin ne yaptığını bilmeye başladı.

Bu da yetmedi gittik Jira aldık. Jira’da git provider’ı olarak seçtiğimiz Bitbucket’ı entegre ettik. Bitbucket’ta açtığımız her branch yapılan her commit Jira’daki üzerinde çalışılan issue’ya bağlanıyordu. Eğer orada merged ibaresi çıkıyor ise merged tarihini takip eden ilk sabah artık bu feature pre-prod’da demekti. Bu artık yeni normalimizdi. En önemlisi de buydu. Herkes ayak uydurdu. Jira eğitimleri verdik, publish günlerini belirledik. Publish için son saat belirlendi. Eğer saate uyulmuyorsa bir sonraki publish beklemek artık normal oldu. Buna herkes tamam dedikten sonrası çok kolay oldu.

En son ne mi oldu? Aşağıdaki gibi bir analiz sonucu ortaya çıkabildi. Buraya nereden geldik? 8800 gün+ technical debt’den 270gün’e kadar azalttık. 20 yılda değil 20 haftada :)

Sonarqube analiznden küçük bir kare :)

Günün sonunda nereye geldik onu anlatayım. Dev ekibi artık sadece geliştirme yapıyor. Ürün ekipleri her sabah test ortamlarında testlerini yapıyor tamam derse issue’yu code review’a yolluyor ve ilgili arkadaşlar code review yapıyor herşey tamamsa merge yapılıyor. Testler çalışıyor her şey tamamsa bir sonraki publish günü yayındayız! Değilse hatalar bulunuyor ve pipeline bizi uyarıyor bu uyarılar sonucunda hedef kimse testleri o düzeltiyor. Kimsenin işi bozulmuyor kimse sıkıntı çekmiyor. Daha fazla odak daha fazla iş olarak ilerliyoruz.

Biraz da metriklerinden bahsedeyim;

Ayda 8 adam/gün dev kazancı.

Neredeyse 1 saatlik bir monitoring ile publish

%99 oranında live issue’da azalma

Yüksek kod kalitesi

Daha fazla yeni özellik üretimi

O kadar fazla vaktimiz arttı ki kalan vakitlerde işten hariç aykırı bir şekilde hobi projeleri bile geliştiriyoruz. Hatta bunları open source olarak açma gibi bir planımız bile var. Daha fazla otomasyon ile onları da yaparız, neden olmasın?

Neler öğrendik?

Test yazmak her zaman en önemli öncelik olmalı devops olsun olması, zaten olmadan olmuyormuş. Pair programming yapmadan kaliteden söz edilmiyormuş. Test olmadan mimari değiştirilmiyormuş. Mimari hatalı olunca test de yazılmıyormuş :) Devops kelimesi tek başına anlam ifade etmiyormuş. Doğru araçlar olmadan hiç birşey yapılamıyormuş.

Neler kullandık?

Jenkins, Sonarqube, ElasticSearch, Kibana, New Relic, Msbuild, Msdeploy, xunit 2, dotCover, Postman, SOAPUI, dotMemory, Nuget repo, Powershell, MySql, AWS, fxcop, eslint, resharper, JIRA, OneNote, Trello, Bitbucket, Webhook, Slack, email providers, IFFFT

Peki burada bıraktık mı? Hayır tabiki! Devops’ta yeni hedeflerimiz sadece ana projeyi değil, tüm projelerin ortalama %80 code coverage’ı yakalaması, sistemin tamamına smoke test ve UI testleri odaklarıyla çalışıyoruz. Bunlardan sonra belki gerçekten continuous delivery’den deployment’a geçebilir ne dersiniz?

Yazılarımızı takipte kalın, bahsettiğim tüm konular özellinde in-depth blog yazıları yolda!

--

--

Orhun Begendi
hesapkurdu-development

Senior Enginner, Tech Lead, Hardcore Developer, Software Craftsman.