Kubernetes Microservice Deployment(.Net Core)
.Net Core 3.1 Swagger & Mysql Database Uygulama Örneği
Merhabalar,
Bu yazımda .Net core 3.1 ile yazılmış basit bir microservice Kubernetes deploy etmeyi inceliycez.
İlk olarak microservis nedir buna bakalım.
Mikroservis sadece bir işi yapan, bir fonksiyonaliteyi gerçekleştiren çok küçük kod parçacıkları. Geliştirme süreçleri, bağımlılıkları, boyutları olabildiğince küçük olan atomik servislerdir diyebiliriz.
Not: Eğer siz bu örneği minikube üzerinde gerçekleştirmek isterseniz minikube ‘addons’ ile ‘ingress’ yüklemelisiniz.
Örneği gerçekleştirceğim Single Clusterım şekildeki gibidir.
Kubernetes Deploy edeceğimiz proje .Net Core 3.1 ile geliştirilmiştir. Projenin dosya yapısına bakacak olursak.
İlk olarak dockerfile bakalım.
Not: Database işlemlerinde genelde migrations kullanılır. Birden fazla tablo olduğunda bu tabloları tek tek girmek ayrı bir iş yüküdür. Bizim örneğimizde tek bir tablo olduğu için kubernetes podunu exec ile bağlanıp kendimiz oluşturmayı öğrencez.
Şimdide dockerfile dosyamızdan image alıp tagleyip kendi gitlabımdaki projenin bulunduğu alandaki container registry alanına gönderelim. Bunun için;
docker image build — tag registry.gitlab.com/deniz.turkmen/netcoreswagger/netcoreswaggerui_swagger .docker push registry.gitlab.com/deniz.turkmen/netcoreswagger/netcoreswaggerui_swagger
Container registry alanımıza image’ımıza göndermiş bulunmaktayız. Bakacak olursak aşağıdaki şekilde gözüktüğü gibidir.
Şimdide uygulamamızı Kubernetes Deploy edelim. İlk olarak bir tane namespace oluşturarak başlayalım.
“kubectl apply -f namespace.yaml” komutu ile namespace oluşturalım ve “kubectl get namespace” komutu ile de clusterrımızda bulunan namespaceleri listeleyelim.
Görüldüğü gibi namespace oluşturuldu.
Şimdi de container registry alanından image çekmek için secret oluşturalım. Bunun için dilerseniz detaylı öğrenmek için diğer yazımı okuyabilirsiz, çünkü ilk olarak gitlabı secret olarak localinize tanıtmanız gerekir tanıtmak için yazacağınız komut
kubectl create secret docker-registry regcred /— docker-server=registry.gitlab.com /— docker-username=kullanıcı_adi /— docker-password=şifre -n deniz
Not: Buradaki “-n deniz” bu namespace yaratılması için yazılmıştır.
“Secret.yaml” içeriğine bakacak olursak,
“kubectl apply -f secret.yaml” komutu ile uygulayalım ve “kubectl get secret -n deniz” komutu ile secretimizi listeleyelim.
Bir de secretimizde kubernetes dashbaordumuzdan bakalım.
Şimdi de Mysql yazalım. ilk olarak Podlar bilindiğiniz üzere herhangi bir sıkıntıdan dolayı kendileri restart edebilirler. Dolayısıyla üzerinde tuttukları veriler de gider. Çünkü restart denilen aslında container silinip belirtilen image dan tekrar oluşturulma işlemedir. İşte bizde birden fazla clusterımız olabilceğini göz önüne alarak her bir farklı clusterdan aynı verilere erişebilmesi için “Persistent Volume” ve “Persistent Volume Claims” objesi yaratırız.
Not: emptir ve hostpath gibi volumelerde vardır, fakat bu volumeler üzerlerinde oluşturulan nodelara bağlıdır. Dolayısıyla nodelara herhangi bir nedenden “crash” olduğunda üzerinde tuttukları bilgiler de gider. Bunun önüne geçmek için biz “persisten volume” tanımlıycaz.
Persistent volume objemize göz atalım sonrada “kubeclt apply -f mysqlpervol.yaml” komutu ile oluşturalım ve ardından “kubectl get pv -n deniz” komutu ile bakalım.
Persistent Volume objesinde bilmeniz gereken storage,FileSystem ve accessModes dur.
- storage: olarak 25Gi
- volumeMode: FileSystem
- persistentVolumeReclaimPolicy : 3 tipi vardır.
1- Retain :Cluster silinsede volume mount ettiğiniz klasöre bişey olmaz.(Production ortamında kullanılan ReclaimPolicydir.)
2- Retain: Podlar silindiğinde mount ettiğiniz klasörün içindeki veriler gider ama mount edilen klasör kalır.
3- Delete: Mount edilen klasör veya dizin komple silinir.
Oluşturduktan sonra baktığımızda gördüğünüz gibi oluşmuş ve status “avaible” durumda. Şimdide “Persistent Volume Claims” objesi oluşturarak Persistent volume objemize bağlanmasını sağlayalım. Persistent Volume Claims objemisin içeriğine bakacak olursak.
Burada önemli olan noktalar;
- Oluşturduğumuz ‘Persistent Volume’ objesindeki accesModes ne ise aynı olmak zorunda farklı bir acccesMode verirseniz ‘bound’ yani bağlanmaz. AccessModes olarak 3 farklı tipi vardır.Bunlar
1- ReadWriteOnce: Tek bir node için okuma ve yazma.
2- ReadOnlyMany: Birden fazla node için sadece okuma.
3- ReadWriteMany: Birden fazla node için okuma ve yazma yetkisi.
Not: Burada kastedilen node ve okuma-yazma ile birden fazla podun bi volume geldiğinde nasıl bir davranış izleyeceği ile ilgilidir.
- Em önemlisi ise tabiki de labellar. Biliyorsunuz ki bir objenin diğer obje ile iletişimi “label-selector” ile olur.
“kubectl apply -f mysqlpervolClaims.yaml” komutu ile oluşturalım ve “kubectl get pvc -n deniz” ile de oluşturduğumuz PVClaims objemize bakalım.
Görüldüğü gibi PVClaims objemiz oluştu ve PVolume objemise “bound” oldu.
Şimdide service oluşturalım. İlk olarak service.yaml dosyamıza bir göz atalım.
“kubectl apply -f mysqlservice.yaml” ile oluşturalım ve “kubernetes get svc -n deniz” ile oluşturduğumuz servis objesine bakalım.
Servis objeleri le biz clustırımızdaki bir podu dışarıya açarız.Dört tip servis tipi vardır. Bizim örneğimizde “ClusterIP” tipindededir. Eğer servisimini tipini NodePort yada LoadBalancer olarak belirtseydik ExternalIP alacak ve dışarıdan artık bu ip ve aldığı port ile ulaşabilcektik.
Not: Podumuz oluştuktan sonra Dbeaver ile Mysql database ClusterIP aldığı İp ile bağlantı kuracağız.
Şimdi de podumuzu oluşturcak obje olan deployment objemize bakalım.
Burada bilmeniz gerekenler,
- Secret objesi oluşturmuştuk oradaki değerleri env altında okuyarak alıyoruz.
- Volume olarak mysql /var/lib/mysql containerin içineki mount bizim oluşturdğumuz Persitent Volume bağlıyoruz.
- NodeAffinity ile hangi nodeda çalışmasını istediğimizi yazıyoruz.
“kubectl apply -f mysqlDeployment.yaml” sonrda “kubectl get deployment -n deniz “ ve “kubectl get pods -n deniz -o wide” komutları ile bakıyoruz.
Görüldüğü gibi oluşan podlar bizim istediğimiz gibi “deniz-master” çalışıyor.
Şimdide .Net Core Microservisi deploy edelim. Bu sefer objeleri tek tek değilde hepsini bir anda oluşturalım.
“kubectl apply -f swaggerr.yaml” komutu çalıştıralım.
Görüldüğü gibi tüm objelerimiz oluştu. Deployment objesi biraz açıklamak gerekirse,
- Selectore dikket etmemiz grekiyor.
- Container Registry alanında image çekmek için gerekli ayarları yapmıştır. Burada Image ismi yazıyoruz.
- Secret ile mysql bağlanacağımız için onun bilgileri secret objemizden alıyoruz.
Ingress objesini biraz açıklamak gerekirse,
- host ile tarayıcıdan gideceğimiz adresi tanımlıyoruz. Burada ben nginx ingress kullanıyorum. Annatotions kısmında nginx ingress ayarlıycağımız parametreleri giribilirsiniz.
Not: İngress altığı ip ve host ismini /etc/hosts yazmalıyız. Gördüğünüz gibi hostumuz “web.swagger.com” olarak girilmiş.
Şimdide son olarak clusterımızdaki tüm objeleri listeleyelim. Clusterımızdaki objelerin durumlarına bakalım.
Not: Endpointler bize podların aldığı ipleri gösterir.
Sonrada tarayıcıdan ingress tanımladığımız hosta gidersek,
Yukarıdaki şekilde gördüğünüz gibi database mysql podumuzada veritabanı kurulu olmadığı için hata alıyoruz. Şimdide database kurulumunu yapalım.
Not: Production ortamında çok fazla olacağı için genelde migration ya da dump ile kurulum yapılır.
“kubectl get pods -n deniz” komutu ile podlarımızı listeleyelim.
kubectl exec -it pod_ismi -n namaspace_ismi — bash
Komutu ile podumuza bağlanalım ve “printenv” ile envirmentlarımızı almış mı kontrol edelim.
Şimdi de mysql bağlanarak database ve tabloyu oluşturalım. Bağlanmak için,
mysql -uroot -p
Burada root ile bağlancağımı ve secret objemizdeki “MYSQL_ROOT_PASSWORD” value değeri olan example yazıp giriş yapıyoruz.
Evet giriş tamam şimdi de database ve tablo oluşturalım.
Şimdide oluşturduğumuz database ve tabloya bakalım.
Görüldüğü gibi database ve tablo işlemleri tamam. Tekrar ingress te tanımladığımız hosta gidelim ve GetAll metotunu çalıştıralım.
Bir de create metotunu deneyelim.
Görüldüğü gibi .Net Core 3.1 ile yazdığımız basit microservisi kubernetes deploy etme işlemi gerçekleştirdik.
Bu yazımızın da sonuna gelmiş bulunmaktayız. Araştırmalarım ve sektörde karşılaştığım senaryolar üzerine yazılarımı yazmaya devam edeceğim. Umarım faydalı bir yazı olmuştur. Yazımı okuduğunuz için teşekkürler.
Referanslar;