K8s FullStack(Spring Boot — Nodejs)Deploy Hands-On
Merhaba github adresimde bulunan TodoApp uygulamamızı dockerize etmiştik. Buradan o yazıma ulaşabilirsiniz.
Şimdi ise TodoApp uygulamamızı localde geliştirmelerimizi/testlerimizi yaparken kullanmamızı sağlayan minikube ile dağıtacağız.
Aws üzerinde tek ec2 instance üzerine kurup uygulamamı dağıtacağım, aynı işlemleri sanal sunucuda digitalocean’da da yaparak takip edebilirsiniz. Fakat localde de rahatlıkla yapabilirsiniz :)
Local için buradaki adımları takip edebilirsiniz, tabii ki docker önceden kurulu olduğunu varsayıyorum :)
Aws EC2 Minikube Kurulumu
AMI: Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
Type: t3.xlarge (4 CPU, 16GB Memory)
Tags:
- Key: Name
- Value: K8s
Security Group : SSH, 0.0.0.0/0 Custom & All Traffic Anywhere
Şeklinde ec2 instance oluşturuyoruz.
Windows makineden bağlanmak için MobaXterm baya kullanışlı.
Adımlarını yaptıktan sonra minikube hazır olacak,
Test için kubectl get all komutunu kullanabiliriz.
Şimdi TodoApp uygulamamızı clone yapıyoruz.
MySQL Deploy
ilk önce backend uygulamamız için veritabanı ayarlarını yapmamız gerekmektedir
Burada yapmamız gereken PersistentVolumeClaim(pvc) ve PersistentVolume(pv) oluşturmak.
PersistentVolume,
- PersistentVolume(pv), cluster’daki bir depolama parçasıdır.
- Kalıcı volume lifecycle, Pod lifecycle’dan bağımsızdır.
- Pod’ların yeniden başlatılmasında, crash olmasında veri kaybını korur.
PersistentVolumeClaim,
- PersistentVolume, PersistentVolumeClaim(pvc) tarafından kullanılır.
- PersistentVolume depolaması istemek için bir PersistentVolueClaim oluştururuz.
- PVC’ler belirli bir boyut ve erişim modları ister.
- ReadWriteOnce, birimin tek bir node tarafından okuma yazma olarak mount edilebileceği anlamına gelir.
- pvc ve pv bire bir eşleşmesi gerekir, bu yüzden pv 10 gb kullanıyorsa, pvc 3gb kullanıyorsa. pvc kapasitesi 10 gb’dır.)
- storageClassName ile pvc-pv bağlantısı kurulur.
pvc ve pv hakkında daha fazla bilgi için K8s Persistence Volumes Nedir? inceleyip örneklere bakabilirsiniz.
Deployment,
- Uygulamalarımızı bir cluster üzerinde dağıtabilmek için deployment yapılandırmasına ihtiyacımız vardır.
- Uygulamalarımızın instance’larını nasıl oluşturacağımızı ve güncelleyeceğimizi bildirmektedir. (docker image seçimi vs..)
Service,
- Deployment ile oluşturduğumuz pod’lara erişmek için bir ilke tanımlar.
- Service tarafından hedeflenen pod’lar kümesi LabalSelector ile belirlenir.
- Service bir dizi pod için trafiği yönlendirir ve uygulamayı etkilemeden k8'lerde ölmesine ve çoğalmasına izin verir.(service’ler pod’ları ortak bir port üzerinden expose eder.) Böylece eğer bir node/port çalışmıyorsa bu alanları dahili olarak yeniden oluşturuyorsa uygulama zarar görmez.
- Unique IP adresleri bir service ile dış cluster’a maruz kalmaz. ServiceSpec içerisinde bir tür belirtilerek hizmetler farklı şekillerde verilebilir.(ClusterIP, NodePort, LoadBalancer, ExternalName)
Deployment ve Service hakkında daha fazla bilgi için K8s Deployment Nedir? ve K8s Service Nedir? inceleyip örneklere bakabilirsiniz.
Şimdi de MySQL Deployment ve Service işlemlerine bakalım,
Deployment alanında,
- metadata name alanı deployment’ımız için verdiğimiz isimdir. (pod ismi.)
- label için verdiğimiz isim service ile dışarıya mysql’i açtığımızda pod ile matchleşmesi içindir.
- spec container içerisinde gördüğünüz üzere mysql:5.7 image’i dockerHub’dan çekmektedir.
- env içerisinde MySQL env’ları veriyoruz fakat burada en önemli şey şifre ve password’ı direkt içerisine vermiyoruz sadece value-key veriyoruz.(bunun için kubectl create secret komutu kullanacağız uygulamamızı ayağa kaldırırken.)
- VolumeMounts ile verilerimiz pod crash olduğunda kaybolmaması için bir yer veriyoruz.
Service alanında ise,
- metada name ile Service’in ismini belirliyoruz. Bu isimler şu yüzden önemli, spring boot uygulamamızdan service’e erişmek için bu ismi kullanacağız. (Örn: jdbc:mysql://todo-app-mysql:3306)
- Selector ile deployment’a verdiğimiz ismi veriyoruz.
- Type değerini ClusterIP yaptık çünkü veritabanı içeride kullanılacak bir uygulamadır dışarıdan başkalarının veritabanına erişmesini istemiyoruz.
Spring Boot(api) Deployment
Deployment alanında,
- MySQL Deployment ve Service ile çok benzerlik göstermektedir.
- Aslında 1 tanede olsa 1000 tane de configlerimiz çok benzerdir.
- Burada fark spec içerisinde replicas gelmektedir. Bunu veritabanında da yapabilirdik.
- Replicas ile eğer pod’lardan biri crash olursa bir diğeri ayakta olarak bağlantı kesilmesini önlemektedir. Aynı zamanda loadbalance ile de gelen trafiği yönetebilmek için kullanılmaktadır.
- Selector matchLabels ve metadata labels isimleri ikisinde de api olduğunu göreceğiz çünkü replicaset’im ve pod’larım birbirlerini tanıyabilsin diye aynı isimlendirmeyi yapmaktayız.
- env ‘da api uygulamasında bulunan application-product.properties içerisinde veritabanı bilgilerini parametre olarak aldığımı göreceksiniz. Bu parametleri burada veriyoruz.
Service alanında ise,
- Selector ile pod’umuzu seçiyoruz.(Pod’umuzda bulunan metadata bilgileri ile aynı olmalı ki service pod’a erişebilsin.)
- port bilgilerini giriyoruz.
- api’mize sadece ui erişeceği için ClusterIP yapıyoruz.
Ui Deployment
Deployment alanında,
- pod ismini ui yapıyoruz.
- Uygulama içerisinde product env çalışmasını istediğim için env olarak veriyorum.
Service alanında,
- Selector ile pod ismini seçiyorum.
- Type NodePort yapıyorum ve dışarıdan erişilmesi için bir nodePort veriyorum. NodePort ile ui’a dışarıdan erişilebilecektir.
- Böylelikle dışarıdan 31000 portuna gelen istek içeride 8082 portuna yönlendirilecek.
Full Deploy and Test
Projemizi önceden oluşturduğumuz ec2 instance’a clone yapmıştık.
Şimdi k8s klasörü içerisine girelim.
- Hatırlarsanız MySQL yaml dosyasını oluştururken bazı secretKeyRef’ler vermiştik.
- Veritabanı kimlik bilgilerini saklamak için K8s secret kullanıyoruz.
- Secret, K8s parolaları, token, ssh key gibi bilgileri saklayıp yönetmemizi sağlamaktadır.
Bu secretKey’leri manuel olarak oluşturuyoruz.
Bu komutları yazalım ve böylelikle oluşacak veritabanımız için url, username, password bilgilerini oluşturmuş oluyoruz.
Aşağıdaki komut ile k8s klasörü içerisinde bulunan tüm yaml dosyaları çalıştırılır.
kubectl apply -f .
Bu işlemi yaptıktan sonra ekran görüntüsü aşağıdaki gibi olacaktır,
Aşağıdaki komut ile tüm pod,service,replicaset, deployment’ları listeleyelim.
kubectl get all
Gördüğümüz gibi tüm sistem ayağa kalktı.
api için replicaset 2 vermiştik ve bu yüzden 2 tane pod ayağa kalktı.
İlk önce ec2 publicip:31000 adresine girelim ve ui’ın açıldığını görelim.
Şimdi de pod içerisinde log’lar nasıl izlenir ona bakalım,
kubectl logs -f <podName>
Bu işlemi yaptıktan sonra ui’dan CREATE ACCOUNT deyip bir kayıt oluşturalım.
Daha sonra logları görüntülediğimizde,
Burada gözümüze çarpan şey api-service:8080 olabilir bildiğimiz gibi api.yaml oluştururken service metadata name olarak vermiştik. Böylelikle ip’ler değişken olabileceği için service name kullanışlı olmaktadır.
Son olarak api’mizin log’una bakalım.
ve uygulamamızı minikube üzerinde dağıtmış olduk.
Başka yazılarda görüşmek üzere :)