Ölçeklendirme Scala: Kubernetes Kullanarak Nasıl Dockerize Edilir
Yayınlanan: 2022-03-11Kubernetes, uygulamaları buluta dağıtmaya ve daha hızlı ölçeklendirmeye yardımcı olmayı vaat eden bloktaki yeni çocuktur. Bugün, bir mikro hizmet mimarisi için geliştirme yaparken, API sunucuları oluşturmak için Scala'yı seçmek oldukça standart.
Planlarınızda bir Scala uygulaması varsa ve bunu bir buluta ölçeklendirmek istiyorsanız doğru yerdesiniz. Bu makalede, genel bir Scala uygulamasının nasıl alınacağını ve uygulamanın birden çok örneğini başlatmak için Kubernetes'in Docker ile nasıl uygulanacağını adım adım göstereceğim. Nihai sonuç, birden çok örnek olarak dağıtılan tek bir uygulama ve Kubernetes tarafından yük dengeleme olacaktır.
Tüm bunlar, Scala uygulamanıza Kubernetes kaynak kitini içe aktararak uygulanacaktır. Lütfen kitin kurulum ve konfigürasyonla ilgili birçok karmaşık ayrıntıyı gizlediğini unutmayın, ancak ne yaptığını analiz etmek istiyorsanız okunabilir ve anlaşılması kolay olacak kadar küçüktür. Basit olması için her şeyi yerel makinenize dağıtacağız. Ancak aynı yapılandırma, Kubernetes'in gerçek dünyadaki bulut dağıtımı için uygundur.
Kubernetes nedir?
Uygulamanın kanlı ayrıntılarına girmeden önce, Kubernetes'in ne olduğunu ve neden önemli olduğunu tartışalım.
Docker'ı zaten duymuş olabilirsiniz. Bir anlamda, hafif bir sanal makinedir.
Bu nedenlerden dolayı, bulutlarda uygulamaları dağıtmak için daha yaygın olarak kullanılan araçlardan biridir. Bir Docker görüntüsünün oluşturulması oldukça kolay ve hızlıdır ve çoğaltılabilir, VMWare, VirtualBox veya XEN gibi geleneksel bir sanal makineden çok daha kolaydır.
Kubernetes, Docker'ı tamamlar ve dockerize uygulamaları yönetmek için eksiksiz bir ortam sunar. Kubernetes kullanarak yüzlerce hatta binlerce Docker uygulamasını kolayca dağıtabilir, yapılandırabilir, düzenleyebilir, yönetebilir ve izleyebilirsiniz.
Kubernetes, Google tarafından geliştirilen ve diğer birçok satıcı tarafından benimsenen açık kaynaklı bir araçtır. Kubernetes, Google bulut platformunda yerel olarak mevcuttur, ancak diğer satıcılar bunu OpenShift bulut hizmetleri için de benimsemiştir. Amazon AWS, Microsoft Azure, RedHat OpenShift ve hatta daha fazla bulut teknolojisinde bulunabilir. Bulut uygulamalarını dağıtmak için bir standart haline gelmek için iyi bir konumda olduğunu söyleyebiliriz.
Önkoşullar
Artık temel konuları ele aldığımıza göre, önkoşul olan tüm yazılımların kurulu olup olmadığını kontrol edelim. Her şeyden önce, Docker'a ihtiyacınız var. Windows veya Mac kullanıyorsanız Docker Araç Kutusu'na ihtiyacınız vardır. Linux kullanıyorsanız, dağıtımınız tarafından sağlanan belirli paketi yüklemeniz veya yalnızca resmi yönergeleri izlemeniz gerekir.
JVM dili olan Scala ile kodlama yapacağız. Elbette, Java Development Kit'e ve global yolda kurulu ve mevcut olan scala SBT aracına ihtiyacınız var. Halihazırda bir Scala programcısıysanız, bu araçların zaten kurulu olma ihtimali vardır.
Windows veya Mac kullanıyorsanız, Docker varsayılan olarak yalnızca 1 GB belleğe sahip default
adlı bir sanal makine oluşturur; bu, Kubernetes'i çalıştırmak için çok küçük olabilir. Deneyimlerime göre, varsayılan ayarlarla ilgili sorunlar yaşadım. VirtualBox GUI'sini açmanızı, sanal makine default
seçmenizi ve belleği en az 2048MB olarak değiştirmenizi öneririm.
Kümeleme Uygulaması
Bu eğitimdeki talimatlar, herhangi bir Scala uygulamasına veya projesine uygulanabilir. Bu makalede üzerinde çalışılacak bir miktar "et" olması için, Scala'da Akka HTTP adı verilen basit bir REST mikro hizmetini göstermek için çok sık kullanılan bir örnek seçtim. Kaynak kiti uygulamanızda kullanmayı denemeden önce önerilen örneğe uygulamayı denemenizi tavsiye ederim. Kiti demo uygulamasına karşı test ettim, ancak kodunuzla herhangi bir çakışma olmayacağını garanti edemem.
İlk önce demo uygulamasını klonlayarak başlıyoruz:
git clone https://github.com/theiterators/akka-http-microservice
Ardından, her şeyin doğru çalışıp çalışmadığını test edin:
cd akka-http-microservice sbt run
Ardından, http://localhost:9000/ip/8.8.8.8
erişin ve aşağıdaki resimdeki gibi bir şey görmelisiniz:
Kaynak Kiti Ekleme
Şimdi, kaynak kiti biraz Git büyüsü ile ekleyebiliriz:
git remote add ScalaGoodies https://github.com/sciabarra/ScalaGoodies git fetch --all git merge ScalaGoodies/kubernetes
Bununla, kaynak kiti içeren demoya sahip olursunuz ve denemeye hazırsınız. Veya kodu oradan kopyalayıp uygulamanıza yapıştırabilirsiniz.
Projelerinizdeki dosyaları birleştirdikten veya kopyaladıktan sonra başlamaya hazırsınız.
Kubernetes'i Başlatma
Kiti indirdikten sonra, aşağıdakileri çalıştırarak gerekli kubectl
ikili dosyasını indirmemiz gerekiyor:
bin/install.sh
Bu yükleyici, sisteminize bağlı olarak OSX, Linux veya Windows için doğru kubectl
ikili dosyasını indirecek kadar akıllıdır (umarım). Yükleyicinin sahip olduğum sistemlerde çalıştığını unutmayın. Kiti düzeltebilmem için lütfen sorunları bildirin.
kubectl
ikili dosyasını yükledikten sonra, tüm Kubernetes'i yerel Docker'ınızda başlatabilirsiniz. Sadece koş:
bin/start-local-kube.sh
İlk çalıştırıldığında, bu komut tüm Kubernetes yığınının görüntülerini ve görüntülerinizi depolamak için gereken yerel bir kayıt defterini indirecektir. Biraz zaman alabilir, bu yüzden lütfen sabırlı olun. Ayrıca, internete doğrudan erişime ihtiyacı olduğunu unutmayın. Bir proxy arkasındaysanız, kit proxy'leri desteklemediğinden sorun olacaktır. Bunu çözmek için, proxy'yi kullanmak için Docker, curl ve benzeri araçları yapılandırmanız gerekir. Geçici olarak sınırsız erişim almanızı önerecek kadar karmaşık.
Her şeyi başarıyla indirebildiğinizi varsayarak Kubernetes'in düzgün çalışıp çalışmadığını kontrol etmek için aşağıdaki komutu yazabilirsiniz:
bin/kubectl get nodes
Beklenen cevap şudur:
NAME STATUS AGE 127.0.0.1 Ready 2m
Yaşın elbette değişebileceğini unutmayın. Ayrıca, Kubernetes'i başlatmak biraz zaman alabileceğinden, cevabı görmeden önce komutu birkaç kez çağırmanız gerekebilir. Burada hata almıyorsanız, tebrikler, yerel makinenizde Kubernetes kurulu ve çalışıyor demektir.
Scala Uygulamanızı Dockerize Etme
Artık Kubernetes'iniz hazır ve çalışır durumda olduğuna göre, uygulamanızı bunun içinde dağıtabilirsiniz. Eski günlerde, Docker'dan önce, uygulamanızı çalıştırmak için tüm sunucuyu dağıtmanız gerekiyordu. Kubernetes ile uygulamanızı dağıtmak için yapmanız gereken tek şey:
- Bir Docker görüntüsü oluşturun.
- Başlatılabileceği bir kayıt defterine itin.
- Görüntüyü kayıt defterinden alacak olan Kubernetes ile örneği başlatın.
Neyse ki, özellikle de birçok kişinin yaptığı gibi SBT oluşturma aracını kullanıyorsanız, göründüğünden çok daha az karmaşıktır.
Kitte, Scala uygulamalarını çalıştırabilen bir görüntü oluşturmak için gerekli tüm tanımları veya en azından Akka HTTP demosunu çalıştırmak için gerekenleri içeren iki dosya ekledim. Diğer Scala uygulamalarıyla çalışacağını garanti edemem, ancak bu iyi bir başlangıç noktasıdır ve birçok farklı konfigürasyon için çalışması gerekir. Docker görüntüsünü oluşturmak için aranacak dosyalar şunlardır:
docker.sbt project/docker.sbt
Gelin içlerinde neler var bir göz atalım. project/docker.sbt
dosyası, sbt-docker
eklentisini içe aktarma komutunu içerir:
addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.4.0")
Bu eklenti, sizin için SBT ile Docker görüntüsünün oluşturulmasını yönetir. Docker tanımı docker.sbt
dosyasındadır ve şöyle görünür:
imageNames in docker := Seq(ImageName("localhost:5000/akkahttp:latest")) dockerfile in docker := { val jarFile: File = sbt.Keys.`package`.in(Compile, packageBin).value val classpath = (managedClasspath in Compile).value val mainclass = mainClass.in(Compile, packageBin).value.getOrElse(sys.error("Expected exactly one main class")) val jarTarget = s"/app/${jarFile.getName}" val classpathString = classpath.files.map("/app/" + _.getName) .mkString(":") + ":" + jarTarget new Dockerfile { from("anapsix/alpine-java:8") add(classpath.files, "/app/") add(jarFile, jarTarget) entryPoint("java", "-cp", classpathString, mainclass) } }
Bu dosyanın anlamını tam olarak anlamak için Docker'ı bu tanım dosyasını anlayacak kadar iyi bilmeniz gerekir. Ancak, Docker tanım dosyasının ayrıntılarına girmiyoruz çünkü görüntüyü oluşturmak için onu tam olarak anlamanıza gerek yok.

SBT sizin için tüm dosyaları toplayacaktır.
Sınıf yolunun aşağıdaki komut tarafından otomatik olarak oluşturulduğunu unutmayın:
val classpath = (managedClasspath in Compile).value
Genel olarak, bir uygulamayı çalıştırmak için tüm JAR dosyalarını toplamak oldukça karmaşıktır. SBT kullanılarak, Docker dosyası add(classpath.files, "/app/")
ile oluşturulacaktır. Bu şekilde, SBT sizin için tüm JAR dosyalarını toplar ve uygulamanızı çalıştırmak için bir Dockerfile oluşturur.
Diğer komutlar, bir Docker görüntüsü oluşturmak için eksik parçaları toplar. Görüntü, Java programlarını çalıştırmak için mevcut bir görüntü APT kullanılarak oluşturulacaktır ( anapsix/alpine-java:8
, internette Docker Hub'da mevcuttur). Diğer talimatlar, uygulamanızı çalıştırmak için diğer dosyaları ekliyor. Son olarak bir giriş noktası belirleyerek çalıştırabiliriz. Ayrıca adın bilerek localhost:5000
ile başladığını unutmayın, çünkü localhost:5000
, start-kube-local.sh
komut dosyasında kayıt defterini kurduğum yerdir.
SBT ile Docker Görüntüsü Oluşturma
Docker görüntüsünü oluşturmak için Dockerfile'ın tüm ayrıntılarını yok sayabilirsiniz. Sadece şunu yazmanız gerekiyor:
sbt dockerBuildAndPush
sbt-docker
eklentisi daha sonra sizin için bir Docker görüntüsü oluşturacak, gerekli tüm parçaları internetten indirecek ve ardından localhost
Kubernetes uygulamasıyla birlikte daha önce başlatılan bir Docker kayıt defterine itecektir. Yani tek ihtiyacınız olan şey, resminizin pişmesi ve hazır olması için biraz daha beklemek.
Sorun yaşarsanız, yapılacak en iyi şeyin aşağıdaki komutları çalıştırarak her şeyi bilinen bir duruma sıfırlamak olduğunu unutmayın:
bin/stop-kube-local.sh bin/start-kube-local.sh
Bu komutlar tüm kapsayıcıları durdurmalı ve kayıt defterinizi sbt
tarafından oluşturulan ve gönderilen görüntüyü almaya hazır hale getirmek için doğru şekilde yeniden başlatmalıdır.
Kubernetes'te Hizmeti Başlatma
Artık uygulama bir kapsayıcıda paketlendiğine ve bir kayıt defterine gönderildiğine göre, onu kullanmaya hazırız. Kubernetes, kümeyi yönetmek için komut satırını ve yapılandırma dosyalarını kullanır. Komut satırları çok uzun olabileceğinden ve aynı zamanda adımları tekrarlayabildiğinden, burada konfigürasyon dosyalarını kullanıyorum. Kaynak kitteki tüm örnekler kube
klasöründedir.
Bir sonraki adımımız görüntünün tek bir örneğini başlatmak. Çalışan bir görüntü, Kubernetes dilinde pod olarak adlandırılır. Şimdi aşağıdaki komutu çağırarak bir pod oluşturalım:
bin/kubectl create -f kube/akkahttp-pod.yml
Şimdi durumu şu komutla inceleyebilirsiniz:
bin/kubectl get pods
Görmelisin:
NAME READY STATUS RESTARTS AGE akkahttp 1/1 Running 0 33s k8s-etcd-127.0.0.1 1/1 Running 0 7d k8s-master-127.0.0.1 4/4 Running 0 7d k8s-proxy-127.0.0.1 1/1 Running 0 7d
Durum aslında farklı olabilir, örneğin “ContainerCreating”, “Çalışıyor” haline gelmesi birkaç saniye alabilir. Ayrıca, örneğin görüntüyü daha önce oluşturmayı unutursanız, “Hata” gibi başka bir durum alabilirsiniz.
Ayrıca, pod'unuzun çalışıp çalışmadığını şu komutla da kontrol edebilirsiniz:
bin/kubectl logs akkahttp
Bunun gibi bir şeyle biten bir çıktı görmelisiniz:
[DEBUG] [05/30/2016 12:19:53.133] [default-akka.actor.default-dispatcher-5] [akka://default/system/IO-TCP/selectors/$a/0] Successfully bound to /0:0:0:0:0:0:0:0:9000
Artık hizmetiniz var ve konteynerin içinde çalışıyor. Ancak servise henüz ulaşılamıyor. Bu davranış, Kubernetes tasarımının bir parçasıdır. Pod'unuz çalışıyor, ancak onu açıkça göstermelisiniz. Aksi takdirde, hizmetin dahili olması gerekir.
Hizmet Oluşturma
Bir hizmet oluşturmak ve sonucu kontrol etmek, yürütme meselesidir:
bin/kubectl create -f kube/akkahttp-service.yaml bin/kubectl get svc
Bunun gibi bir şey görmelisiniz:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE akkahttp-service 10.0.0.54 9000/TCP 44s kubernetes 10.0.0.1 <none> 443/TCP 3m
Bağlantı noktasının farklı olabileceğini unutmayın. Kubernetes, hizmet için bir bağlantı noktası ayırdı ve başlattı. Linux kullanıyorsanız, doğrudan tarayıcıyı açıp sonucu görmek için http://10.0.0.54:9000/ip/8.8.8.8
yazabilirsiniz. Docker Toolbox ile Windows veya Mac kullanıyorsanız IP, Docker çalıştıran sanal makinede yereldir ve ne yazık ki hala erişilemez.
Burada bunun bir Kubernetes sorunu olmadığını, bunun yerine VirtualBox gibi başka bir bilgisayar içinde bir bilgisayar gibi davranan sanal makinelerin dayattığı kısıtlamalara bağlı olan Docker Toolbox'ın bir sınırlaması olduğunu vurgulamak istiyorum. Bu sınırlamayı aşmak için bir tünel oluşturmamız gerekiyor. İşleri kolaylaştırmak için, dağıttığımız herhangi bir hizmete ulaşmak için rastgele bir bağlantı noktasında bir tünel açan başka bir komut dosyası ekledim. Aşağıdaki komutu yazabilirsiniz:
bin/forward-kube-local.sh akkahttp-service 9000
Tünelin arka planda çalışmayacağını unutmayın, terminal penceresini ihtiyacınız olduğu sürece açık tutmanız ve artık tünele ihtiyacınız olmadığında kapatmanız gerekir. Tünel çalışırken, http://localhost:9000/ip/8.8.8.8
açabilir ve son olarak Kubernetes'te çalışan uygulamayı görebilirsiniz.
Son Dokunuş: Ölçek
Şimdiye kadar uygulamamızı Kubernetes'e “basitçe” koyduk. Heyecan verici bir başarı olsa da, dağıtımımıza çok fazla değer katmaz. Bir sunucuya yükleme ve yükleme ve bunun için bir proxy sunucusu yapılandırma çabasından kurtulduk.
Kubernetes'in parladığı yer ölçeklendirmedir. Yalnızca yapılandırma dosyasındaki kopya sayısını değiştirerek uygulamamızın iki, on veya yüz örneğini dağıtabilirsiniz. Öyleyse hadi yapalım.
Tek bölmeyi durduracağız ve bunun yerine bir dağıtım başlatacağız. O halde aşağıdaki komutları uygulayalım:
bin/kubectl delete -f kube/akkahttp-pod.yml bin/kubectl create -f kube/akkahttp-deploy.yaml
Ardından, durumu kontrol edin. Yine, dağıtımın gerçekleştirilmesi biraz zaman alabileceğinden birkaç kez deneyebilirsiniz:
NAME READY STATUS RESTARTS AGE akkahttp-deployment-4229989632-mjp6u 1/1 Running 0 16s akkahttp-deployment-4229989632-s822x 1/1 Running 0 16s k8s-etcd-127.0.0.1 1/1 Running 0 6d k8s-master-127.0.0.1 4/4 Running 0 6d k8s-proxy-127.0.0.1 1/1 Running 0 6d
Şimdi bir değil iki kapsülümüz var. Bunun nedeni, sağladığım yapılandırma dosyasında, sistem tarafından oluşturulan iki farklı adla replica: 2
değerinin bulunmasıdır. Yapılandırma dosyalarının ayrıntılarına girmiyorum, çünkü makalenin kapsamı, Scala programcılarının Kubernetes'e hızlı bir şekilde başlaması için bir giriş niteliğindedir.
Her neyse, şu anda aktif olan iki bölme var. İlginç olan, hizmetin öncekiyle aynı olmasıdır. Hizmeti, akkahttp
etiketli tüm bölmeler arasında yük dengesi oluşturacak şekilde yapılandırdık. Bu, hizmeti yeniden dağıtmamız gerekmediği, ancak tek örneği çoğaltılmış bir örnekle değiştirebileceğimiz anlamına gelir.
Proxy'yi yeniden başlatarak bunu doğrulayabiliriz (Windows kullanıyorsanız ve onu kapattıysanız):
bin/forward-kube-local.sh akkahttp-service 9000
Ardından, iki terminal penceresi açmayı deneyebilir ve her bölme için günlükleri görebiliriz. Örneğin, ilk türde:
bin/kubectl logs -f akkahttp-deployment-4229989632-mjp6u
Ve ikinci tipte:
bin/kubectl logs -f akkahttp-deployment-4229989632-s822x
Elbette komut satırını sisteminizde bulunan değerlere göre düzenleyin.
Şimdi servise iki farklı tarayıcı ile erişmeyi deneyin. Aşağıdaki resimde olduğu gibi, birden çok kullanılabilir sunucu arasında bölünecek istekleri görmeyi beklemelisiniz:
Çözüm
Bugün yüzeyi zar zor çizdik. Kubernetes, otomatik ölçekleme ve yeniden başlatma, artımlı dağıtımlar ve birimler dahil olmak üzere çok daha fazla olanak sunar. Ayrıca örnek olarak kullandığımız uygulama çok basit, vatansız ve çeşitli örneklerin birbirini tanımasına gerek yok. Gerçek dünyada, dağıtılmış uygulamaların birbirini tanıması ve diğer sunucuların kullanılabilirliğine göre yapılandırmaları değiştirmesi gerekir. Aslında Kubernetes, yeni örnekler dağıtıldığında farklı uygulamaların birbirleriyle iletişim kurmasına izin vermek için dağıtılmış bir anahtar deposu ( etcd
) sunar. Ancak bu örnek, temel işlevlere odaklanarak başlamanıza yardımcı olacak kadar küçük ve basitleştirilmiştir. Öğreticiyi takip ederseniz, çok sayıda ayrıntıyla kafanız karışmadan ve karmaşıklık içinde kaybolmadan makinenizde Scala uygulamanız için bir çalışma ortamı elde edebilmelisiniz.
- Bulutta Bulut için Geliştirme: AWS'de Docker ile Büyük Veri Geliştirme
- K8'ler/Kubernetes: AWS ve GCP ve Azure
- Bir Kubernetes Hizmet Ağı Karşılaştırması